summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-04-19 14:16:38 +0000
committerGerald Carter <jerry@samba.org>2006-04-19 14:16:38 +0000
commit3269caf5f189e31e8ce43dd8c96c50cb1577a5f0 (patch)
tree97766343da5c19ebc174ff90c5a26fdfb511a8c1
parent160f2a3ea700c763b2e0d7753f393e677c5b8f54 (diff)
parent1478912775330638b9dc6e7129d966168264db1a (diff)
downloadsamba-3269caf5f189e31e8ce43dd8c96c50cb1577a5f0.tar.gz
r15135: working on 3.0.23pre1; sync to SAMBA_3_0 r15132
-rw-r--r--examples/LDAP/samba.schema2
-rw-r--r--examples/VFS/Makefile.in2
-rw-r--r--examples/VFS/skel_opaque.c6
-rw-r--r--examples/VFS/skel_transparent.c6
-rw-r--r--examples/libmsrpc/test/sam/samenum.c2
-rw-r--r--examples/libsmbclient/get_auth_data_fn.h1
-rw-r--r--examples/libsmbclient/testbrowse.c51
-rwxr-xr-xexamples/misc/adssearch.pl1
-rw-r--r--examples/pam_winbind/pam_winbind.conf26
-rw-r--r--examples/pdb/mysql/mysql.dump37
-rw-r--r--examples/pdb/mysql/smb.conf11
-rw-r--r--examples/pdb/sambapdb.dtd46
-rw-r--r--examples/pdb/test.c2
-rw-r--r--examples/perfcounter/perf_writer.c2
-rwxr-xr-xexamples/scripts/shares/perl/modify_samba_config.pl3
-rwxr-xr-xpackaging/Debian/debian-sarge/rules2
-rwxr-xr-xpackaging/Debian/debian-unstable/rules2
-rwxr-xr-xpackaging/Debian/debian-woody/rules2
-rw-r--r--packaging/RHEL/makerpms.sh.tmpl10
-rw-r--r--packaging/RHEL/samba.spec.tmpl2
-rw-r--r--packaging/RedHat-9/samba.spec.tmpl2
-rw-r--r--packaging/Solaris/makepkg.sh4
-rw-r--r--source/Makefile.in407
-rw-r--r--source/VERSION4
-rw-r--r--source/aclocal.m42
-rw-r--r--source/auth/auth.c22
-rw-r--r--source/auth/auth_builtin.c6
-rw-r--r--source/auth/auth_compat.c2
-rw-r--r--source/auth/auth_domain.c45
-rw-r--r--source/auth/auth_ntlmssp.c10
-rw-r--r--source/auth/auth_rhosts.c230
-rw-r--r--source/auth/auth_sam.c78
-rw-r--r--source/auth/auth_script.c10
-rw-r--r--source/auth/auth_server.c16
-rw-r--r--source/auth/auth_unix.c20
-rw-r--r--source/auth/auth_util.c1621
-rw-r--r--source/auth/auth_winbind.c25
-rw-r--r--source/client/client.c96
-rw-r--r--source/client/clitar.c13
-rwxr-xr-xsource/client/mount.cifs.c42
-rw-r--r--source/client/smbctool.c8
-rw-r--r--source/client/smbmount.c2
-rw-r--r--source/client/smbspool.c15
-rw-r--r--source/client/umount.cifs.c16
-rw-r--r--source/configure.in557
-rw-r--r--source/groupdb/mapping.c480
-rw-r--r--source/include/ads.h6
-rw-r--r--source/include/auth.h31
-rw-r--r--source/include/debug.h5
-rw-r--r--source/include/debugparse.h (renamed from source/ubiqx/debugparse.h)2
-rw-r--r--source/include/doserr.h1
-rw-r--r--source/include/event.h31
-rw-r--r--source/include/gpo.h91
-rw-r--r--source/include/hmacmd5.h10
-rw-r--r--source/include/idmap.h4
-rw-r--r--source/include/includes.h90
-rw-r--r--source/include/libmsrpc.h2
-rw-r--r--source/include/libsmb_internal.h12
-rw-r--r--source/include/libsmbclient.h96
-rw-r--r--source/include/local.h11
-rw-r--r--source/include/messages.h3
-rw-r--r--source/include/nameserv.h6
-rw-r--r--source/include/nt_printing.h28
-rw-r--r--source/include/nt_status.h6
-rw-r--r--source/include/ntdomain.h6
-rw-r--r--source/include/ntlmssp.h1
-rw-r--r--source/include/passdb.h344
-rw-r--r--source/include/rpc_dce.h19
-rw-r--r--source/include/rpc_dfs.h532
-rw-r--r--source/include/rpc_lsa.h444
-rw-r--r--source/include/rpc_misc.h15
-rw-r--r--source/include/rpc_netlogon.h106
-rw-r--r--source/include/rpc_samr.h69
-rwxr-xr-xsource/include/rpc_spoolss.h55
-rw-r--r--source/include/secrets.h6
-rw-r--r--source/include/smb.h385
-rw-r--r--source/include/smb_macros.h18
-rw-r--r--source/include/smbldap.h22
-rw-r--r--source/include/smbprofile.h2
-rw-r--r--source/include/trans2.h26
-rw-r--r--source/include/vfs.h10
-rw-r--r--source/include/vfs_macros.h3
-rw-r--r--source/iniparser/AUTHORS1
-rw-r--r--source/iniparser/INSTALL12
-rw-r--r--source/iniparser/LICENSE21
-rw-r--r--source/iniparser/Makefile55
-rw-r--r--source/iniparser/README11
-rw-r--r--source/iniparser/html/dir_000000.html27
-rw-r--r--source/iniparser/html/dirs.html19
-rw-r--r--source/iniparser/html/doxygen.css309
-rw-r--r--source/iniparser/html/doxygen.pngbin0 -> 1281 bytes
-rw-r--r--source/iniparser/html/globals_func.html35
-rw-r--r--source/iniparser/html/index.html148
-rw-r--r--source/iniparser/html/iniparser_8h.html737
-rw-r--r--source/iniparser/html/iniparser_8main.html19
-rw-r--r--source/iniparser/src/dictionary.c508
-rw-r--r--source/iniparser/src/dictionary.h244
-rw-r--r--source/iniparser/src/iniparser.c517
-rw-r--r--source/iniparser/src/iniparser.h282
-rw-r--r--source/iniparser/src/strlib.c211
-rw-r--r--source/iniparser/src/strlib.h108
-rw-r--r--source/iniparser/test/Makefile24
-rw-r--r--source/iniparser/test/iniexample.c117
-rw-r--r--source/intl/lang_tdb.c7
-rw-r--r--source/lib/account_pol.c9
-rw-r--r--source/lib/audit.c149
-rw-r--r--source/lib/charcnv.c51
-rw-r--r--source/lib/debug.c39
-rw-r--r--source/lib/display_sec.c (renamed from source/rpcclient/display_sec.c)44
-rw-r--r--source/lib/dummysmbd.c9
-rw-r--r--source/lib/events.c121
-rw-r--r--source/lib/fault.c97
-rw-r--r--source/lib/gencache.c22
-rw-r--r--source/lib/genrand.c4
-rw-r--r--source/lib/hmacmd5.c25
-rw-r--r--source/lib/ldap_escape.c7
-rw-r--r--source/lib/messages.c33
-rw-r--r--source/lib/pam_errors.c1
-rw-r--r--source/lib/pidfile.c6
-rw-r--r--source/lib/privileges.c20
-rw-r--r--source/lib/readline.c4
-rw-r--r--source/lib/repdir.c218
-rw-r--r--source/lib/secace.c8
-rw-r--r--source/lib/secdesc.c24
-rw-r--r--source/lib/sendfile.c1
-rw-r--r--source/lib/sharesec.c308
-rw-r--r--source/lib/smbldap.c275
-rw-r--r--source/lib/smbldap_util.c121
-rw-r--r--source/lib/smbrun.c18
-rw-r--r--source/lib/snprintf.c759
-rw-r--r--source/lib/socket_wrapper.c373
-rw-r--r--source/lib/substitute.c490
-rw-r--r--source/lib/sysacls.c11
-rw-r--r--source/lib/sysquotas.c76
-rw-r--r--source/lib/system.c178
-rw-r--r--source/lib/system_smbd.c132
-rw-r--r--source/lib/talloc.c36
-rw-r--r--source/lib/time.c130
-rw-r--r--source/lib/username.c574
-rw-r--r--source/lib/util.c377
-rw-r--r--source/lib/util_file.c76
-rw-r--r--source/lib/util_getent.c337
-rw-r--r--source/lib/util_pw.c80
-rw-r--r--source/lib/util_sid.c93
-rw-r--r--source/lib/util_smbd.c86
-rw-r--r--source/lib/util_sock.c5
-rw-r--r--source/lib/util_str.c157
-rw-r--r--source/lib/util_unistr.c113
-rw-r--r--source/lib/wins_srv.c3
-rw-r--r--source/lib/xfile.c5
-rw-r--r--source/libads/ads_ldap.c1
-rw-r--r--source/libads/ads_utils.c42
-rw-r--r--source/libads/gpo.c680
-rw-r--r--source/libads/gpo_util.c496
-rw-r--r--source/libads/kerberos.c65
-rw-r--r--source/libads/kerberos_verify.c35
-rw-r--r--source/libads/krb5_errs.c109
-rw-r--r--source/libads/krb5_setpw.c75
-rw-r--r--source/libads/ldap.c219
-rw-r--r--source/libads/sasl.c27
-rw-r--r--source/libmsrpc/cac_lsarpc.c44
-rw-r--r--source/libmsrpc/cac_samr.c46
-rw-r--r--source/libmsrpc/cac_svcctl.c2
-rw-r--r--source/libmsrpc/cac_winreg.c44
-rw-r--r--source/libmsrpc/libmsrpc.c9
-rw-r--r--source/libmsrpc/libmsrpc_internal.c18
-rw-r--r--source/libsmb/asn1.c7
-rw-r--r--source/libsmb/cliconnect.c27
-rw-r--r--source/libsmb/clidfs.c26
-rw-r--r--source/libsmb/clientgen.c6
-rw-r--r--source/libsmb/clierror.c45
-rw-r--r--source/libsmb/clifile.c105
-rw-r--r--source/libsmb/clikrb5.c176
-rw-r--r--source/libsmb/clilist.c23
-rw-r--r--source/libsmb/clirap.c34
-rw-r--r--source/libsmb/clireadwrite.c7
-rw-r--r--source/libsmb/clispnego.c2
-rw-r--r--source/libsmb/clitrans.c66
-rw-r--r--source/libsmb/conncache.c36
-rw-r--r--source/libsmb/credentials.c208
-rw-r--r--source/libsmb/dcerpc_err.c55
-rw-r--r--source/libsmb/errormap.c19
-rw-r--r--source/libsmb/gpo.c167
-rw-r--r--source/libsmb/libsmb_cache.c16
-rw-r--r--source/libsmb/libsmbclient.c324
-rw-r--r--source/libsmb/namequery.c349
-rw-r--r--source/libsmb/namequery_dc.c28
-rw-r--r--source/libsmb/nterr.c4
-rw-r--r--source/libsmb/ntlmssp.c20
-rw-r--r--source/libsmb/ntlmssp_sign.c6
-rw-r--r--source/libsmb/passchange.c40
-rw-r--r--source/libsmb/samlogon_cache.c1
-rw-r--r--source/libsmb/smb_share_modes.c46
-rw-r--r--source/libsmb/smb_signing.c244
-rw-r--r--source/libsmb/smbdes.c36
-rw-r--r--source/libsmb/smbencrypt.c19
-rw-r--r--source/libsmb/spnego.c4
-rw-r--r--source/locking/brlock.c1314
-rw-r--r--source/locking/locking.c613
-rw-r--r--source/locking/posix.c104
-rw-r--r--source/modules/vfs_fake_perms.c8
-rw-r--r--source/modules/vfs_full_audit.c21
-rw-r--r--source/modules/vfs_shadow_copy.c7
-rw-r--r--source/nmbd/asyncdns.c8
-rw-r--r--source/nmbd/nmbd.c53
-rw-r--r--source/nmbd/nmbd_browserdb.c22
-rw-r--r--source/nmbd/nmbd_browsesync.c6
-rw-r--r--source/nmbd/nmbd_incomingdgrams.c2
-rw-r--r--source/nmbd/nmbd_incomingrequests.c6
-rw-r--r--source/nmbd/nmbd_mynames.c8
-rw-r--r--source/nmbd/nmbd_namelistdb.c236
-rw-r--r--source/nmbd/nmbd_packets.c4
-rw-r--r--source/nmbd/nmbd_subnetdb.c33
-rw-r--r--source/nmbd/nmbd_winsproxy.c21
-rw-r--r--source/nmbd/nmbd_winsserver.c718
-rw-r--r--source/nsswitch/pam_winbind.c1033
-rw-r--r--source/nsswitch/pam_winbind.h79
-rw-r--r--source/nsswitch/wb_client.c68
-rw-r--r--source/nsswitch/wb_common.c19
-rw-r--r--source/nsswitch/wbinfo.c201
-rw-r--r--source/nsswitch/winbind_nss_aix.c14
-rw-r--r--source/nsswitch/winbind_nss_config.h19
-rw-r--r--source/nsswitch/winbind_nss_irix.c24
-rw-r--r--source/nsswitch/winbind_nss_irix.h4
-rw-r--r--source/nsswitch/winbind_nss_linux.c18
-rw-r--r--source/nsswitch/winbind_nss_solaris.c6
-rw-r--r--source/nsswitch/winbindd.c105
-rw-r--r--source/nsswitch/winbindd.h21
-rw-r--r--source/nsswitch/winbindd_ads.c7
-rw-r--r--source/nsswitch/winbindd_async.c59
-rw-r--r--source/nsswitch/winbindd_cache.c946
-rw-r--r--source/nsswitch/winbindd_cm.c105
-rw-r--r--source/nsswitch/winbindd_cred_cache.c268
-rw-r--r--source/nsswitch/winbindd_creds.c164
-rw-r--r--source/nsswitch/winbindd_dual.c242
-rw-r--r--source/nsswitch/winbindd_group.c213
-rw-r--r--source/nsswitch/winbindd_ldap.c646
-rw-r--r--source/nsswitch/winbindd_misc.c27
-rw-r--r--source/nsswitch/winbindd_nss.h100
-rw-r--r--source/nsswitch/winbindd_pam.c1124
-rw-r--r--source/nsswitch/winbindd_passdb.c207
-rw-r--r--source/nsswitch/winbindd_reconnect.c32
-rw-r--r--source/nsswitch/winbindd_rpc.c69
-rw-r--r--source/nsswitch/winbindd_sid.c54
-rw-r--r--source/nsswitch/winbindd_user.c46
-rw-r--r--source/nsswitch/winbindd_util.c89
-rw-r--r--source/nsswitch/wins.c2
-rw-r--r--source/pam_smbpass/pam_smb_acct.c12
-rw-r--r--source/pam_smbpass/pam_smb_auth.c27
-rw-r--r--source/pam_smbpass/pam_smb_passwd.c40
-rw-r--r--source/pam_smbpass/support.c8
-rw-r--r--source/pam_smbpass/support.h4
-rw-r--r--source/param/loadparm.c973
-rw-r--r--source/param/params.c16
-rw-r--r--source/passdb/login_cache.c8
-rw-r--r--source/passdb/lookup_sid.c1130
-rw-r--r--source/passdb/machine_sid.c27
-rw-r--r--source/passdb/passdb.c1614
-rw-r--r--source/passdb/pdb_compat.c10
-rw-r--r--source/passdb/pdb_get_set.c610
-rw-r--r--source/passdb/pdb_guest.c164
-rw-r--r--source/passdb/pdb_interface.c2078
-rw-r--r--source/passdb/pdb_ldap.c2851
-rw-r--r--source/passdb/pdb_mysql.c509
-rw-r--r--source/passdb/pdb_nds.c30
-rw-r--r--source/passdb/pdb_pgsql.c605
-rw-r--r--source/passdb/pdb_plugin.c4
-rw-r--r--source/passdb/pdb_smbpasswd.c116
-rw-r--r--source/passdb/pdb_sql.c571
-rw-r--r--source/passdb/pdb_tdb.c1414
-rw-r--r--source/passdb/pdb_xml.c580
-rw-r--r--source/passdb/secrets.c267
-rw-r--r--source/passdb/util_builtin.c79
-rw-r--r--source/passdb/util_sam_sid.c238
-rw-r--r--source/passdb/util_unixsids.c94
-rw-r--r--source/passdb/util_wellknown.c175
-rw-r--r--source/printing/lpq_parse.c2
-rw-r--r--source/printing/notify.c2
-rw-r--r--source/printing/nt_printing.c90
-rw-r--r--source/printing/print_cups.c7
-rw-r--r--source/printing/print_generic.c14
-rw-r--r--source/printing/print_iprint.c7
-rw-r--r--source/printing/printfsp.c4
-rw-r--r--source/printing/printing.c41
-rw-r--r--source/python/py_common.c2
-rw-r--r--source/python/py_lsa.c4
-rw-r--r--source/python/py_samr.c2
-rw-r--r--source/python/py_winbind.c12
-rw-r--r--source/registry/reg_db.c9
-rw-r--r--source/registry/reg_objects.c59
-rw-r--r--source/registry/reg_perfcount.c56
-rw-r--r--source/registry/reg_printing.c13
-rw-r--r--source/rpc_client/cli_dfs.c673
-rw-r--r--source/rpc_client/cli_echo.c3
-rw-r--r--source/rpc_client/cli_lsarpc.c291
-rw-r--r--source/rpc_client/cli_netlogon.c32
-rw-r--r--source/rpc_client/cli_pipe.c39
-rw-r--r--source/rpc_client/cli_samr.c176
-rw-r--r--source/rpc_client/cli_spoolss.c6
-rw-r--r--source/rpc_parse/parse_buffer.c24
-rw-r--r--source/rpc_parse/parse_dfs.c2789
-rw-r--r--source/rpc_parse/parse_lsa.c1339
-rw-r--r--source/rpc_parse/parse_misc.c73
-rw-r--r--source/rpc_parse/parse_net.c260
-rw-r--r--source/rpc_parse/parse_prs.c103
-rw-r--r--source/rpc_parse/parse_reg.c95
-rw-r--r--source/rpc_parse/parse_rpc.c13
-rw-r--r--source/rpc_parse/parse_samr.c292
-rw-r--r--source/rpc_parse/parse_shutdown.c14
-rw-r--r--source/rpc_parse/parse_spoolss.c218
-rw-r--r--source/rpc_server/srv_dfs.c587
-rw-r--r--source/rpc_server/srv_dfs_nt.c410
-rw-r--r--source/rpc_server/srv_eventlog_lib.c13
-rw-r--r--source/rpc_server/srv_eventlog_nt.c2
-rw-r--r--source/rpc_server/srv_lsa.c160
-rw-r--r--source/rpc_server/srv_lsa_nt.c905
-rw-r--r--source/rpc_server/srv_netlog.c42
-rw-r--r--source/rpc_server/srv_netlog_nt.c509
-rw-r--r--source/rpc_server/srv_pipe.c85
-rw-r--r--source/rpc_server/srv_pipe_hnd.c17
-rw-r--r--source/rpc_server/srv_reg_nt.c4
-rw-r--r--source/rpc_server/srv_samr.c68
-rw-r--r--source/rpc_server/srv_samr_nt.c1395
-rw-r--r--source/rpc_server/srv_samr_util.c12
-rwxr-xr-xsource/rpc_server/srv_spoolss.c55
-rw-r--r--source/rpc_server/srv_spoolss_nt.c795
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c226
-rw-r--r--source/rpc_server/srv_svcctl_nt.c11
-rw-r--r--source/rpcclient/cmd_dfs.c111
-rw-r--r--source/rpcclient/cmd_ds.c6
-rw-r--r--source/rpcclient/cmd_lsarpc.c169
-rw-r--r--source/rpcclient/cmd_netlogon.c43
-rw-r--r--source/rpcclient/cmd_reg.c2
-rw-r--r--source/rpcclient/cmd_samr.c404
-rw-r--r--source/rpcclient/cmd_spoolss.c7
-rw-r--r--source/rpcclient/rpcclient.c51
-rw-r--r--source/sam/idmap.c41
-rw-r--r--source/sam/idmap_ad.c7
-rw-r--r--source/sam/idmap_ldap.c271
-rw-r--r--source/sam/idmap_rid.c12
-rw-r--r--source/sam/idmap_smbldap.c10
-rw-r--r--source/sam/idmap_tdb.c39
-rw-r--r--source/sam/idmap_util.c74
-rwxr-xr-xsource/script/installbin.sh.in (renamed from source/script/installbin.sh)27
-rwxr-xr-xsource/script/installdat.sh60
-rwxr-xr-xsource/script/installdirs.sh21
-rwxr-xr-xsource/script/installman.sh5
-rwxr-xr-xsource/script/installmodules.sh22
-rw-r--r--source/script/installmsg.sh62
-rwxr-xr-xsource/script/installswat.sh275
-rwxr-xr-xsource/script/tests/dlopen.sh91
-rw-r--r--source/script/tests/functions82
-rw-r--r--source/script/tests/runtests.sh129
-rwxr-xr-xsource/script/tests/selftest.sh211
-rw-r--r--source/script/tests/t_001.sh30
-rw-r--r--source/script/tests/t_002.sh30
-rw-r--r--source/script/tests/test_functions.sh221
-rwxr-xr-xsource/script/tests/test_posix_s3.sh61
-rwxr-xr-xsource/script/tests/test_smbclient_s3.sh23
-rwxr-xr-xsource/script/tests/test_smbtorture_s3.sh47
-rwxr-xr-xsource/script/tests/tests_all.sh11
-rw-r--r--source/script/tests/timelimit.c107
-rwxr-xr-xsource/script/uninstallbin.sh42
-rwxr-xr-xsource/script/uninstallbin.sh.in46
-rwxr-xr-xsource/script/uninstallmodules.sh22
-rw-r--r--source/services/services_db.c2
-rw-r--r--source/smbd/blocking.c277
-rw-r--r--source/smbd/chgpasswd.c128
-rw-r--r--source/smbd/close.c75
-rw-r--r--source/smbd/conn.c18
-rw-r--r--source/smbd/dir.c40
-rw-r--r--source/smbd/dmapi.c306
-rw-r--r--source/smbd/dosmode.c32
-rw-r--r--source/smbd/fake_file.c2
-rw-r--r--source/smbd/files.c12
-rw-r--r--source/smbd/ipc.c449
-rw-r--r--source/smbd/lanman.c2873
-rw-r--r--source/smbd/map_username.c180
-rw-r--r--source/smbd/msdfs.c24
-rw-r--r--source/smbd/notify.c17
-rw-r--r--source/smbd/notify_fam.c463
-rw-r--r--source/smbd/notify_hash.c24
-rw-r--r--source/smbd/notify_kernel.c1
-rw-r--r--source/smbd/ntquotas.c9
-rw-r--r--source/smbd/nttrans.c647
-rw-r--r--source/smbd/open.c225
-rw-r--r--source/smbd/oplock.c50
-rw-r--r--source/smbd/oplock_irix.c6
-rw-r--r--source/smbd/password.c274
-rw-r--r--source/smbd/posix_acls.c101
-rw-r--r--source/smbd/process.c233
-rw-r--r--source/smbd/reply.c251
-rw-r--r--source/smbd/sec_ctx.c135
-rw-r--r--source/smbd/server.c240
-rw-r--r--source/smbd/service.c406
-rw-r--r--source/smbd/session.c4
-rw-r--r--source/smbd/sesssetup.c97
-rw-r--r--source/smbd/share_access.c269
-rw-r--r--source/smbd/tdbutil.c85
-rw-r--r--source/smbd/trans2.c1102
-rw-r--r--source/smbd/uid.c152
-rw-r--r--source/smbd/vfs-wrap.c12
-rw-r--r--source/smbd/vfs.c3
-rw-r--r--source/smbwrapper/shared.c4
-rw-r--r--source/smbwrapper/smbw.c2
-rw-r--r--source/smbwrapper/smbw_dir.c10
-rw-r--r--source/tdb/tdb.c30
-rw-r--r--source/tdb/tdb.h2
-rw-r--r--source/tdb/tdbback.c2
-rw-r--r--source/tdb/tdbdump.c46
-rw-r--r--source/tdb/tdbtorture.c4
-rw-r--r--source/tdb/tdbutil.c37
-rw-r--r--source/tests/os2_delete.c214
-rw-r--r--source/torture/locktest.c24
-rw-r--r--source/torture/locktest2.c2
-rw-r--r--source/torture/masktest.c2
-rw-r--r--source/torture/msgtest.c2
-rw-r--r--source/torture/nsstest.c9
-rw-r--r--source/torture/rpctorture.c2
-rw-r--r--source/torture/t_push_ucs2.c2
-rw-r--r--source/torture/t_strcmp.c2
-rw-r--r--source/torture/t_strstr.c2
-rw-r--r--source/torture/torture.c2
-rw-r--r--source/torture/vfstest.c9
-rw-r--r--source/ubiqx/COPYING.LIB481
-rw-r--r--source/ubiqx/README.UBI18
-rw-r--r--source/ubiqx/sys_include.h52
-rw-r--r--source/ubiqx/ubi_BinTree.c1172
-rw-r--r--source/ubiqx/ubi_BinTree.h887
-rw-r--r--source/ubiqx/ubi_Cache.c505
-rw-r--r--source/ubiqx/ubi_Cache.h412
-rw-r--r--source/ubiqx/ubi_SplayTree.c512
-rw-r--r--source/ubiqx/ubi_SplayTree.h377
-rw-r--r--source/ubiqx/ubi_dLinkList.c171
-rw-r--r--source/ubiqx/ubi_dLinkList.h242
-rw-r--r--source/ubiqx/ubi_sLinkList.c187
-rw-r--r--source/ubiqx/ubi_sLinkList.h254
-rw-r--r--source/utils/debugparse.c (renamed from source/ubiqx/debugparse.c)0
-rw-r--r--source/utils/eventlogadm.c2
-rw-r--r--source/utils/net.c49
-rw-r--r--source/utils/net.h23
-rw-r--r--source/utils/net_ads.c38
-rw-r--r--source/utils/net_ads_gpo.c436
-rw-r--r--source/utils/net_groupmap.c53
-rw-r--r--source/utils/net_help.c9
-rw-r--r--source/utils/net_lookup.c52
-rw-r--r--source/utils/net_rap.c4
-rw-r--r--source/utils/net_rpc.c595
-rw-r--r--source/utils/net_rpc_audit.c414
-rw-r--r--source/utils/net_rpc_join.c18
-rw-r--r--source/utils/net_rpc_printer.c142
-rw-r--r--source/utils/net_rpc_registry.c2
-rw-r--r--source/utils/net_rpc_rights.c55
-rw-r--r--source/utils/net_rpc_samsync.c417
-rw-r--r--source/utils/net_rpc_sh_acct.c411
-rw-r--r--source/utils/net_rpc_shell.c274
-rw-r--r--source/utils/net_sam.c1249
-rw-r--r--source/utils/net_status.c4
-rw-r--r--source/utils/net_usershare.c842
-rw-r--r--source/utils/net_util.c89
-rw-r--r--source/utils/netlookup.c220
-rw-r--r--source/utils/nmblookup.c2
-rw-r--r--source/utils/ntlm_auth.c20
-rw-r--r--source/utils/pdbedit.c397
-rw-r--r--source/utils/smbcacls.c25
-rw-r--r--source/utils/smbcontrol.c170
-rw-r--r--source/utils/smbcquotas.c4
-rw-r--r--source/utils/smbfilter.c2
-rw-r--r--source/utils/smbpasswd.c50
-rw-r--r--source/utils/smbtree.c2
-rw-r--r--source/utils/smbw_sample.c2
-rw-r--r--source/utils/status.c12
-rw-r--r--source/utils/testparm.c2
-rw-r--r--source/web/cgi.c12
-rw-r--r--source/web/startstop.c6
-rw-r--r--source/web/swat.c8
-rw-r--r--source/wrepld/parser.c759
-rw-r--r--source/wrepld/partners.c200
-rw-r--r--source/wrepld/process.c983
-rw-r--r--source/wrepld/server.c670
-rw-r--r--source/wrepld/socket.c69
-rw-r--r--source/wrepld/wins_repl.h161
-rw-r--r--testsuite/nsswitch/pam_winbind_syms.exp2
483 files changed, 50807 insertions, 31055 deletions
diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema
index e7ecc9e070e..4e1556eba5a 100644
--- a/examples/LDAP/samba.schema
+++ b/examples/LDAP/samba.schema
@@ -295,9 +295,9 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.54 NAME 'sambaPasswordHistory'
attributetype ( 1.3.6.1.4.1.7165.2.1.20 NAME 'sambaSID'
DESC 'Security ID'
EQUALITY caseIgnoreIA5Match
+ SUBSTR caseExactIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} SINGLE-VALUE )
-
##
## Primary group SID, compatible with ntSid
##
diff --git a/examples/VFS/Makefile.in b/examples/VFS/Makefile.in
index 79873c38576..caf8f030aa4 100644
--- a/examples/VFS/Makefile.in
+++ b/examples/VFS/Makefile.in
@@ -7,7 +7,7 @@ INSTALLCMD = @INSTALL@
SAMBA_SOURCE = @SAMBA_SOURCE@
SHLIBEXT = @SHLIBEXT@
OBJEXT = @OBJEXT@
-FLAGS = $(CFLAGS) -Iinclude -I$(SAMBA_SOURCE)/include -I$(SAMBA_SOURCE)/popt -I$(SAMBA_SOURCE)/ubiqx -I$(SAMBA_SOURCE)/smbwrapper -I. $(CPPFLAGS) -I$(SAMBA_SOURCE) -fPIC
+FLAGS = $(CFLAGS) -Iinclude -I$(SAMBA_SOURCE)/include -I$(SAMBA_SOURCE)/popt -I$(SAMBA_SOURCE)/smbwrapper -I. $(CPPFLAGS) -I$(SAMBA_SOURCE) -fPIC
prefix = @prefix@
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index e6af475da6e..a02bf3c146b 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -226,6 +226,11 @@ static BOOL skel_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int
return vfswrap_lock(NULL, fsp, fd, op, offset, count, type);
}
+static BOOL skel_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
+{
+ return vfswrap_getlock(NULL, fsp, fd, poffset, pcount, ptype, ppid);
+}
+
static int skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
{
return vfswrap_symlink(NULL, conn, oldpath, newpath);
@@ -576,6 +581,7 @@ static vfs_op_tuple skel_op_tuples[] = {
{SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE},
+ {SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_OPAQUE},
{SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_OPAQUE},
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 14fa2276e1f..5996b298060 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -225,6 +225,11 @@ static BOOL skel_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int
return SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type);
}
+static BOOL skel_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
+{
+ return SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid);
+}
+
static int skel_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
{
return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath);
@@ -543,6 +548,7 @@ static vfs_op_tuple skel_op_tuples[] = {
{SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_TRANSPARENT},
+ {SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(skel_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT},
diff --git a/examples/libmsrpc/test/sam/samenum.c b/examples/libmsrpc/test/sam/samenum.c
index 5b10475aacf..f1b9ebdf842 100644
--- a/examples/libmsrpc/test/sam/samenum.c
+++ b/examples/libmsrpc/test/sam/samenum.c
@@ -51,7 +51,7 @@ int main(int argc, char **argv) {
eu.in.dom_hnd = sod.out.dom_hnd;
printf("ACB mask (can be 0): ");
- scanf("%hx", &eu.in.acb_mask);
+ scanf("%x", &eu.in.acb_mask);
while(cac_SamEnumUsers(hnd, mem_ctx, &eu)) {
printf("Enumerated %d users:\n", eu.out.num_users);
diff --git a/examples/libsmbclient/get_auth_data_fn.h b/examples/libsmbclient/get_auth_data_fn.h
index 2954039f0aa..eb493885af2 100644
--- a/examples/libsmbclient/get_auth_data_fn.h
+++ b/examples/libsmbclient/get_auth_data_fn.h
@@ -7,7 +7,6 @@ get_auth_data_fn(const char * pServer,
int maxLenUsername,
char * pPassword,
int maxLenPassword)
-
{
char temp[128];
diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c
index ca126c9510f..96f78aad85a 100644
--- a/examples/libsmbclient/testbrowse.c
+++ b/examples/libsmbclient/testbrowse.c
@@ -24,6 +24,16 @@ static void browse(char * path,
int indent);
+static void
+get_auth_data_with_context_fn(SMBCCTX * context,
+ const char * pServer,
+ const char * pShare,
+ char * pWorkgroup,
+ int maxLenWorkgroup,
+ char * pUsername,
+ int maxLenUsername,
+ char * pPassword,
+ int maxLenPassword);
int
main(int argc, char * argv[])
@@ -31,6 +41,7 @@ main(int argc, char * argv[])
int debug = 0;
int debug_stderr = 0;
int no_auth = 0;
+ int context_auth = 0;
int scan = 0;
int iterations = -1;
int again;
@@ -64,6 +75,10 @@ main(int argc, char * argv[])
0, "Do not request authentication data", "integer"
},
{
+ "contextauth", 'C', POPT_ARG_NONE, &context_auth,
+ 0, "Use new authentication function with context", "integer"
+ },
+ {
NULL
}
};
@@ -94,12 +109,21 @@ main(int argc, char * argv[])
/* Set mandatory options (is that a contradiction in terms?) */
context->debug = debug;
- context->callbacks.auth_fn = (no_auth ? no_auth_data_fn : get_auth_data_fn);
+ if (context_auth) {
+ context->callbacks.auth_fn = NULL;
+ smbc_option_set(context,
+ "auth_function",
+ (void *) get_auth_data_with_context_fn);
+ smbc_option_set(context, "user_data", "hello world");
+ } else {
+ context->callbacks.auth_fn =
+ (no_auth ? no_auth_data_fn : get_auth_data_fn);
+ }
/* If we've been asked to log to stderr instead of stdout... */
if (debug_stderr) {
/* ... then set the option to do so */
- smbc_option_set(context, "debug_stderr");
+ smbc_option_set(context, "debug_stderr", (void *) 1);
}
/* Initialize the context using the previously specified options */
@@ -161,6 +185,29 @@ no_auth_data_fn(const char * pServer,
return;
}
+
+static void
+get_auth_data_with_context_fn(SMBCCTX * context,
+ const char * pServer,
+ const char * pShare,
+ char * pWorkgroup,
+ int maxLenWorkgroup,
+ char * pUsername,
+ int maxLenUsername,
+ char * pPassword,
+ int maxLenPassword)
+{
+ printf("Authenticating with context 0x%lx", context);
+ if (context != NULL) {
+ char *user_data = smbc_option_get(context, "user_data");
+ printf(" with user data %s", user_data);
+ }
+ printf("\n");
+
+ get_auth_data_fn(pServer, pShare, pWorkgroup, maxLenWorkgroup,
+ pUsername, maxLenUsername, pPassword, maxLenPassword);
+}
+
static void browse(char * path, int scan, int indent)
{
char * p;
diff --git a/examples/misc/adssearch.pl b/examples/misc/adssearch.pl
index f9a7f949262..3651564ec22 100755
--- a/examples/misc/adssearch.pl
+++ b/examples/misc/adssearch.pl
@@ -438,6 +438,7 @@ my %attr_handler = (
"msDS-User-Account-Control-Computed" => \&dump_uacc,
# "msRADIUSFramedIPAddress" => \&dump_ipaddr,
# "msRASSavedFramedIPAddress" => \&dump_ipaddr,
+ "netbootGUID" => \&dump_guid,
"nTMixedDomain" => \&dump_mixed_domain,
"nTSecurityDescriptor" => \&dump_secdesc,
"objectGUID" => \&dump_guid,
diff --git a/examples/pam_winbind/pam_winbind.conf b/examples/pam_winbind/pam_winbind.conf
new file mode 100644
index 00000000000..ca36e2ab00a
--- /dev/null
+++ b/examples/pam_winbind/pam_winbind.conf
@@ -0,0 +1,26 @@
+#
+# pam_winbind configuration file
+#
+# /etc/security/pam_winbind.conf
+#
+
+[global]
+
+# turn on debugging
+;debug = no
+
+# request a cached login if possible
+# (needs "winbind offline logon = yes" in smb.conf)
+;cached_login = no
+
+# authenticate using kerberos
+;krb5_auth = no
+
+# when using kerberos, request a "FILE" krb5 credential cache type
+# (leave empty to just do krb5 authentication but not have a ticket
+# afterwards)
+;krb5_ccache_type =
+
+# make successful authentication dependend on membership of one SID
+# (can also take a name)
+;require_membership_of =
diff --git a/examples/pdb/mysql/mysql.dump b/examples/pdb/mysql/mysql.dump
deleted file mode 100644
index 72018ce5a70..00000000000
--- a/examples/pdb/mysql/mysql.dump
+++ /dev/null
@@ -1,37 +0,0 @@
-# Put this in your MySQL database by running
-# mysql -u<user> -p<password> -h<host> <database> < mysql.dump
-
-CREATE TABLE user (
- logon_time int(9),
- logoff_time int(9),
- kickoff_time int(9),
- pass_last_set_time int(9),
- pass_can_change_time int(9),
- pass_must_change_time int(9),
- username varchar(255),
- domain varchar(255),
- nt_username varchar(255),
- nt_fullname varchar(255),
- home_dir varchar(255),
- dir_drive varchar(4),
- logon_script varchar(255),
- profile_path varchar(255),
- acct_desc varchar(255),
- workstations varchar(255),
- unknown_str varchar(255),
- munged_dial varchar(255),
- uid int(9) NOT NULL DEFAULT "0" PRIMARY KEY auto_increment,
- gid int(9),
- user_sid varchar(255),
- group_sid varchar(255),
- lm_pw varchar(255),
- nt_pw varchar(255),
- acct_ctrl int(9),
- unknown_3 int(9),
- logon_divs int(9),
- hours_len int(9),
- unknown_5 int(9),
- unknown_6 int(9) default "1260",
- bad_password_count int(9),
- logon_count int(9)
-);
diff --git a/examples/pdb/mysql/smb.conf b/examples/pdb/mysql/smb.conf
deleted file mode 100644
index 61a3f198168..00000000000
--- a/examples/pdb/mysql/smb.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-[global]
-netbios name = FOOBAR
-workgroup = TESTGROUP
-security = domain
-domain logons = yes
-domain master = yes
-passdb backend = plugin:/usr/local/samba/lib/pdb_mysql.so:mysql
-mysql:mysql host = rhonwyn
-mysql:mysql user = samba
-mysql:mysql password = ambas
-mysql:mysql database = samba
diff --git a/examples/pdb/sambapdb.dtd b/examples/pdb/sambapdb.dtd
deleted file mode 100644
index 1f4054ddec4..00000000000
--- a/examples/pdb/sambapdb.dtd
+++ /dev/null
@@ -1,46 +0,0 @@
-<!ELEMENT samba:crypt (#PCDATA)* >
-<!ATTLIST samba:crypt type CDATA #REQUIRED >
-
-<!ELEMENT samba:password (samba:crypt*) >
-<!ATTLIST samba:password last_set CDATA #IMPLIED
- must_change CDATA #IMPLIED
- can_change CDATA #IMPLIED>
-
-<!ELEMENT samba:group (#PCDATA)* >
-<!ATTLIST samba:group sid CDATA #REQUIRED
- gid CDATA #IMPLIED >
-
-<!ELEMENT samba:domain (#PCDATA)* >
-<!ELEMENT samba:fullname (#PCDATA)* >
-<!ELEMENT samba:nt_username (#PCDATA)* >
-<!ELEMENT samba:logon_script (#PCDATA)* >
-<!ELEMENT samba:profile_path (#PCDATA)* >
-<!ELEMENT samba:logon_time (#PCDATA)* >
-<!ELEMENT samba:logoff_time (#PCDATA)* >
-<!ELEMENT samba:kickoff_time (#PCDATA)* >
-<!ELEMENT samba:logon_divs (#PCDATA)* >
-<!ELEMENT samba:hours_len (#PCDATA)* >
-<!ELEMENT samba:unknown_3 (#PCDATA)* >
-<!ELEMENT samba:unknown_5 (#PCDATA)* >
-<!ELEMENT samba:unknown_6 (#PCDATA)* >
-<!ELEMENT samba:homedir (#PCDATA)* >
-<!ELEMENT samba:unknown_str (#PCDATA)* >
-<!ELEMENT samba:dir_drive (#PCDATA)* >
-<!ELEMENT samba:munged_dial (#PCDATA)* >
-<!ELEMENT samba:acct_desc (#PCDATA)* >
-<!ELEMENT samba:acct_ctrl (#PCDATA)* >
-<!ELEMENT samba:workstations (#PCDATA)* >
-
-<!ELEMENT samba:user ( samba:group?, samba:domain?, samba:nt_username?, samba:fullname?, samba:homedir?, samba:dir_drive?, samba:logon_script?, samba:profile_path?, samba:password?, samba:acct_ctrl?,samba:unknown_3?, samba:logon_divs?, samba:hours_len?, samba:logon_time?, samba:logoff_time?, samba:kickoff_time?, samba:unknown_5?, samba:unknown_6?, samba:unknown_str?, samba:munged_dial?, samba:acct_desc?, samba:workstations? ) >
-
-<!ATTLIST samba:user sid CDATA #REQUIRED
- uid CDATA #IMPLIED
- name CDATA #REQUIRED>
-
-<!ELEMENT samba:users (samba:user*) >
-
-<!ELEMENT samba (samba:users?) >
-
-<!ATTLIST samba
- xmlns CDATA #FIXED 'http://samba.org/~jelmer/sambapdb.dtd'>
-
diff --git a/examples/pdb/test.c b/examples/pdb/test.c
index 63eb1eaaf97..68b5b9a3e5a 100644
--- a/examples/pdb/test.c
+++ b/examples/pdb/test.c
@@ -29,7 +29,7 @@ static int testsam_debug_level = DBGC_ALL;
Start enumeration of the passwd list.
****************************************************************/
-static NTSTATUS testsam_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask)
+static NTSTATUS testsam_setsampwent(struct pdb_methods *methods, BOOL update, uint32 acb_mask)
{
DEBUG(10, ("testsam_setsampwent called\n"));
return NT_STATUS_NOT_IMPLEMENTED;
diff --git a/examples/perfcounter/perf_writer.c b/examples/perfcounter/perf_writer.c
index 04127f5621f..00e47bdabaf 100644
--- a/examples/perfcounter/perf_writer.c
+++ b/examples/perfcounter/perf_writer.c
@@ -26,7 +26,7 @@ sig_atomic_t keep_running = TRUE;
/* allocates memory and gets numCPUs, total memory, and PerfFreq, number of disks... */
void get_constants(PERF_DATA_BLOCK *data)
{
- data->cpuInfo.numCPUs = sysconf(_SC_NPROCESSORS_ONLN);
+ data->cpuInfo.numCPUs = sysconf(_SC_NPROCESSORS_ONLN) > 0 ? sysconf(_SC_NPROCESSORS_ONLN) : 1;
data->PerfFreq = sysconf(_SC_CLK_TCK);
init_mem_data(data);
init_cpu_data(data);
diff --git a/examples/scripts/shares/perl/modify_samba_config.pl b/examples/scripts/shares/perl/modify_samba_config.pl
index e59ac451baf..aaf2958a95a 100755
--- a/examples/scripts/shares/perl/modify_samba_config.pl
+++ b/examples/scripts/shares/perl/modify_samba_config.pl
@@ -36,7 +36,7 @@ my $tmp_file_name = undef;
if ($#ARGV == 1) {
$delete_mode = 1;
}
-elsif ($#ARGV == 3) {
+elsif ($#ARGV == 4) {
$add_mode = 1;
}
else {
@@ -101,6 +101,7 @@ close (CONFIGFILE);
if ($add_mode) {
$config{$ARGV[1]}{'path'} = $ARGV[2];
$config{$ARGV[1]}{'comment'} = $ARGV[3];
+ $config{$ARGV[1]}{'max connections'} = $ARGV[4];
}
elsif ($delete_mode) {
delete $config{$ARGV[1]};
diff --git a/packaging/Debian/debian-sarge/rules b/packaging/Debian/debian-sarge/rules
index 4db1aafd3ac..eb6e71c90e1 100755
--- a/packaging/Debian/debian-sarge/rules
+++ b/packaging/Debian/debian-sarge/rules
@@ -181,7 +181,7 @@ install: build
# Install winbind stuff not installed by 'make install'
install -m 0644 source/nsswitch/libnss_winbind.so \
$(DESTDIR)/lib/libnss_winbind.so.2
- install -m 0644 source/nsswitch/pam_winbind.so \
+ install -m 0644 source/bin/pam_winbind.so \
$(DESTDIR)/lib/security/
# Install libnss_wins.so, which is not installed by 'make install' either.
diff --git a/packaging/Debian/debian-unstable/rules b/packaging/Debian/debian-unstable/rules
index 71f833d4cb2..bfc15255f33 100755
--- a/packaging/Debian/debian-unstable/rules
+++ b/packaging/Debian/debian-unstable/rules
@@ -176,7 +176,7 @@ install: build
# Install winbind stuff not installed by 'make install'
install -m 0644 source/nsswitch/libnss_winbind.so \
$(DESTDIR)/lib/libnss_winbind.so.2
- install -m 0644 source/nsswitch/pam_winbind.so \
+ install -m 0644 source/bin/pam_winbind.so \
$(DESTDIR)/lib/security/
# Install libnss_wins.so, which is not installed by 'make install' either.
diff --git a/packaging/Debian/debian-woody/rules b/packaging/Debian/debian-woody/rules
index f17ea75c015..d97dc99bce8 100755
--- a/packaging/Debian/debian-woody/rules
+++ b/packaging/Debian/debian-woody/rules
@@ -147,7 +147,7 @@ install: build
# Install winbind stuff not installed by 'make install'
install -m 0644 source/nsswitch/libnss_winbind.so \
$(DESTDIR)/lib/libnss_winbind.so.2
- install -m 0644 source/nsswitch/pam_winbind.so \
+ install -m 0644 source/bin/pam_winbind.so \
$(DESTDIR)/lib/security/
# Install libnss_wins.so, which is not installed by 'make install' either.
diff --git a/packaging/RHEL/makerpms.sh.tmpl b/packaging/RHEL/makerpms.sh.tmpl
index e6c178f6f3c..ebaa4e649f7 100644
--- a/packaging/RHEL/makerpms.sh.tmpl
+++ b/packaging/RHEL/makerpms.sh.tmpl
@@ -11,6 +11,8 @@
# /usr/src/redhat directory
#
+EXTRA_OPTIONS="$1"
+
SPECDIR=`rpm --eval %_specdir`
SRCDIR=`rpm --eval %_sourcedir`
@@ -39,7 +41,9 @@ esac
( cd ../../source; if [ -f Makefile ]; then make distclean; fi )
( cd ../../.. ; chown -R ${USERID}.${GRPID} samba-${VERSION} )
+echo -n "Creating samba-${VERSION}.tar.bz2 ... "
( cd ../../.. ; tar --exclude=.svn -cf - samba-${VERSION}/. | bzip2 > ${SRCDIR}/samba-${VERSION}.tar.bz2 )
+echo "Done."
##
## copy additional source files
@@ -51,9 +55,9 @@ cp -p ${SPECFILE} ${SPECDIR}
##
## Build
##
-echo Getting Ready to build release package
+echo "$(basename $0): Getting Ready to build release package"
cd ${SPECDIR}
-${RPM} -ba --clean --rmsource $SPECFILE
+${RPM} -ba --clean --rmsource $EXTRA_OPTIONS $SPECFILE
-echo Done.
+echo "$(basename $0): Done."
diff --git a/packaging/RHEL/samba.spec.tmpl b/packaging/RHEL/samba.spec.tmpl
index f5302a87a72..6e5ebcb6d0b 100644
--- a/packaging/RHEL/samba.spec.tmpl
+++ b/packaging/RHEL/samba.spec.tmpl
@@ -211,7 +211,7 @@ cd ..
cp source/bin/pam_smbpass.so $RPM_BUILD_ROOT/%{_lib}/security/pam_smbpass.so
# NSS & PAM winbind support
-install -m 755 source/nsswitch/pam_winbind.so $RPM_BUILD_ROOT/%{_lib}/security/pam_winbind.so
+install -m 755 source/bin/pam_winbind.so $RPM_BUILD_ROOT/%{_lib}/security/pam_winbind.so
install -m 755 source/nsswitch/libnss_winbind.so $RPM_BUILD_ROOT/%{_lib}/libnss_winbind.so
install -m 755 source/nsswitch/libnss_wins.so $RPM_BUILD_ROOT/%{_lib}/libnss_wins.so
( cd $RPM_BUILD_ROOT/%{_lib};
diff --git a/packaging/RedHat-9/samba.spec.tmpl b/packaging/RedHat-9/samba.spec.tmpl
index 6ea456c3841..e450bf512fb 100644
--- a/packaging/RedHat-9/samba.spec.tmpl
+++ b/packaging/RedHat-9/samba.spec.tmpl
@@ -177,7 +177,7 @@ install -m755 source/nsswitch/libnss_wins.so $RPM_BUILD_ROOT/lib
# Install winbind shared libraries
install -m755 source/nsswitch/libnss_winbind.so $RPM_BUILD_ROOT/lib
( cd $RPM_BUILD_ROOT/lib; ln -sf libnss_winbind.so libnss_winbind.so.2 )
-install -m755 source/nsswitch/pam_winbind.so $RPM_BUILD_ROOT/lib/security
+install -m755 source/bin/pam_winbind.so $RPM_BUILD_ROOT/lib/security
# Install pam_smbpass.so
install -m755 source/bin/pam_smbpass.so $RPM_BUILD_ROOT/lib/security
diff --git a/packaging/Solaris/makepkg.sh b/packaging/Solaris/makepkg.sh
index 18e9f00f84a..6a8660b350c 100644
--- a/packaging/Solaris/makepkg.sh
+++ b/packaging/Solaris/makepkg.sh
@@ -172,8 +172,8 @@ DOCDIR=$INSTALL_BASE/docs
##
cp -fp nsswitch/libnss_wins.so $TMPINSTALLDIR/$LIBDIR/nss_wins.so.1
cp -fp nsswitch/libnss_winbind.so $TMPINSTALLDIR/$LIBDIR/nss_winbind.so.1
-if [ -f nsswitch/pam_winbind.so ]; then
- cp -fp nsswitch/pam_winbind.so $TMPINSTALLDIR/$LIBDIR/pam_winbind.so
+if [ -f bin/pam_winbind.so ]; then
+ cp -fp bin/pam_winbind.so $TMPINSTALLDIR/$LIBDIR/pam_winbind.so
fi
if [ -f bin/smbwrapper.so ]; then
cp -fp bin/smbwrapper.so $TMPINSTALLDIR/$INSTALL_BASE/lib
diff --git a/source/Makefile.in b/source/Makefile.in
index c67938727e0..27753dd0721 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -5,11 +5,15 @@
# Copyright Andrew Bartlett 2002
# Copyright (C) 2003 Jim McDonough <jmcd@us.ibm.com>
# Copyright (C) 2002-2003 Jelmer Vernooij <jelmer@samba.org>
+# Copyright (C) 2006 Lars Mueller <lars@samba.org>
###########################################################################
prefix=@prefix@
exec_prefix=@exec_prefix@
+selftest_prefix=@selftest_prefix@
+smbtorture4_path=@smbtorture4_path@
+
LIBS=@LIBS@
CC=@CC@
SHLD=@SHLD@
@@ -34,10 +38,13 @@ PASSDB_LIBS=@PASSDB_LIBS@
IDMAP_LIBS=@IDMAP_LIBS@
KRB5LIBS=@KRB5_LIBS@
LDAP_LIBS=@LDAP_LIBS@
+NSCD_LIBS=@NSCD_LIBS@
INSTALLCMD=@INSTALL@
INSTALLLIBCMD_SH=@INSTALLLIBCMD_SH@
INSTALLLIBCMD_A=@INSTALLLIBCMD_A@
+UNINSTALLLIBCMD_SH=@UNINSTALLLIBCMD_SH@
+UNINSTALLLIBCMD_A=@UNINSTALLLIBCMD_A@
VPATH=@srcdir@
srcdir=@abs_srcdir@
@@ -56,7 +63,9 @@ BASEDIR= @prefix@
BINDIR = @bindir@
# sbindir is mapped to bindir when compiling SAMBA in 2.0.x compatibility mode.
SBINDIR = @sbindir@
+ROOTSBINDIR = @rootsbindir@
LIBDIR = @libdir@
+PAMMODULESDIR = @pammodulesdir@
VFSLIBDIR = $(LIBDIR)/vfs
PDBLIBDIR = $(LIBDIR)/pdb
RPCLIBDIR = $(LIBDIR)/rpc
@@ -106,8 +115,8 @@ LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@
LIBSMBSHAREMODES_MAJOR=0
LIBSMBSHAREMODES_MINOR=2
-FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_
-FLAGS2 =
+FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_
+FLAGS2 =
FLAGS3 =
FLAGS4 =
FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4)
@@ -127,6 +136,8 @@ PATH_FLAGS = $(PATH_FLAGS6) $(PASSWD_FLAGS)
SBIN_PROGS = bin/smbd@EXEEXT@ bin/nmbd@EXEEXT@ bin/swat@EXEEXT@ @EXTRA_SBIN_PROGS@
+ROOT_SBIN_PROGS = @CIFSMOUNT_PROGS@
+
BIN_PROGS1 = bin/smbclient@EXEEXT@ bin/net@EXEEXT@ bin/smbspool@EXEEXT@ \
bin/testparm@EXEEXT@ bin/smbstatus@EXEEXT@ bin/smbget@EXEEXT@
BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
@@ -134,7 +145,7 @@ BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
bin/tdbtool@EXEEXT@
BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ \
- bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@
+ bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@
TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
@@ -147,6 +158,8 @@ EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ bin/talloctort@E
SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ @LIBSMBSHAREMODES@ cac
+PAM_MODULES = @PAM_MODULES@
+
SCRIPTS = $(srcdir)/script/smbtar $(builddir)/script/findsmb
VFS_MODULES = @VFS_MODULES@
@@ -191,10 +204,10 @@ 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/interfaces.o lib/pidfile.o lib/replace.o lib/replace1.o lib/repdir.o \
lib/signal.o lib/system.o lib/sendfile.o lib/time.o \
lib/ufc.o lib/genrand.o lib/username.o \
- lib/util_getent.o lib/util_pw.o lib/access.o lib/smbrun.o \
+ lib/util_pw.o lib/access.o lib/smbrun.o \
lib/bitmap.o lib/crc32.o $(SNPRINTF_OBJ) 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 \
@@ -207,8 +220,9 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
nsswitch/wb_client.o $(WBCOMMON_OBJ) \
lib/pam_errors.o intl/lang_tdb.o \
lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \
- lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \
- lib/secdesc.o lib/secace.o lib/secacl.o @SOCKWRAP@
+ 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@ \
+ libads/krb5_errs.o lib/system_smbd.o lib/audit.o
LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o
LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ)
@@ -219,10 +233,7 @@ READLINE_OBJ = lib/readline.o
# Be sure to include them into your application
POPT_LIB_OBJ = lib/popt_common.o
-UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
- ubiqx/ubi_dLinkList.o ubiqx/ubi_sLinkList.o
-
-PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o
+PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o lib/sharesec.o
KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o
@@ -239,20 +250,20 @@ SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o
LIBNMB_OBJ = libsmb/unexpected.o libsmb/namecache.o libsmb/nmblib.o \
libsmb/namequery.o libsmb/conncache.o
-LIBSAMBA_OBJ = libsmb/nterr.o libsmb/smbdes.o libsmb/smbencrypt.o libsmb/ntlm_check.o \
- libsmb/ntlmssp.o libsmb/ntlmssp_parse.o libsmb/ntlmssp_sign.o
+LIBSAMBA_OBJ = libsmb/nterr.o libsmb/dcerpc_err.o libsmb/smbdes.o \
+ libsmb/smbencrypt.o libsmb/ntlm_check.o \
+ libsmb/ntlmssp.o libsmb/ntlmssp_parse.o libsmb/ntlmssp_sign.o
LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clikrb5.o libsmb/clispnego.o libsmb/asn1.o \
libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \
libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
- libsmb/clistr.o lib/util_seaccess.o \
- libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \
+ libsmb/clistr.o libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o $(ERRORMAP_OBJ) libsmb/clirap2.o \
$(DOSERR_OBJ) \
- $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
+ $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
@@ -326,14 +337,11 @@ LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
- passdb/util_sam_sid.o passdb/util_builtin.o passdb/pdb_compat.o \
- passdb/lookup_sid.o \
- passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \
- lib/system_smbd.o lib/account_pol.o lib/privileges.o
-
-XML_OBJ = passdb/pdb_xml.o
-MYSQL_OBJ = passdb/pdb_mysql.o
-PGSQL_OBJ = passdb/pdb_pgsql.o
+ passdb/util_wellknown.o passdb/util_builtin.o passdb/pdb_compat.o \
+ passdb/util_unixsids.o passdb/lookup_sid.o \
+ passdb/login_cache.o @PDB_STATIC@ \
+ lib/account_pol.o lib/privileges.o
+
DEVEL_HELP_WEIRD_OBJ = modules/weird.o
CP850_OBJ = modules/CP850.o
CP437_OBJ = modules/CP437.o
@@ -350,7 +358,7 @@ 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
+NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o smbd/notify_fam.o
VFS_AUDIT_OBJ = modules/vfs_audit.o
VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o
@@ -392,8 +400,9 @@ SMBD_OBJ_MAIN = smbd/server.o
BUILDOPT_OBJ = smbd/build_options.o
SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
- smbd/utmp.o smbd/session.o \
- smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
+ smbd/utmp.o smbd/session.o smbd/map_username.o \
+ smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o \
+ smbd/share_access.o smbd/fileio.o \
smbd/ipc.o smbd/lanman.o smbd/negprot.o \
smbd/message.o smbd/nttrans.o smbd/pipes.o \
smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
@@ -407,7 +416,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/change_trust_pw.o smbd/fake_file.o \
smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \
$(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \
- $(MANGLE_OBJ) @VFS_STATIC@
+ smbd/dmapi.o $(MANGLE_OBJ) @VFS_STATIC@
SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
$(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) \
@@ -441,16 +450,9 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \
nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
-NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \
+NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
-WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \
- wrepld/partners.o
-
-WREPL_OBJ = $(WREPL_OBJ1) $(PARAM_OBJ) $(UBIQX_OBJ) \
- $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
- $(LIBSAMBA_OBJ)
-
SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
web/swat.o web/neg_lang.o
@@ -465,12 +467,13 @@ SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
- $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ)
+ $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) \
+ $(DOSERR_OBJ)
SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
- $(SECRETS_OBJ) $(LIBSAMBA_OBJ) \
+ $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) \
$(PRINTBASE_OBJ) $(ERRORMAP_OBJ)
SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
@@ -479,12 +482,12 @@ SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
TESTPARM_OBJ = utils/testparm.o \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
- $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
+ $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
SMBPASSWD_OBJ = utils/smbpasswd.o utils/passwd_util.o $(PASSCHANGE_OBJ) \
$(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \
$(GROUPDB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
- $(POPT_OBJS) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ)
+ $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ)
PDBEDIT_OBJ = utils/pdbedit.o utils/passwd_util.o $(PARAM_OBJ) $(PASSDB_OBJ) \
$(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) \
@@ -497,9 +500,9 @@ 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/display_sec.o rpcclient/cmd_ds.o \
- rpcclient/cmd_echo.o rpcclient/cmd_shutdown.o \
- rpcclient/cmd_test.o
+ rpcclient/cmd_ds.o rpcclient/cmd_echo.o \
+ rpcclient/cmd_shutdown.o rpcclient/cmd_test.o \
+ lib/display_sec.o
RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \
@@ -508,9 +511,11 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
$(SMBLDAP_OBJ) $(DCUTIL_OBJ)
-PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.@PICSUFFIX@ \
- nsswitch/wb_common.@PICSUFFIX@ lib/replace1.@PICSUFFIX@ \
- lib/snprintf.@PICSUFFIX@
+PAM_WINBIND_OBJ = nsswitch/pam_winbind.o $(WBCOMMON_OBJ) \
+ lib/replace1.o $(SNPRINTF_OBJ) @BUILD_INIPARSER@
+
+PAM_WINBIND_PICOBJ = $(PAM_WINBIND_OBJ:.o=.@PICSUFFIX@)
+
SMBW_OBJ1 = smbwrapper/smbw.o \
smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \
@@ -544,13 +549,15 @@ LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o
LIBBIGBALLOFMUD_MAJOR = 0
-LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \
+LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_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
+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_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
@@ -565,7 +572,9 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
utils/net_status.o utils/net_rpc_printer.o utils/net_rpc_rights.o \
- utils/net_rpc_service.o utils/net_rpc_registry.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
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -573,7 +582,8 @@ NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(LIBMSRPC_OBJ) $(IDMAP_OBJ) \
$(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \
$(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \
- $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ)
+ $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ) $(READLINE_OBJ) \
+ lib/display_sec.o
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ)
@@ -585,8 +595,12 @@ MNT_OBJ = client/smbmnt.o lib/replace.o $(VERSION_OBJ) $(SNPRINTF_OBJ)
UMOUNT_OBJ = client/smbumount.o
-NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(LIBNMB_OBJ) \
- $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
+CIFS_MOUNT_OBJ = client/mount.cifs.o
+
+CIFS_UMOUNT_OBJ = client/umount.cifs.o
+
+NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(LIBNMB_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) \
+ $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \
torture/denytest.o torture/mangle_test.o
@@ -629,11 +643,13 @@ SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
EVTLOGADM_OBJ0 = utils/eventlogadm.o
EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \
- $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ0) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
- registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \
+ $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
+ $(SECRETS_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) libsmb/nterr.o
+TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
+ $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LIBSAMBA_OBJ) $(SECRETS_OBJ)
RPCTORTURE_OBJ = torture/rpctorture.o \
rpcclient/display.o \
@@ -643,9 +659,9 @@ RPCTORTURE_OBJ = torture/rpctorture.o \
rpcclient/cmd_srvsvc.o \
rpcclient/cmd_netlogon.o \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
- $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ)
+ $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) $(SECRETS_OBJ)
-DEBUG2HTML_OBJ = utils/debug2html.o ubiqx/debugparse.o
+DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o
SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(SECRETS_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ)
@@ -679,9 +695,10 @@ CAC_PICOBJS = $(CAC_OBJ:.o=.@PICSUFFIX@)
PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \
- pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \
- $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
- $(SECRETS_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ)
+ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \
+ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+ $(SECRETS_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ) \
+ $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.@PICSUFFIX@)
@@ -703,7 +720,9 @@ WINBINDD_OBJ1 = \
nsswitch/winbindd_ads.o \
nsswitch/winbindd_passdb.o \
nsswitch/winbindd_dual.o \
- nsswitch/winbindd_async.o
+ nsswitch/winbindd_async.o \
+ nsswitch/winbindd_creds.o \
+ nsswitch/winbindd_cred_cache.o
WINBINDD_OBJ = \
$(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -712,10 +731,11 @@ WINBINDD_OBJ = \
$(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \
$(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
$(DCUTIL_OBJ) $(IDMAP_OBJ) \
- $(AFS_OBJ) $(AFS_SETTOKEN_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)
+ $(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@
@@ -724,6 +744,9 @@ WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.@PICSUFFIX@) lib/snprintf.@PICSUFFIX
POPT_OBJS=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)
TDBTOOL_OBJ = tdb/tdbtool.o $(TDBBASE_OBJ) $(SNPRINTF_OBJ)
@@ -735,16 +758,20 @@ NTLM_AUTH_OBJ1 = utils/ntlm_auth.o utils/ntlm_auth_diagnostics.o
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_OBJ0) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+ libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o
######################################################################
# now the rules...
######################################################################
-all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \
- $(MODULES) @EXTRA_ALL_TARGETS@
+all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(ROOT_SBIN_PROGS) \
+ $(SHLIBS) $(MODULES) $(PAM_MODULES) @EXTRA_ALL_TARGETS@
-pam_smbpass : SHOWFLAGS bin/pam_smbpass.@SHLIBEXT@
+pam_modules : $(PAM_MODULES)
+
+pam_smbpass : SHOWFLAGS proto_exists bin/pam_smbpass.@SHLIBEXT@
+
+pam_winbind : SHOWFLAGS proto_exists bin/pam_winbind.@SHLIBEXT@
smbwrapper : SHOWFLAGS @SMBWRAPPER@
@@ -777,7 +804,7 @@ eventlogadm: SHOWFLAGS bin/eventlogadm@EXEEXT@
talloctort : SHOWFLAGS bin/talloctort@EXEEXT@
nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ @WINBIND_NSS@ \
- @WINBIND_WINS_NSS@ nsswitch/pam_winbind.@SHLIBEXT@
+ @WINBIND_WINS_NSS@ bin/pam_winbind.@SHLIBEXT@
wins : SHOWFLAGS @WINBIND_WINS_NSS@
@@ -785,7 +812,7 @@ modules: SHOWFLAGS proto_exists $(MODULES)
cac: SHOWFLAGS bin/libmsrpc.@SHLIBEXT@ bin/libmsrpc.a
-everything: all libsmbclient debug2html smbfilter talloctort modules torture eventlogadm \
+everything: all libsmbclient debug2html smbfilter talloctort modules torture \
$(EVERYTHING_PROGS)
.SUFFIXES:
@@ -810,25 +837,20 @@ MAKEDIR = || exec false; \
.c.o:
@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)'";\
+ $(CC_CHECKER) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $< -o $@;\
+ fi
@echo Compiling $*.c
- @$(CC) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $< \
- -o $@
+ @$(CC) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $< -o $@
@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:
+pch: proto_exists
rm -f $(srcdir)/include/includes.h.gch
$(CC) -I. -I$(srcdir) $(FLAGS) @PIE_CFLAGS@ -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch
-##
-## Targets for 'make test'
-##
-test: all torture
- @echo Running Samba 3 Test suite
- @sh ./script/tests/runtests.sh t_dir
-
-
# These dependencies are only approximately correct: we want to make
# sure Samba's paths are updated if ./configure is re-run. Really it
# would be nice if "make prefix=/opt/samba all" also rebuilt things,
@@ -868,6 +890,10 @@ smbd/build_options.c: include/config.h.in script/mkbuildoptions.awk
.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%'` $@
@@ -881,16 +907,12 @@ bin/smbd@EXEEXT@: $(SMBD_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBD_OBJ) $(LDFLAGS) $(LDAP_LIBS) \
$(KRB5LIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) \
- $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@
+ $(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)
-bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy
- @echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(WREPL_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@
-
bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \
@@ -912,7 +934,7 @@ bin/smbctool@EXEEXT@: $(TOOL_OBJ) @BUILD_POPT@ bin/.dummy
bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS)
bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -934,6 +956,14 @@ bin/smbumount@EXEEXT@: $(UMOUNT_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -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)
+
+bin/umount.cifs@EXEEXT@: $(CIFS_UMOUNT_OBJ) bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -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@
@@ -951,12 +981,12 @@ bin/smbcontrol@EXEEXT@: $(SMBCONTROL_OBJ) @BUILD_POPT@ bin/.dummy
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) @PIE_LDFLAGS@ -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
-bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) bin/.dummy
+bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \
- $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -976,7 +1006,7 @@ bin/nmblookup@EXEEXT@: $(NMBLOOKUP_OBJ) @BUILD_POPT@ bin/.dummy
bin/smbtorture@EXEEXT@: $(SMBTORTURE_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy
@echo Linking $@
@@ -988,7 +1018,7 @@ bin/masktest@EXEEXT@: $(MASKTEST_OBJ) bin/.dummy
bin/msgtest@EXEEXT@: $(MSGTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbcacls@EXEEXT@: $(SMBCACLS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -1000,7 +1030,7 @@ bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy
bin/eventlogadm@EXEEXT@: $(EVTLOGADM_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
@echo Linking $@
@@ -1012,7 +1042,7 @@ bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy
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)
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) @SMBD_LIBS@
bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -1165,7 +1195,7 @@ 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) \
- @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
+ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(NSCD_LIBS)
# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
# libraries. Add to the appropriate PICOBJ variable instead.
@@ -1173,18 +1203,18 @@ bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
@WINBIND_NSS@: $(WINBIND_NSS_PICOBJS)
@echo "Linking $@"
@$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_PICOBJS) \
- @WINBIND_NSS_EXTRA_LIBS@ @SONAMEFLAG@`basename $@`@SONAMEVERSIONSUFFIX@
+ @WINBIND_NSS_EXTRA_LIBS@ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
@WINBIND_WINS_NSS@: $(WINBIND_WINS_NSS_PICOBJS)
@echo "Linking $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_PICOBJS) \
$(LDAP_LIBS) $(KRB5LIBS) \
- @SONAMEFLAG@`basename $@`@SONAMEVERSIONSUFFIX@
+ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
-nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_PICOBJ) bin/.dummy
- @echo "Linking $@"
+bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_PICOBJ) bin/.dummy
+ @echo "Linking shared library $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_PICOBJ) \
- @SONAMEFLAG@`basename $@` -lpam
+ @SONAMEFLAG@`basename $@` -lpam @INIPARSERLIBS@
bin/rhosts.@SHLIBEXT@: $(AUTH_RHOSTS_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@@ -1218,16 +1248,6 @@ bin/sam.@SHLIBEXT@: $(AUTH_SAM_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SAM_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
-bin/mysql.@SHLIBEXT@: $(MYSQL_OBJ:.o=.@PICSUFFIX@)
- @echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(MYSQL_OBJ:.o=.@PICSUFFIX@) @MYSQL_LIBS@ \
- @SONAMEFLAG@`basename $@`
-
-bin/pgsql.@SHLIBEXT@: $(PGSQL_OBJ:.o=.@PICSUFFIX@)
- @echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(PGSQL_OBJ:.o=.@PICSUFFIX@) @PGSQL_LIBS@ \
- @SONAMEFLAG@`basename $@`
-
bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.@PICSUFFIX@
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) $(LDAP_LIBS) -o $@ passdb/pdb_ldap.@PICSUFFIX@ \
@@ -1273,11 +1293,6 @@ bin/macosxfs.@SHLIBEXT@: $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@)
@$(SHLD) $(LDSHFLAGS) -o $@ $(CHARSET_MACOSXFS_OBJ:.o=.@PICSUFFIX@) \
-framework CoreFoundation @SONAMEFLAG@`basename $@`
-bin/xml.@SHLIBEXT@: $(XML_OBJ:.o=.@PICSUFFIX@)
- @echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(XML_OBJ:.o=.@PICSUFFIX@) @XML_LIBS@ \
- @SONAMEFLAG@`basename $@`
-
bin/audit.@SHLIBEXT@: $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AUDIT_OBJ:.o=.@PICSUFFIX@) \
@@ -1390,7 +1405,12 @@ bin/t_push_ucs2@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_push_ucs2.o
bin/t_snprintf@EXEEXT@: lib/snprintf.c
$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) -DTEST_SNPRINTF lib/snprintf.c -lm
-install: installbin installman installscripts installdat installswat installmodules @INSTALL_LIBSMBCLIENT@ @INSTALL_LIBMSRPC@
+
+bin/timelimit@EXEEXT@: script/tests/timelimit.o
+ @echo Linking $@
+ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) script/tests/timelimit.o
+
+install: installservers installbin @INSTALL_CIFSMOUNT@ installman installscripts installdat installswat installmodules @INSTALL_LIBSMBCLIENT@ @INSTALL_LIBMSRPC@ @INSTALL_PAM_MODULES@
install-everything: install installmodules
@@ -1403,25 +1423,27 @@ install-everything: install installmodules
# is not used
installdirs:
- @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(PRIVATEDIR) $(DESTDIR)$(PIDDIR) $(DESTDIR)$(LOCKDIR) $(DESTDIR)$(MANDIR)
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(BINDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(PRIVATEDIR) $(PIDDIR) $(LOCKDIR) $(MANDIR)
installservers: all installdirs
- @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS)
+ @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(SBINDIR) $(SBIN_PROGS)
installbin: all installdirs
- @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS)
- @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(BIN_PROGS)
+ @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(BINDIR) $(BIN_PROGS)
+installcifsmount: @CIFSMOUNT_PROGS@
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(ROOTSBINDIR)
+ @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(ROOTSBINDIR) @CIFSMOUNT_PROGS@
# Some symlinks are required for the 'probing' of modules.
# This mechanism should go at some point..
installmodules: modules installdirs
- @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(VFSLIBDIR) $(VFS_MODULES)
- @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(PDBLIBDIR) $(PDB_MODULES)
- @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(RPCLIBDIR) $(RPC_MODULES)
- @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(IDMAPLIBDIR) $(IDMAP_MODULES)
- @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(CHARSETLIBDIR) $(CHARSET_MODULES)
- @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(AUTHLIBDIR) $(AUTH_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(VFSLIBDIR) $(VFS_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(PDBLIBDIR) $(PDB_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(RPCLIBDIR) $(RPC_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(IDMAPLIBDIR) $(IDMAP_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ ldapsam_compat.@SHLIBEXT@
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) rhosts.@SHLIBEXT@ hostsequiv.@SHLIBEXT@
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) sam.@SHLIBEXT@ sam_ignoredomain.@SHLIBEXT@
@@ -1432,28 +1454,36 @@ installscripts: installdirs
@$(SHELL) $(srcdir)/script/installscripts.sh $(INSTALLPERMS) $(DESTDIR)$(BINDIR) $(SCRIPTS)
installdat: installdirs
- @$(SHELL) $(srcdir)/script/installdat.sh $(DESTDIR)$(LIBDIR) $(srcdir)
+ @$(SHELL) $(srcdir)/script/installdat.sh $(DESTDIR) $(LIBDIR) $(srcdir)
installmsg: installdirs
- @$(SHELL) $(srcdir)/script/installmsg.sh $(DESTDIR)$(LIBDIR) $(srcdir)
+ @$(SHELL) $(srcdir)/script/installmsg.sh $(DESTDIR) $(LIBDIR) $(srcdir)
installswat: installdirs installmsg
- @$(SHELL) $(srcdir)/script/installswat.sh $(DESTDIR)$(SWATDIR) $(srcdir)
+ @$(SHELL) $(srcdir)/script/installswat.sh $(DESTDIR) $(SWATDIR) $(srcdir)
installclientlib: installdirs libsmbclient
- @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(LIBDIR)
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(LIBDIR)
-$(INSTALLLIBCMD_SH) bin/libsmbclient.@SHLIBEXT@ $(DESTDIR)$(LIBDIR)
-$(INSTALLLIBCMD_A) bin/libsmbclient.a $(DESTDIR)$(LIBDIR)
- @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)${prefix}/include
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) ${prefix}/include
-$(INSTALLCMD) $(srcdir)/include/libsmbclient.h $(DESTDIR)${prefix}/include
installlibmsrpc: installdirs libmsrpc
- @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(LIBDIR)
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(LIBDIR)
-$(INSTALLLIBCMD_SH) bin/libmsrpc.@SHLIBEXT@ $(DESTDIR)$(LIBDIR)
-$(INSTALLLIBCMD_A) bin/libmsrpc.a $(DESTDIR)$(LIBDIR)
- @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)${prefix}/include
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) ${prefix}/include
-$(INSTALLCMD) $(srcdir)/include/libmsrpc.h $(DESTDIR)${prefix}/include
+installpammodules: $(PAM_MODULES)
+ @$(SHELL) $(srcdir)/script/installdirs.sh $(INSTALLPERMS) $(DESTDIR) $(PAMMODULESDIR)
+ @for module in $(PAM_MODULES); do \
+ echo "Installing module $${module} as $(DESTDIR)/$(PAMMODULESDIR)/$${module}.@SHLIBEXT@ "; \
+ install -m $(INSTALLPERMS) bin/$${module}.@SHLIBEXT@ \
+ "$(DESTDIR)/$(PAMMODULESDIR)"; \
+ done
+
# Python extensions
PYTHON_OBJS = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \
@@ -1497,7 +1527,7 @@ installman: installdirs
showlayout:
@echo "Samba will be installed into:"
- @echo " basedir: $(BASEDIR)"
+ @echo " prefix: $(prefix)"
@echo " bindir: $(BINDIR)"
@echo " sbindir: $(SBINDIR)"
@echo " libdir: $(LIBDIR)"
@@ -1510,46 +1540,78 @@ showlayout:
@echo " swatdir: $(SWATDIR)"
-uninstall: uninstallman uninstallbin uninstallscripts uninstallmodules
+uninstall: uninstallman uninstallservers uninstallbin @UNINSTALL_CIFSMOUNT@ uninstallscripts uninstalldat uninstallswat uninstallmodules @UNINSTALL_LIBSMBCLIENT@ @UNINSTALL_LIBMSRPC@ @UNINSTALL_PAM_MODULES@
uninstallman:
@$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C
+uninstallservers:
+ @$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(SBINDIR) $(SBIN_PROGS)
+
uninstallbin:
- @$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(SBIN_PROGS)
- @$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(BIN_PROGS)
+ @$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(BINDIR) $(BIN_PROGS)
+
+uninstallcifsmount:
+ @$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(ROOTSBINDIR) @CIFSMOUNT_PROGS@
uninstallmodules:
- @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(VFSLIBDIR) $(DESTDIR)$(VFS_MODULES)
- @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(PDBLIBDIR) $(DESTDIR)$(PDB_MODULES)
- @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(RPCLIBDIR) $(DESTDIR)$(RPC_MODULES)
- @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(CHARSETLIBDIR) $(DESTDIR)$(CHARSET_MODULES)
- @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(AUTHLIBDIR) $(DESTDIR)$(AUTH_MODULES)
+ @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(VFSLIBDIR) $(VFS_MODULES)
+ @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(PDBLIBDIR) $(PDB_MODULES)
+ @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(RPCLIBDIR) $(RPC_MODULES)
+ @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(IDMAPLIBDIR) $(IDMAP_MODULES)
+ @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
+ @$(SHELL) $(srcdir)/script/uninstallmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
uninstallscripts:
@$(SHELL) $(srcdir)/script/uninstallscripts.sh $(INSTALLPERMS) $(DESTDIR)$(BINDIR) $(SCRIPTS)
+uninstalldat:
+ @$(SHELL) $(srcdir)/script/uninstalldat.sh $(DESTDIR) $(LIBDIR) $(srcdir)
+
+uninstallmsg:
+ @$(SHELL) $(srcdir)/script/uninstallmsg.sh $(DESTDIR) $(LIBDIR) $(srcdir)
+
+uninstallswat: uninstallmsg
+ @$(SHELL) $(srcdir)/script/uninstallswat.sh $(DESTDIR) $(SWATDIR) $(srcdir)
+
+uninstallclientlib: installdirs libsmbclient
+ -$(UNINSTALLLIBCMD_SH) $(DESTDIR)$(LIBDIR)/libsmbclient.@SHLIBEXT@
+ -$(UNINSTALLLIBCMD_A) $(DESTDIR)$(LIBDIR)/libsmbclient.a
+ -rm -f $(DESTDIR)${prefix}/include/libsmbclient.h
+
+uninstalllibmsrpc: installdirs libmsrpc
+ -$(UNINSTALLLIBCMD_SH) $(DESTDIR)$(LIBDIR)/libmsrpc.@SHLIBEXT@
+ -$(UNINSTALLLIBCMD_A) $(DESTDIR)$(LIBDIR)/libmsrpc.a
+ -rm -f $(DESTDIR)${prefix}/include/libmsrpc.h
+
+uninstallpammodules:
+ @for module in $(PAM_MODULES); do \
+ echo "Removing $(DESTDIR)/$(PAMMODULESDIR)/$${module}.@SHLIBEXT@ "; \
+ rm -f "$(DESTDIR)/$(PAMMODULESDIR)/$${module}.@SHLIBEXT@"; \
+ done
+
# Toplevel clean files
TOPFILES=dynconfig.o dynconfig.@PICSUFFIX@
clean: delheaders python_clean
-rm -f core */*~ *~ */*.o */*.@PICSUFFIX@ */*.@SHLIBEXT@ \
- $(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(MODULES) \
- $(TORTURE_PROGS) $(LIBSMBCLIENT) $(LIBSMBSHAREMODES) \
- $(EVERYTHING_PROGS) $(LIBMSRPC) .headers.stamp
+ $(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(ROOT_SBIN_PROGS) \
+ $(MODULES) $(TORTURE_PROGS) $(LIBSMBCLIENT) \
+ $(LIBSMBSHAREMODES) $(EVERYTHING_PROGS) $(LIBMSRPC) \
+ .headers.stamp
-rm -rf t_dir
# Making this target will just make sure that the prototype files
# exist, not necessarily that they are up to date. Since they're
# removed by "make clean" this will always be run when you do anything
# afterwards.
-proto_exists: include/proto.h include/wrepld_proto.h include/build_env.h \
+proto_exists: include/proto.h include/build_env.h \
nsswitch/winbindd_proto.h web/swat_proto.h \
client/client_proto.h utils/net_proto.h utils/ntlm_auth_proto.h smbd/build_options.c
delheaders:
@echo Removing prototype headers
- @rm -f include/proto.h include/build_env.h include/wrepld_proto.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
@@ -1567,12 +1629,6 @@ include/build_env.h: script/build_env.sh
@$(SHELL) $(srcdir)/script/build_env.sh $(srcdir) $(builddir) $(CC) \
> $(builddir)/include/build_env.h
-include/wrepld_proto.h:
- @echo Building include/wrepld_proto.h
- @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \
- -h _WREPLD_PROTO_H_ $(builddir)/include/wrepld_proto.h \
- $(WREPL_OBJ1)
-
nsswitch/winbindd_proto.h:
@cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \
-h _WINBINDD_PROTO_H_ $(builddir)/nsswitch/winbindd_proto.h \
@@ -1611,7 +1667,6 @@ headers:
$(MAKE) smbd/build_options.c; \
$(MAKE) include/proto.h; \
$(MAKE) include/build_env.h; \
- $(MAKE) include/wrepld_proto.h; \
$(MAKE) nsswitch/winbindd_proto.h; \
$(MAKE) web/swat_proto.h; \
$(MAKE) client/client_proto.h; \
@@ -1630,7 +1685,8 @@ ctags:
ctags `find $(srcdir) -name "*.[ch]" | grep -v /CVS/`
realclean: clean delheaders
- -rm -f config.log bin/.dummy script/findsmb
+ -rm -f config.log bin/.dummy script/findsmb script/gen-8bit-gap.sh
+ -rm -f script/installbin.sh script/uninstallbin.sh
distclean: realclean
-rm -f include/stamp-h
@@ -1665,28 +1721,25 @@ Makefile: $(srcdir)/Makefile.in config.status
######################################################################
# Samba Testing Framework
-# FIXME: LD_LIBRARY_PATH is not portable, but in the absence of
-# libtool I don't know a better way to do it. Perhaps we should fix
-# libbigballofmud to link statically?
+# Check for PAM module problems. Specifically, check that every module we
+# built can actually be loaded by a minimal PAM-aware application.
+test_pam_modules: pam_modules
+ @echo "Testing $(PAM_MODULES) "
+ @for module in $(PAM_MODULES); do \
+ ./script/tests/dlopen.sh -lpam -ldl bin/$${module}.@SHLIBEXT@ \
+ || exit 1; \
+ done
+
##
-## not working...to be replaced by 'make test' --jerry
+## Targets for 'make test'
##
-#check: check-programs
-# LD_LIBRARY_PATH="`pwd`/bin:$$LD_LIBRARY_PATH" \
-# PATH="`pwd`/bin:$$PATH" \
-# python stf/standardcheck.py; \
-# if test -n "$(PYTHON)"; then \
-# python stf/pythoncheck.py; \
-# fi
-
-# These are called by the test suite and need to be built before
-# running it. For the time being we don't build all of BIN_PROGS,
-# because they're not all needed.
-# check-programs: bin/t_strcmp bin/t_strstr bin/t_push_ucs2 bin/smbcontrol bin/t_snprintf bin/t_asn1
-
-#test: all
-# @if test -z "$(SMB4TORTURE)"; then \
-# echo "Please set the SMB4TORTURE environment variable"; \
-# exit 1; \
-# fi
-# ./script/smb4torture.sh `pwd`/prefix-test $(SMB4TORTURE)
+test: all torture bin/timelimit
+ @echo Running Test suite
+ @sh ./script/tests/selftest.sh ${selftest_prefix}/st all "${smbtorture4_path}"
+
+valgrindtest: all torture bin/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}"
diff --git a/source/VERSION b/source/VERSION
index 2bc9da4fc29..eed177544cf 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -25,7 +25,7 @@
########################################################
SAMBA_VERSION_MAJOR=3
SAMBA_VERSION_MINOR=0
-SAMBA_VERSION_RELEASE=22
+SAMBA_VERSION_RELEASE=23
########################################################
# 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 af93aa23685..86c43f80dc0 100644
--- a/source/aclocal.m4
+++ b/source/aclocal.m4
@@ -56,7 +56,7 @@ AC_DEFUN(SMB_MODULE,
[$6]
string_shared_modules="$string_shared_modules $1"
elif test x"$DEST" = xSTATIC; then
- [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init();"
+ [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init();"
string_static_modules="$string_static_modules $1"
$4_STATIC="$$4_STATIC $2"
AC_SUBST($4_STATIC)
diff --git a/source/auth/auth.c b/source/auth/auth.c
index df7d6fc9c60..5329e736ff1 100644
--- a/source/auth/auth.c
+++ b/source/auth/auth.c
@@ -196,7 +196,7 @@ static BOOL check_domain_match(const char *user, const char *domain)
* function auth_get_challenge().
*
* @param server_info If successful, contains information about the authentication,
- * including a SAM_ACCOUNT struct describing the user.
+ * including a struct samu struct describing the user.
*
* @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
*
@@ -216,10 +216,10 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
return NT_STATUS_LOGON_FAILURE;
DEBUG(3, ("check_ntlm_password: Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n",
- user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str));
+ user_info->client_domain, user_info->smb_name, user_info->wksta_name));
DEBUG(3, ("check_ntlm_password: mapped user is: [%s]\\[%s]@[%s]\n",
- user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str));
+ user_info->domain, user_info->internal_username, user_info->wksta_name));
if (auth_context->challenge.length != 8) {
DEBUG(0, ("check_ntlm_password: Invalid challenge stored for this auth context - cannot continue\n"));
@@ -243,14 +243,14 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
#endif
/* This needs to be sorted: If it doesn't match, what should we do? */
- if (!check_domain_match(user_info->smb_name.str, user_info->domain.str))
+ if (!check_domain_match(user_info->smb_name, user_info->domain))
return NT_STATUS_LOGON_FAILURE;
for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) {
NTSTATUS result;
mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name,
- user_info->domain.str, user_info->smb_name.str);
+ user_info->domain, user_info->smb_name);
result = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info);
@@ -265,10 +265,10 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n",
- auth_method->name, user_info->smb_name.str));
+ auth_method->name, user_info->smb_name));
} else {
DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n",
- auth_method->name, user_info->smb_name.str, nt_errstr(nt_status)));
+ auth_method->name, user_info->smb_name, nt_errstr(nt_status)));
}
talloc_destroy(mem_ctx);
@@ -302,8 +302,8 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
DEBUG((*server_info)->guest ? 5 : 2,
("check_ntlm_password: %sauthentication for user [%s] -> [%s] -> [%s] succeeded\n",
(*server_info)->guest ? "guest " : "",
- user_info->smb_name.str,
- user_info->internal_username.str,
+ user_info->smb_name,
+ user_info->internal_username,
unix_username));
}
@@ -313,8 +313,8 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
/* failed authentication; check for guest lapping */
DEBUG(2, ("check_ntlm_password: Authentication for user [%s] -> [%s] FAILED with error %s\n",
- user_info->smb_name.str, user_info->internal_username.str,
- nt_errstr(nt_status)));
+ user_info->smb_name, user_info->internal_username,
+ nt_errstr(nt_status)));
ZERO_STRUCTP(server_info);
return nt_status;
diff --git a/source/auth/auth_builtin.c b/source/auth/auth_builtin.c
index 96c2221652e..d4d6d49e40c 100644
--- a/source/auth/auth_builtin.c
+++ b/source/auth/auth_builtin.c
@@ -41,8 +41,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context,
/* mark this as 'not for me' */
NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
- if (!(user_info->internal_username.str
- && *user_info->internal_username.str)) {
+ if (!(user_info->internal_username
+ && *user_info->internal_username)) {
nt_status = make_server_info_guest(server_info);
}
@@ -84,7 +84,7 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_
NTSTATUS nt_status;
fstring user;
long error_num;
- fstrcpy(user, user_info->smb_name.str);
+ fstrcpy(user, user_info->smb_name);
if (strnequal("NT_STATUS", user, strlen("NT_STATUS"))) {
strupper_m(user);
diff --git a/source/auth/auth_compat.c b/source/auth/auth_compat.c
index 2ac70d73546..bd5d7f02290 100644
--- a/source/auth/auth_compat.c
+++ b/source/auth/auth_compat.c
@@ -84,7 +84,7 @@ static NTSTATUS pass_check_smb(const char *smb_name,
} else {
nt_status = check_plaintext_password(smb_name, plaintext_password, &server_info);
}
- free_server_info(&server_info);
+ TALLOC_FREE(server_info);
return nt_status;
}
diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c
index 266851b2292..c91cbf7af11 100644
--- a/source/auth/auth_domain.c
+++ b/source/auth/auth_domain.c
@@ -210,6 +210,10 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
return nt_status;
}
+ /* store a successful connection */
+
+ saf_store( domain, cli->desthost );
+
ZERO_STRUCT(info3);
/*
@@ -221,9 +225,9 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
mem_ctx,
user_info->logon_parameters,/* flags such as 'allow workstation logon' */
dc_name, /* server name */
- user_info->smb_name.str, /* user name logging on. */
- user_info->domain.str, /* domain name */
- user_info->wksta_name.str, /* workstation name */
+ user_info->smb_name, /* user name logging on. */
+ user_info->domain, /* domain name */
+ user_info->wksta_name, /* workstation name */
chal, /* 8 byte challenge. */
user_info->lm_resp, /* lanman 24 byte response */
user_info->nt_resp, /* nt 24 byte response */
@@ -237,8 +241,8 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("domain_client_validate: unable to validate password "
"for user %s in domain %s to Domain controller %s. "
- "Error was %s.\n", user_info->smb_name.str,
- user_info->domain.str, dc_name,
+ "Error was %s.\n", user_info->smb_name,
+ user_info->domain, dc_name,
nt_errstr(nt_status)));
/* map to something more useful */
@@ -247,13 +251,13 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
}
} else {
nt_status = make_server_info_info3(mem_ctx,
- user_info->internal_username.str,
- user_info->smb_name.str,
+ user_info->internal_username,
+ user_info->smb_name,
domain,
server_info,
&info3);
- netsamlogon_cache_store( user_info->smb_name.str, &info3 );
+ netsamlogon_cache_store( user_info->smb_name, &info3 );
}
/* Note - once the cli stream is shutdown the mem_ctx used
@@ -296,7 +300,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
* password file.
*/
- if(strequal(get_global_sam_name(), user_info->domain.str)) {
+ if(strequal(get_global_sam_name(), user_info->domain)) {
DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n"));
return NT_STATUS_NOT_IMPLEMENTED;
}
@@ -305,7 +309,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
DEBUG(5,("check_ntdomain_security: unable to locate a DC for domain %s\n",
- user_info->domain.str));
+ user_info->domain));
return NT_STATUS_NO_LOGON_SERVERS;
}
@@ -360,9 +364,9 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
* Check that the requested domain is not our own machine name or domain name.
*/
- if( strequal(get_global_sam_name(), user_info->domain.str)) {
+ if( strequal(get_global_sam_name(), user_info->domain)) {
DEBUG(3,("check_trustdomain_security: Requested domain [%s] was for this machine.\n",
- user_info->domain.str));
+ user_info->domain));
return NT_STATUS_NOT_IMPLEMENTED;
}
@@ -371,7 +375,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
The logic is that if we know nothing about the domain, that
user is not known to us and does not exist */
- if ( !is_trusted_domain( user_info->domain.str ) )
+ if ( !is_trusted_domain( user_info->domain ) )
return NT_STATUS_NOT_IMPLEMENTED;
/*
@@ -379,14 +383,17 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
* No need to become_root() as secrets_init() is done at startup.
*/
- if (!secrets_fetch_trusted_domain_password(user_info->domain.str, &trust_password,
+ if (!secrets_fetch_trusted_domain_password(user_info->domain, &trust_password,
&sid, &last_change_time)) {
- DEBUG(0, ("check_trustdomain_security: could not fetch trust account password for domain %s\n", user_info->domain.str));
+ DEBUG(0, ("check_trustdomain_security: could not fetch trust "
+ "account password for domain %s\n",
+ user_info->domain));
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("Trust password for domain %s is %s\n", user_info->domain.str, trust_password));
+ DEBUG(100, ("Trust password for domain %s is %s\n", user_info->domain,
+ trust_password));
#endif
E_md4hash(trust_password, trust_md4_password);
SAFE_FREE(trust_password);
@@ -402,15 +409,15 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
/* use get_dc_name() for consistency even through we know that it will be
a netbios name */
- if ( !get_dc_name(user_info->domain.str, NULL, dc_name, &dc_ip) ) {
+ if ( !get_dc_name(user_info->domain, NULL, dc_name, &dc_ip) ) {
DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n",
- user_info->domain.str));
+ user_info->domain));
return NT_STATUS_NO_LOGON_SERVERS;
}
nt_status = domain_client_validate(mem_ctx,
user_info,
- user_info->domain.str,
+ user_info->domain,
(uchar *)auth_context->challenge.data,
server_info,
dc_name,
diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index 2fef8f1e9b5..1d3d17d60dd 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -115,6 +115,14 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
+
+ nt_status = create_local_token(auth_ntlmssp_state->server_info);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(10, ("create_local_token failed\n"));
+ return nt_status;
+ }
+
if (auth_ntlmssp_state->server_info->user_session_key.length) {
DEBUG(10, ("Got NT session key of length %u\n",
(unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
@@ -179,7 +187,7 @@ void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
((*auth_ntlmssp_state)->auth_context->free)(&(*auth_ntlmssp_state)->auth_context);
}
if ((*auth_ntlmssp_state)->server_info) {
- free_server_info(&(*auth_ntlmssp_state)->server_info);
+ TALLOC_FREE((*auth_ntlmssp_state)->server_info);
}
talloc_destroy(mem_ctx);
*auth_ntlmssp_state = NULL;
diff --git a/source/auth/auth_rhosts.c b/source/auth/auth_rhosts.c
index b561e3d42be..23e276bc84e 100644
--- a/source/auth/auth_rhosts.c
+++ b/source/auth/auth_rhosts.c
@@ -24,33 +24,35 @@
#define DBGC_CLASS DBGC_AUTH
/****************************************************************************
- Create a SAM_ACCOUNT - either by looking in the pdb, or by faking it up from
+ Create a struct samu - either by looking in the pdb, or by faking it up from
unix info.
****************************************************************************/
-static NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account)
+static NTSTATUS auth_get_sam_account(const char *user, struct samu **account)
{
BOOL pdb_ret;
- NTSTATUS nt_status;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(account))) {
- return nt_status;
+ NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER;
+
+ if ( !(*account = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
}
become_root();
pdb_ret = pdb_getsampwnam(*account, user);
unbecome_root();
- if (!pdb_ret) {
-
- struct passwd *pass = Get_Pwnam(user);
- if (!pass)
- return NT_STATUS_NO_SUCH_USER;
+ if (!pdb_ret)
+ {
+ struct passwd *pass;
- if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*account, pass))) {
- return nt_status;
+ if ( !(pass = Get_Pwnam( user )) ) {
+ return NT_STATUS_NO_SUCH_USER;
}
+
+ nt_status = samu_set_unix( *account, pass );
}
- return NT_STATUS_OK;
+
+ return nt_status;
}
/****************************************************************************
@@ -60,116 +62,114 @@ static NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account)
static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file)
{
- int plus_allowed = 1;
- char *file_host;
- char *file_user;
- char **lines = file_lines_load(equiv_file, NULL);
- int i;
-
- DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
- if (! lines) return False;
- for (i=0; lines[i]; i++) {
- char *buf = lines[i];
- trim_char(buf,' ',' ');
-
- if (buf[0] != '#' && buf[0] != '\n')
- {
- BOOL is_group = False;
- int plus = 1;
- char *bp = buf;
- if (strcmp(buf, "NO_PLUS\n") == 0)
- {
- DEBUG(6, ("check_user_equiv NO_PLUS\n"));
- plus_allowed = 0;
- }
- else {
- if (buf[0] == '+')
- {
- bp++;
- if (*bp == '\n' && plus_allowed)
- {
- /* a bare plus means everbody allowed */
- DEBUG(6, ("check_user_equiv everybody allowed\n"));
- file_lines_free(lines);
- return True;
- }
- }
- else if (buf[0] == '-')
- {
- bp++;
- plus = 0;
- }
- if (*bp == '@')
- {
- is_group = True;
- bp++;
+ int plus_allowed = 1;
+ char *file_host;
+ char *file_user;
+ char **lines = file_lines_load(equiv_file, NULL,0);
+ int i;
+
+ DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
+ if (! lines) {
+ return False;
}
- file_host = strtok(bp, " \t\n");
- file_user = strtok(NULL, " \t\n");
- DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)",
- file_user ? file_user : "(null)" ));
- if (file_host && *file_host)
- {
- BOOL host_ok = False;
+ for (i=0; lines[i]; i++) {
+ char *buf = lines[i];
+ trim_char(buf,' ',' ');
+
+ if (buf[0] != '#' && buf[0] != '\n') {
+ BOOL is_group = False;
+ int plus = 1;
+ char *bp = buf;
+
+ if (strcmp(buf, "NO_PLUS\n") == 0) {
+ DEBUG(6, ("check_user_equiv NO_PLUS\n"));
+ plus_allowed = 0;
+ } else {
+ if (buf[0] == '+') {
+ bp++;
+ if (*bp == '\n' && plus_allowed) {
+ /* a bare plus means everbody allowed */
+ DEBUG(6, ("check_user_equiv everybody allowed\n"));
+ file_lines_free(lines);
+ return True;
+ }
+ } else if (buf[0] == '-') {
+ bp++;
+ plus = 0;
+ }
+ if (*bp == '@') {
+ is_group = True;
+ bp++;
+ }
+ file_host = strtok(bp, " \t\n");
+ file_user = strtok(NULL, " \t\n");
+ DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)",
+ file_user ? file_user : "(null)" ));
+
+ if (file_host && *file_host) {
+ BOOL host_ok = False;
#if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN)
- if (is_group)
- {
- static char *mydomain = NULL;
- if (!mydomain)
- yp_get_default_domain(&mydomain);
- if (mydomain && innetgr(file_host,remote,user,mydomain))
- host_ok = True;
- }
+ if (is_group) {
+ static char *mydomain = NULL;
+ if (!mydomain) {
+ yp_get_default_domain(&mydomain);
+ }
+ if (mydomain && innetgr(file_host,remote,user,mydomain)) {
+ host_ok = True;
+ }
+ }
#else
- if (is_group)
- {
- DEBUG(1,("Netgroups not configured\n"));
- continue;
- }
+ if (is_group) {
+ DEBUG(1,("Netgroups not configured\n"));
+ continue;
+ }
#endif
- /* is it this host */
- /* the fact that remote has come from a call of gethostbyaddr
- * means that it may have the fully qualified domain name
- * so we could look up the file version to get it into
- * a canonical form, but I would rather just type it
- * in full in the equiv file
- */
- if (!host_ok && !is_group && strequal(remote, file_host))
- host_ok = True;
-
- if (!host_ok)
- continue;
-
- /* is it this user */
- if (file_user == 0 || strequal(user, file_user))
- {
- DEBUG(5, ("check_user_equiv matched %s%s %s\n",
- (plus ? "+" : "-"), file_host,
- (file_user ? file_user : "")));
- file_lines_free(lines);
- return (plus ? True : False);
- }
+ /* is it this host */
+ /* the fact that remote has come from a call of gethostbyaddr
+ * means that it may have the fully qualified domain name
+ * so we could look up the file version to get it into
+ * a canonical form, but I would rather just type it
+ * in full in the equiv file
+ */
+
+ if (!host_ok && !is_group && strequal(remote, file_host)) {
+ host_ok = True;
+ }
+
+ if (!host_ok) {
+ continue;
+ }
+
+ /* is it this user */
+ if (file_user == 0 || strequal(user, file_user)) {
+ DEBUG(5, ("check_user_equiv matched %s%s %s\n",
+ (plus ? "+" : "-"), file_host,
+ (file_user ? file_user : "")));
+ file_lines_free(lines);
+ return (plus ? True : False);
+ }
+ }
+ }
+ }
}
- }
- }
- }
- file_lines_free(lines);
- return False;
+
+ file_lines_free(lines);
+ return False;
}
/****************************************************************************
check for a possible hosts equiv or rhosts entry for the user
****************************************************************************/
-static BOOL check_hosts_equiv(SAM_ACCOUNT *account)
+static BOOL check_hosts_equiv(struct samu *account)
{
uid_t uid;
char *fname = NULL;
fname = lp_hosts_equiv();
- if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(account), &uid)))
+ if (!sid_to_uid(pdb_get_user_sid(account), &uid))
return False;
/* note: don't allow hosts.equiv on root */
@@ -193,9 +193,9 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status;
- SAM_ACCOUNT *account = NULL;
+ struct samu *account = NULL;
if (!NT_STATUS_IS_OK(nt_status =
- auth_get_sam_account(user_info->internal_username.str,
+ auth_get_sam_account(user_info->internal_username,
&account))) {
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER))
nt_status = NT_STATUS_NOT_IMPLEMENTED;
@@ -204,8 +204,11 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex
if (check_hosts_equiv(account)) {
nt_status = make_server_info_sam(server_info, account);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE(account);
+ }
} else {
- pdb_free_sam(&account);
+ TALLOC_FREE(account);
nt_status = NT_STATUS_NOT_IMPLEMENTED;
}
@@ -236,12 +239,12 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
auth_serversupplied_info **server_info)
{
NTSTATUS nt_status;
- SAM_ACCOUNT *account = NULL;
+ struct samu *account = NULL;
pstring rhostsfile;
const char *home;
if (!NT_STATUS_IS_OK(nt_status =
- auth_get_sam_account(user_info->internal_username.str,
+ auth_get_sam_account(user_info->internal_username,
&account))) {
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER))
nt_status = NT_STATUS_NOT_IMPLEMENTED;
@@ -255,12 +258,15 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
become_root();
if (check_user_equiv(pdb_get_username(account),client_name(),rhostsfile)) {
nt_status = make_server_info_sam(server_info, account);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE(account);
+ }
} else {
- pdb_free_sam(&account);
+ TALLOC_FREE(account);
}
unbecome_root();
} else {
- pdb_free_sam(&account);
+ TALLOC_FREE(account);
nt_status = NT_STATUS_NOT_IMPLEMENTED;
}
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index 558c181f704..94e4ec414b6 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -23,8 +23,6 @@
#include "includes.h"
-extern struct timeval smb_last_time;
-
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
@@ -35,12 +33,12 @@ extern struct timeval smb_last_time;
static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
TALLOC_CTX *mem_ctx,
- SAM_ACCOUNT *sampass,
+ struct samu *sampass,
const auth_usersupplied_info *user_info,
DATA_BLOB *user_sess_key,
DATA_BLOB *lm_sess_key)
{
- uint16 acct_ctrl;
+ uint32 acct_ctrl;
const uint8 *lm_pw, *nt_pw;
const char *username = pdb_get_username(sampass);
@@ -62,8 +60,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
&user_info->lm_resp, &user_info->nt_resp,
&user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd,
username,
- user_info->smb_name.str,
- user_info->client_domain.str,
+ user_info->smb_name,
+ user_info->client_domain,
lm_pw, nt_pw, user_sess_key, lm_sess_key);
}
@@ -73,7 +71,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
bitmask.
****************************************************************************/
-static BOOL logon_hours_ok(SAM_ACCOUNT *sampass)
+static BOOL logon_hours_ok(struct samu *sampass)
{
/* In logon hours first bit is Sunday from 12AM to 1AM */
const uint8 *hours;
@@ -87,7 +85,7 @@ static BOOL logon_hours_ok(SAM_ACCOUNT *sampass)
return True;
}
- lasttime = (time_t)smb_last_time.tv_sec;
+ lasttime = time(NULL);
utctime = gmtime(&lasttime);
/* find the corresponding byte and bit */
@@ -108,15 +106,15 @@ static BOOL logon_hours_ok(SAM_ACCOUNT *sampass)
}
/****************************************************************************
- Do a specific test for a SAM_ACCOUNT being vaild for this connection
+ Do a specific test for a struct samu being vaild for this connection
(ie not disabled, expired and the like).
****************************************************************************/
static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
- SAM_ACCOUNT *sampass,
+ struct samu *sampass,
const auth_usersupplied_info *user_info)
{
- uint16 acct_ctrl = pdb_get_acct_ctrl(sampass);
+ uint32 acct_ctrl = pdb_get_acct_ctrl(sampass);
char *workstation_list;
time_t kickoff_time;
@@ -177,22 +175,22 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
fstring tok;
const char *s = workstation_list;
- const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name.str);
+ const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name);
if (machine_name == NULL)
return NT_STATUS_NO_MEMORY;
while (next_token(&s, tok, ",", sizeof(tok))) {
- DEBUG(10,("sam_account_ok: checking for workstation match %s and %s (len=%d)\n",
- tok, user_info->wksta_name.str, user_info->wksta_name.len));
- if(strequal(tok, user_info->wksta_name.str)) {
+ DEBUG(10,("sam_account_ok: checking for workstation match %s and %s\n",
+ tok, user_info->wksta_name));
+ if(strequal(tok, user_info->wksta_name)) {
invalid_ws = False;
break;
}
if (tok[0] == '+') {
DEBUG(10,("sam_account_ok: checking for workstation %s in group: %s\n",
machine_name, tok + 1));
- if (user_in_group_list(machine_name, tok + 1, NULL, 0)) {
+ if (user_in_group(machine_name, tok + 1)) {
invalid_ws = False;
break;
}
@@ -236,7 +234,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
const auth_usersupplied_info *user_info,
auth_serversupplied_info **server_info)
{
- SAM_ACCOUNT *sampass=NULL;
+ struct samu *sampass=NULL;
BOOL ret;
NTSTATUS nt_status;
NTSTATUS update_login_attempts_status;
@@ -250,19 +248,21 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
/* Can't use the talloc version here, because the returned struct gets
kept on the server_info */
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
- return nt_status;
+
+ if ( !(sampass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
}
/* get the account information */
become_root();
- ret = pdb_getsampwnam(sampass, user_info->internal_username.str);
+ ret = pdb_getsampwnam(sampass, user_info->internal_username);
unbecome_root();
if (ret == False) {
- DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb.\n", user_info->internal_username.str));
- pdb_free_sam(&sampass);
+ DEBUG(3,("check_sam_security: Couldn't find user '%s' in "
+ "passdb.\n", user_info->internal_username));
+ TALLOC_FREE(sampass);
return NT_STATUS_NO_SUCH_USER;
}
@@ -294,13 +294,13 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
}
if (updated_autolock || updated_badpw){
become_root();
- if(!pdb_update_sam_account(sampass))
+ if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
DEBUG(1, ("Failed to modify entry.\n"));
unbecome_root();
}
data_blob_free(&user_sess_key);
data_blob_free(&lm_sess_key);
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return nt_status;
}
@@ -313,7 +313,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
if (updated_autolock || updated_badpw){
become_root();
- if(!pdb_update_sam_account(sampass))
+ if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
DEBUG(1, ("Failed to modify entry.\n"));
unbecome_root();
}
@@ -321,21 +321,33 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
nt_status = sam_account_ok(mem_ctx, sampass, user_info);
if (!NT_STATUS_IS_OK(nt_status)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
data_blob_free(&user_sess_key);
data_blob_free(&lm_sess_key);
return nt_status;
}
- if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) {
+ become_root();
+ nt_status = make_server_info_sam(server_info, sampass);
+ unbecome_root();
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
+ TALLOC_FREE(sampass);
data_blob_free(&user_sess_key);
data_blob_free(&lm_sess_key);
return nt_status;
}
- (*server_info)->user_session_key = user_sess_key;
- (*server_info)->lm_session_key = lm_sess_key;
+ (*server_info)->user_session_key =
+ data_blob_talloc(*server_info, user_sess_key.data,
+ user_sess_key.length);
+ data_blob_free(&user_sess_key);
+
+ (*server_info)->lm_session_key =
+ data_blob_talloc(*server_info, lm_sess_key.data,
+ lm_sess_key.length);
+ data_blob_free(&lm_sess_key);
return nt_status;
}
@@ -369,8 +381,8 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
return NT_STATUS_LOGON_FAILURE;
}
- is_local_name = is_myname(user_info->domain.str);
- is_my_domain = strequal(user_info->domain.str, lp_workgroup());
+ is_local_name = is_myname(user_info->domain);
+ is_my_domain = strequal(user_info->domain, lp_workgroup());
/* check whether or not we service this domain/workgroup name */
@@ -379,7 +391,7 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
case ROLE_DOMAIN_MEMBER:
if ( !is_local_name ) {
DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n",
- user_info->domain.str, (lp_server_role() == ROLE_DOMAIN_MEMBER
+ user_info->domain, (lp_server_role() == ROLE_DOMAIN_MEMBER
? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
return NT_STATUS_NOT_IMPLEMENTED;
}
@@ -387,7 +399,7 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
case ROLE_DOMAIN_BDC:
if ( !is_local_name && !is_my_domain ) {
DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n",
- user_info->domain.str));
+ user_info->domain));
return NT_STATUS_NOT_IMPLEMENTED;
}
default: /* name is ok */
diff --git a/source/auth/auth_script.c b/source/auth/auth_script.c
index 1a715fca319..1bc33ec59e7 100644
--- a/source/auth/auth_script.c
+++ b/source/auth/auth_script.c
@@ -63,8 +63,8 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
return NT_STATUS_INVALID_PARAMETER;
}
- secret_str_len = strlen(user_info->domain.str) + 1 +
- strlen(user_info->smb_name.str) + 1 +
+ secret_str_len = strlen(user_info->domain) + 1 +
+ strlen(user_info->smb_name) + 1 +
16 + 1 + /* 8 bytes of challenge going to 16 */
48 + 1 + /* 24 bytes of challenge going to 48 */
48 + 1;
@@ -74,9 +74,9 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
return NT_STATUS_NO_MEMORY;
}
- safe_strcpy( secret_str, user_info->domain.str, secret_str_len - 1);
+ safe_strcpy( secret_str, user_info->domain, secret_str_len - 1);
safe_strcat( secret_str, "\n", secret_str_len - 1);
- safe_strcat( secret_str, user_info->smb_name.str, secret_str_len - 1);
+ safe_strcat( secret_str, user_info->smb_name, secret_str_len - 1);
safe_strcat( secret_str, "\n", secret_str_len - 1);
for (i = 0; i < 8; i++) {
@@ -110,7 +110,7 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
if (ret) {
DEBUG(1,("script_check_user_credentials: failed to authenticate %s\\%s\n",
- user_info->domain.str, user_info->smb_name.str ));
+ user_info->domain, user_info->smb_name ));
/* auth failed. */
return NT_STATUS_NO_SUCH_USER;
}
diff --git a/source/auth/auth_server.c b/source/auth/auth_server.c
index 7bce32ef2b2..7bec1b4128d 100644
--- a/source/auth/auth_server.c
+++ b/source/auth/auth_server.c
@@ -235,7 +235,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context
* password file.
*/
- if(is_myname(user_info->domain.str)) {
+ if(is_myname(user_info->domain)) {
DEBUG(3,("check_smbserver_security: Requested domain was for this machine.\n"));
return nt_status;
}
@@ -296,7 +296,7 @@ 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.str)) {
+ (char *)badpass, sizeof(badpass), user_info->domain)) {
/*
* We connected to the password server so we
@@ -342,11 +342,11 @@ use this machine as the password server.\n"));
if (!user_info->encrypted) {
/* Plaintext available */
- if (!cli_session_setup(cli, user_info->smb_name.str,
+ 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.str)) {
+ 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);
@@ -354,12 +354,12 @@ use this machine as the password server.\n"));
nt_status = NT_STATUS_OK;
}
} else {
- if (!cli_session_setup(cli, user_info->smb_name.str,
+ 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.str)) {
+ 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);
@@ -380,11 +380,11 @@ use this machine as the password server.\n"));
fstring real_username;
struct passwd *pass;
- if ( (pass = smb_getpwnam( user_info->internal_username.str,
+ 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);
- passwd_free(&pass);
+ TALLOC_FREE(pass);
}
else
{
diff --git a/source/auth/auth_unix.c b/source/auth/auth_unix.c
index f744cba0c43..efe5203b233 100644
--- a/source/auth/auth_unix.c
+++ b/source/auth/auth_unix.c
@@ -30,10 +30,12 @@
**/
static BOOL update_smbpassword_file(const char *user, const char *password)
{
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass;
BOOL ret;
- pdb_init_sam(&sampass);
+ if ( !(sampass = samu_new( NULL )) ) {
+ return False;
+ }
become_root();
ret = pdb_getsampwnam(sampass, user);
@@ -41,7 +43,7 @@ static BOOL update_smbpassword_file(const char *user, const char *password)
if(ret == False) {
DEBUG(0,("pdb_getsampwnam returned NULL\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
@@ -50,19 +52,19 @@ static BOOL update_smbpassword_file(const char *user, const char *password)
* users password from a login.
*/
if (!pdb_set_acct_ctrl(sampass, pdb_get_acct_ctrl(sampass) & ~ACB_DISABLED, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
if (!pdb_set_plaintext_passwd (sampass, password)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
/* Now write it into the file. */
become_root();
- ret = pdb_update_sam_account (sampass);
+ ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
unbecome_root();
@@ -70,7 +72,7 @@ static BOOL update_smbpassword_file(const char *user, const char *password)
DEBUG(3,("pdb_update_sam_account returned %d\n",ret));
}
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return ret;
}
@@ -91,13 +93,13 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context,
struct passwd *pass = NULL;
become_root();
- pass = Get_Pwnam(user_info->internal_username.str);
+ pass = Get_Pwnam(user_info->internal_username);
/** @todo This call assumes a ASCII password, no charset transformation is
done. We may need to revisit this **/
nt_status = pass_check(pass,
- pass ? pass->pw_name : user_info->internal_username.str,
+ pass ? pass->pw_name : user_info->internal_username,
(char *)user_info->plaintext_password.data,
user_info->plaintext_password.length-1,
lp_update_encrypted() ?
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 483686a9dee..4ffbba2e237 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -5,6 +5,7 @@
Copyright (C) Andrew Bartlett 2001
Copyright (C) Jeremy Allison 2000-2001
Copyright (C) Rafal Szczesniak 2002
+ 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
@@ -26,6 +27,12 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
+static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
+ const DOM_SID *user_sid,
+ const DOM_SID *group_sid,
+ BOOL is_guest,
+ int num_groupsids,
+ const DOM_SID *groupsids);
/****************************************************************************
Create a UNIX user on demand.
@@ -69,7 +76,7 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
*user_info = SMB_MALLOC_P(auth_usersupplied_info);
- if (!user_info) {
+ if (*user_info == NULL) {
DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
return NT_STATUS_NO_MEMORY;
}
@@ -78,42 +85,32 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
- (*user_info)->smb_name.str = SMB_STRDUP(smb_name);
- if ((*user_info)->smb_name.str) {
- (*user_info)->smb_name.len = strlen(smb_name);
- } else {
+ (*user_info)->smb_name = SMB_STRDUP(smb_name);
+ if ((*user_info)->smb_name == NULL) {
free_user_info(user_info);
return NT_STATUS_NO_MEMORY;
}
- (*user_info)->internal_username.str = SMB_STRDUP(internal_username);
- if ((*user_info)->internal_username.str) {
- (*user_info)->internal_username.len = strlen(internal_username);
- } else {
+ (*user_info)->internal_username = SMB_STRDUP(internal_username);
+ if ((*user_info)->internal_username == NULL) {
free_user_info(user_info);
return NT_STATUS_NO_MEMORY;
}
- (*user_info)->domain.str = SMB_STRDUP(domain);
- if ((*user_info)->domain.str) {
- (*user_info)->domain.len = strlen(domain);
- } else {
+ (*user_info)->domain = SMB_STRDUP(domain);
+ if ((*user_info)->domain == NULL) {
free_user_info(user_info);
return NT_STATUS_NO_MEMORY;
}
- (*user_info)->client_domain.str = SMB_STRDUP(client_domain);
- if ((*user_info)->client_domain.str) {
- (*user_info)->client_domain.len = strlen(client_domain);
- } else {
+ (*user_info)->client_domain = SMB_STRDUP(client_domain);
+ if ((*user_info)->client_domain == NULL) {
free_user_info(user_info);
return NT_STATUS_NO_MEMORY;
}
- (*user_info)->wksta_name.str = SMB_STRDUP(wksta_name);
- if ((*user_info)->wksta_name.str) {
- (*user_info)->wksta_name.len = strlen(wksta_name);
- } else {
+ (*user_info)->wksta_name = SMB_STRDUP(wksta_name);
+ if ((*user_info)->wksta_name == NULL) {
free_user_info(user_info);
return NT_STATUS_NO_MEMORY;
}
@@ -175,7 +172,7 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
and let the "passdb backend" handle unknown users. */
if ( !is_trusted_domain(domain) && !strequal(domain, get_global_sam_name()) )
- domain = get_default_sam_name();
+ domain = my_sam_name();
/* we know that it is a trusted domain (and we are allowing them) or it is our domain */
@@ -196,26 +193,28 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
const char *client_domain,
const char *wksta_name,
uint32 logon_parameters,
- const uchar *lm_network_pwd, int lm_pwd_len,
- const uchar *nt_network_pwd, int nt_pwd_len)
+ const uchar *lm_network_pwd,
+ int lm_pwd_len,
+ const uchar *nt_network_pwd,
+ int nt_pwd_len)
{
BOOL ret;
- NTSTATUS nt_status;
+ NTSTATUS status;
DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
- nt_status = make_user_info_map(user_info,
- smb_name, client_domain,
- wksta_name,
- lm_pwd_len ? &lm_blob : NULL,
- nt_pwd_len ? &nt_blob : NULL,
- NULL, NULL, NULL,
- True);
+ status = make_user_info_map(user_info,
+ smb_name, client_domain,
+ wksta_name,
+ lm_pwd_len ? &lm_blob : NULL,
+ nt_pwd_len ? &nt_blob : NULL,
+ NULL, NULL, NULL,
+ True);
- if (NT_STATUS_IS_OK(nt_status)) {
+ if (NT_STATUS_IS_OK(status)) {
(*user_info)->logon_parameters = logon_parameters;
}
- ret = NT_STATUS_IS_OK(nt_status) ? True : False;
+ ret = NT_STATUS_IS_OK(status) ? True : False;
data_blob_free(&lm_blob);
data_blob_free(&nt_blob);
@@ -246,8 +245,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
ZERO_STRUCT(key);
memcpy(key, dc_sess_key, 8);
- if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
- if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
+ if (lm_interactive_pwd)
+ memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
+
+ if (nt_interactive_pwd)
+ memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
#ifdef DEBUG_PASSWORD
DEBUG(100,("key:"));
@@ -275,10 +277,12 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
#endif
if (lm_interactive_pwd)
- SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
+ SMBOWFencrypt((const unsigned char *)lm_pwd, chal,
+ local_lm_response);
if (nt_interactive_pwd)
- SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
+ SMBOWFencrypt((const unsigned char *)nt_pwd, chal,
+ local_nt_response);
/* Password info paranoia */
ZERO_STRUCT(key);
@@ -293,26 +297,29 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
DATA_BLOB nt_interactive_blob;
if (lm_interactive_pwd) {
- local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
- lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd));
+ local_lm_blob = data_blob(local_lm_response,
+ sizeof(local_lm_response));
+ lm_interactive_blob = data_blob(lm_pwd,
+ sizeof(lm_pwd));
ZERO_STRUCT(lm_pwd);
}
if (nt_interactive_pwd) {
- local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
- nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd));
+ local_nt_blob = data_blob(local_nt_response,
+ sizeof(local_nt_response));
+ nt_interactive_blob = data_blob(nt_pwd,
+ sizeof(nt_pwd));
ZERO_STRUCT(nt_pwd);
}
- nt_status = make_user_info_map(user_info,
- smb_name, client_domain,
- wksta_name,
- lm_interactive_pwd ? &local_lm_blob : NULL,
- nt_interactive_pwd ? &local_nt_blob : NULL,
- lm_interactive_pwd ? &lm_interactive_blob : NULL,
- nt_interactive_pwd ? &nt_interactive_blob : NULL,
- NULL,
- True);
+ nt_status = make_user_info_map(
+ user_info,
+ smb_name, client_domain, wksta_name,
+ lm_interactive_pwd ? &local_lm_blob : NULL,
+ nt_interactive_pwd ? &local_nt_blob : NULL,
+ lm_interactive_pwd ? &lm_interactive_blob : NULL,
+ nt_interactive_pwd ? &nt_interactive_blob : NULL,
+ NULL, True);
if (NT_STATUS_IS_OK(nt_status)) {
(*user_info)->logon_parameters = logon_parameters;
@@ -347,17 +354,21 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
* Not encrypted - do so.
*/
- DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n"));
+ DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
+ "format.\n"));
if (plaintext_password.data) {
unsigned char local_lm_response[24];
#ifdef DEBUG_PASSWORD
- DEBUG(10,("Unencrypted password (len %d):\n",(int)plaintext_password.length));
- dump_data(100, (const char *)plaintext_password.data, plaintext_password.length);
+ DEBUG(10,("Unencrypted password (len %d):\n",
+ (int)plaintext_password.length));
+ dump_data(100, (const char *)plaintext_password.data,
+ plaintext_password.length);
#endif
- SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response);
+ SMBencrypt( (const char *)plaintext_password.data,
+ (const uchar*)chal, local_lm_response);
local_lm_blob = data_blob(local_lm_response, 24);
/* We can't do an NT hash here, as the password needs to be
@@ -369,14 +380,14 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
local_nt_blob = data_blob(NULL, 0);
}
- ret = make_user_info_map(user_info, smb_name,
- client_domain,
- get_remote_machine_name(),
- local_lm_blob.data ? &local_lm_blob : NULL,
- local_nt_blob.data ? &local_nt_blob : NULL,
- NULL, NULL,
- plaintext_password.data ? &plaintext_password : NULL,
- False);
+ ret = make_user_info_map(
+ user_info, smb_name, client_domain,
+ get_remote_machine_name(),
+ local_lm_blob.data ? &local_lm_blob : NULL,
+ local_nt_blob.data ? &local_nt_blob : NULL,
+ NULL, NULL,
+ plaintext_password.data ? &plaintext_password : NULL,
+ False);
data_blob_free(&local_lm_blob);
return NT_STATUS_IS_OK(ret) ? True : False;
@@ -426,7 +437,6 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info)
void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
{
- fstring sid_str;
size_t i;
if (!token) {
@@ -434,12 +444,15 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
return;
}
- DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",
- sid_to_string(sid_str, &token->user_sids[0]) ));
- DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids));
+ DEBUGC(dbg_class, dbg_lev,
+ ("NT user token of user %s\n",
+ sid_string_static(&token->user_sids[0]) ));
+ DEBUGADDC(dbg_class, dbg_lev,
+ ("contains %lu SIDs\n", (unsigned long)token->num_sids));
for (i = 0; i < token->num_sids; i++)
- DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i,
- sid_to_string(sid_str, &token->user_sids[i])));
+ DEBUGADDC(dbg_class, dbg_lev,
+ ("SID[%3lu]: %s\n", (unsigned long)i,
+ sid_string_static(&token->user_sids[i])));
dump_se_priv( dbg_class, dbg_lev, &token->privileges );
}
@@ -448,609 +461,882 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
prints a UNIX 'token' to debug output.
****************************************************************************/
-void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, int n_groups, gid_t *groups)
+void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
+ int n_groups, gid_t *groups)
{
int i;
- DEBUGC(dbg_class, dbg_lev, ("UNIX token of user %ld\n", (long int)uid));
+ DEBUGC(dbg_class, dbg_lev,
+ ("UNIX token of user %ld\n", (long int)uid));
- DEBUGADDC(dbg_class, dbg_lev, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid, n_groups));
+ DEBUGADDC(dbg_class, dbg_lev,
+ ("Primary group is %ld and contains %i supplementary "
+ "groups\n", (long int)gid, n_groups));
for (i = 0; i < n_groups; i++)
DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i,
(long int)groups[i]));
}
-/****************************************************************************
- Create the SID list for this user.
-****************************************************************************/
+/******************************************************************************
+ Create a token for the root user to be used internally by smbd.
+ This is similar to running under the context of the LOCAL_SYSTEM account
+ in Windows. This is a read-only token. Do not modify it or free() it.
+ Create a copy if your need to change it.
+******************************************************************************/
-static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *group_sid,
- int n_groupSIDs, DOM_SID *groupSIDs,
- BOOL is_guest, NT_USER_TOKEN **token)
+NT_USER_TOKEN *get_root_nt_token( void )
{
- NTSTATUS nt_status = NT_STATUS_OK;
- NT_USER_TOKEN *ptoken;
- int i;
- int sid_ndx;
- DOM_SID domadm;
- BOOL is_domain_admin = False;
- BOOL domain_mode = False;
-
- if ((ptoken = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL) {
- DEBUG(0, ("create_nt_user_token: Out of memory allocating token\n"));
- nt_status = NT_STATUS_NO_MEMORY;
- return nt_status;
+ static NT_USER_TOKEN *token = NULL;
+ DOM_SID u_sid, g_sid;
+ struct passwd *pw;
+
+ if ( token )
+ return token;
+
+ if ( !(pw = sys_getpwnam( "root" )) ) {
+ DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));
+ return NULL;
}
+
+ /* get the user and primary group SIDs; although the
+ BUILTIN\Administrators SId is really the one that matters here */
+
+ uid_to_sid(&u_sid, pw->pw_uid);
+ gid_to_sid(&g_sid, pw->pw_gid);
- ZERO_STRUCTP(ptoken);
+ token = create_local_nt_token(NULL, &u_sid, &g_sid, False,
+ 1, &global_sid_Builtin_Administrators);
+ return token;
+}
- ptoken->num_sids = n_groupSIDs + 5;
+static int server_info_dtor(void *p)
+{
+ auth_serversupplied_info *server_info =
+ talloc_get_type_abort(p, auth_serversupplied_info);
- if ((ptoken->user_sids = SMB_MALLOC_ARRAY( DOM_SID, ptoken->num_sids )) == NULL) {
- DEBUG(0, ("create_nt_user_token: Out of memory allocating SIDs\n"));
- nt_status = NT_STATUS_NO_MEMORY;
- return nt_status;
+ if (server_info->sam_account != NULL) {
+ TALLOC_FREE(server_info->sam_account);
}
-
- memset((char*)ptoken->user_sids,0,sizeof(DOM_SID) * ptoken->num_sids);
-
- /*
- * Note - user SID *MUST* be first in token !
- * se_access_check depends on this.
- *
- * Primary group SID is second in token. Convention.
- */
- sid_copy(&ptoken->user_sids[PRIMARY_USER_SID_INDEX], user_sid);
- if (group_sid)
- sid_copy(&ptoken->user_sids[PRIMARY_GROUP_SID_INDEX], group_sid);
+ ZERO_STRUCTP(server_info);
+ return 0;
+}
- /*
- * Finally add the "standard" SIDs.
- * The only difference between guest and "anonymous" (which we
- * don't really support) is the addition of Authenticated_Users.
- */
+/***************************************************************************
+ Make a server_info struct. Free with TALLOC_FREE().
+***************************************************************************/
- sid_copy(&ptoken->user_sids[2], &global_sid_World);
- sid_copy(&ptoken->user_sids[3], &global_sid_Network);
+static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
+{
+ struct auth_serversupplied_info *result;
- if (is_guest)
- sid_copy(&ptoken->user_sids[4], &global_sid_Builtin_Guests);
- else
- sid_copy(&ptoken->user_sids[4], &global_sid_Authenticated_Users);
-
- sid_ndx = 5; /* next available spot */
+ result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info);
+ if (result == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ talloc_set_destructor(result, server_info_dtor);
- /* this is where we construct the domain admins SID if we can
- so that we can add the BUILTIN\Administrators SID to the token */
+ /* Initialise the uid and gid values to something non-zero
+ which may save us from giving away root access if there
+ is a bug in allocating these fields. */
- ZERO_STRUCT( domadm );
- if ( IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER ) {
- domain_mode = True;
+ result->uid = -1;
+ result->gid = -1;
+ return result;
+}
- if ( IS_DC )
- sid_copy( &domadm, get_global_sam_sid() );
- else {
- /* if we a re a member server and cannot find
- out domain SID then reset the domain_mode flag */
- if ( !secrets_fetch_domain_sid( lp_workgroup(), &domadm ) )
- domain_mode = False;
- }
+/***************************************************************************
+ Make (and fill) a user_info struct from a struct samu
+***************************************************************************/
+
+NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
+ struct samu *sampass)
+{
+ NTSTATUS status;
+ struct passwd *pwd;
+ gid_t *gids;
+ auth_serversupplied_info *result;
- sid_append_rid( &domadm, DOMAIN_GROUP_RID_ADMINS );
+ if ( !(pwd = getpwnam_alloc(NULL, pdb_get_username(sampass))) ) {
+ DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
+ pdb_get_username(sampass)));
+ return NT_STATUS_NO_SUCH_USER;
}
-
- /* add the group SIDs to teh token */
-
- for (i = 0; i < n_groupSIDs; i++) {
- size_t check_sid_idx;
- for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {
- if (sid_equal(&ptoken->user_sids[check_sid_idx],
- &groupSIDs[i])) {
- break;
- }
- }
-
- if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {
- sid_copy(&ptoken->user_sids[sid_ndx++], &groupSIDs[i]);
- } else {
- ptoken->num_sids--;
- }
-
- /* here we check if the user is a domain admin and add the
- BUILTIN\Administrators SID to the token the group membership
- check succeeds. */
- if ( domain_mode ) {
- if ( sid_equal( &domadm, &groupSIDs[i] ) )
- is_domain_admin = True;
- }
-
+ if ( !(result = make_server_info(NULL)) ) {
+ TALLOC_FREE(pwd);
+ return NT_STATUS_NO_MEMORY;
}
- /* finally realloc the SID array and add the BUILTIN\Administrators
- SID if necessary */
+ result->sam_account = sampass;
+ result->unix_name = talloc_strdup(result, pwd->pw_name);
+ result->gid = pwd->pw_gid;
+ result->uid = pwd->pw_uid;
+
+ TALLOC_FREE(pwd);
- if ( is_domain_admin ) {
- DOM_SID *sids;
+ status = pdb_enum_group_memberships(result, sampass,
+ &result->sids, &gids,
+ &result->num_sids);
- if ( !(sids = SMB_REALLOC_ARRAY( ptoken->user_sids, DOM_SID, ptoken->num_sids+1 )) )
- DEBUG(0,("create_nt_user_token: Failed to realloc SID arry of size %d\n", ptoken->num_sids+1));
- else {
- ptoken->user_sids = sids;
- sid_copy( &(ptoken->user_sids)[ptoken->num_sids++], &global_sid_Builtin_Administrators );
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
+ nt_errstr(status)));
+ result->sam_account = NULL; /* Don't free on error exit. */
+ TALLOC_FREE(result);
+ return status;
}
- /* add privileges assigned to this user */
+ /* For now we throw away the gids and convert via sid_to_gid
+ * later. This needs fixing, but I'd like to get the code straight and
+ * simple first. */
+ TALLOC_FREE(gids);
- get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids );
-
- debug_nt_user_token(DBGC_AUTH, 10, ptoken);
-
- if ((lp_log_nt_token_command() != NULL) &&
- (strlen(lp_log_nt_token_command()) > 0)) {
- TALLOC_CTX *mem_ctx;
- char *command;
- fstring sidstr;
- char *user_sidstr, *group_sidstr;
+ DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
+ pdb_get_username(sampass), result->unix_name));
- mem_ctx = talloc_init("setnttoken");
- if (mem_ctx == NULL)
- return NT_STATUS_NO_MEMORY;
+ *server_info = result;
- sid_to_string(sidstr, &ptoken->user_sids[0]);
- user_sidstr = talloc_strdup(mem_ctx, sidstr);
+ return NT_STATUS_OK;
+}
- group_sidstr = talloc_strdup(mem_ctx, "");
- for (i=1; i<ptoken->num_sids; i++) {
- sid_to_string(sidstr, &ptoken->user_sids[i]);
- group_sidstr = talloc_asprintf(mem_ctx, "%s %s",
- group_sidstr, sidstr);
- }
+/*
+ * Add alias SIDs from memberships within the partially created token SID list
+ */
- command = SMB_STRDUP(lp_log_nt_token_command());
- command = realloc_string_sub(command, "%s", user_sidstr);
- command = realloc_string_sub(command, "%t", group_sidstr);
- DEBUG(8, ("running command: [%s]\n", command));
- if (smbrun(command, NULL) != 0) {
- DEBUG(0, ("Could not log NT token\n"));
- nt_status = NT_STATUS_ACCESS_DENIED;
+static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
+ struct nt_user_token *token)
+{
+ uint32 *aliases;
+ size_t i, num_aliases;
+ NTSTATUS status;
+
+ aliases = NULL;
+ num_aliases = 0;
+
+ status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
+ token->user_sids,
+ token->num_sids,
+ &aliases, &num_aliases);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
+ nt_errstr(status)));
+ 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,
+ &token->user_sids,
+ &token->num_sids);
+ if (token->user_sids == NULL) {
+ DEBUG(0, ("add_sid_to_array failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- talloc_destroy(mem_ctx);
- SAFE_FREE(command);
}
- *token = ptoken;
-
- return nt_status;
+ return NT_STATUS_OK;
}
-/****************************************************************************
- Create the SID list for this user.
-****************************************************************************/
-
-NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest)
+static NTSTATUS log_nt_token(TALLOC_CTX *tmp_ctx, NT_USER_TOKEN *token)
{
- DOM_SID user_sid;
- DOM_SID group_sid;
- DOM_SID *group_sids;
- NT_USER_TOKEN *token;
- int i;
+ char *command;
+ char *group_sidstr;
+ size_t i;
- if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, uid))) {
- return NULL;
- }
- if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, gid))) {
- return NULL;
+ if ((lp_log_nt_token_command() == NULL) ||
+ (strlen(lp_log_nt_token_command()) == 0)) {
+ return NT_STATUS_OK;
}
- group_sids = SMB_MALLOC_ARRAY(DOM_SID, ngroups);
- if (!group_sids) {
- DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));
- return NULL;
+ group_sidstr = talloc_strdup(tmp_ctx, "");
+ for (i=1; i<token->num_sids; i++) {
+ group_sidstr = talloc_asprintf(
+ tmp_ctx, "%s %s", group_sidstr,
+ sid_string_static(&token->user_sids[i]));
}
- /* convert the Unix group ids to SIDS */
+ command = talloc_string_sub(
+ tmp_ctx, lp_log_nt_token_command(),
+ "%s", sid_string_static(&token->user_sids[0]));
+ command = talloc_string_sub(tmp_ctx, command, "%t", group_sidstr);
- for (i = 0; i < ngroups; i++) {
- if (!NT_STATUS_IS_OK(gid_to_sid(&(group_sids)[i], (groups)[i]))) {
- DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups[i]));
- SAFE_FREE(group_sids);
- return NULL;
- }
+ if (command == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid, &group_sid,
- ngroups, group_sids, is_guest, &token))) {
- SAFE_FREE(group_sids);
- return NULL;
+ DEBUG(8, ("running command: [%s]\n", command));
+ if (smbrun(command, NULL) != 0) {
+ DEBUG(0, ("Could not log NT token\n"));
+ return NT_STATUS_ACCESS_DENIED;
}
- SAFE_FREE(group_sids);
+ return NT_STATUS_OK;
+}
- return token;
+/*******************************************************************
+*******************************************************************/
+
+static NTSTATUS add_builtin_administrators( TALLOC_CTX *ctx, struct nt_user_token *token )
+{
+ return NT_STATUS_OK;
}
-/******************************************************************************
- Create a token for the root user to be used internally by smbd.
- This is similar to running under the context of the LOCAL_SYSTEM account
- in Windows. This is a read-only token. Do not modify it or free() it.
- Create a copy if your need to change it.
-******************************************************************************/
+/*******************************************************************
+*******************************************************************/
-NT_USER_TOKEN *get_root_nt_token( void )
+static NTSTATUS create_builtin_users( void )
{
- static NT_USER_TOKEN *token = NULL;
- DOM_SID u_sid, g_sid;
- DOM_SID g_sids[1];
- struct passwd *pw;
- NTSTATUS result;
-
- if ( token )
- return token;
-
- if ( !(pw = getpwnam( "root" )) ) {
- DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));
- return NULL;
+ NTSTATUS status;
+ DOM_SID dom_users;
+
+ status = pdb_create_builtin_alias( BUILTIN_ALIAS_RID_USERS );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(0,("create_builtin_users: Failed to create Users\n"));
+ return status;
}
- /* get the user and primary group SIDs; although the
- BUILTIN\Administrators SId is really the one that matters here */
-
- if ( !NT_STATUS_IS_OK(uid_to_sid(&u_sid, pw->pw_uid)) )
- return NULL;
- if ( !NT_STATUS_IS_OK(gid_to_sid(&g_sid, pw->pw_gid)) )
- return NULL;
-
- sid_copy( &g_sids[0], &global_sid_Builtin_Administrators );
-
- result = create_nt_user_token( &u_sid, &g_sid, 1, g_sids, False, &token);
-
- return NT_STATUS_IS_OK(result) ? token : NULL;
-}
+ /* add domain users */
+ if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER))
+ && secrets_fetch_domain_sid(lp_workgroup(), &dom_users))
+ {
+ 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"
+ " Users\n"));
+ return status;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
-/******************************************************************************
- * this function returns the groups (SIDs) of the local SAM the user is in.
- * If this samba server is a DC of the domain the user belongs to, it returns
- * both domain groups and local / builtin groups. If the user is in a trusted
- * domain, or samba is a member server of a domain, then this function returns
- * local and builtin groups the user is a member of.
- *
- * currently this is a hack, as there is no sam implementation that is capable
- * of groups.
- *
- * NOTE!! This function will fail if you pass in a winbind user without
- * the domain --jerry
- ******************************************************************************/
+/*******************************************************************
+*******************************************************************/
-static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid,
- size_t *n_groups, DOM_SID **groups, gid_t **unix_groups)
+static NTSTATUS create_builtin_administrators( void )
{
- int n_unix_groups;
- int i;
+ NTSTATUS status;
+ DOM_SID dom_admins, root_sid;
+ fstring root_name;
+ enum SID_NAME_USE type;
+ TALLOC_CTX *ctx;
+ BOOL ret;
- *n_groups = 0;
- *groups = NULL;
+ status = pdb_create_builtin_alias( BUILTIN_ALIAS_RID_ADMINS );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(0,("create_builtin_administrators: Failed to create Administrators\n"));
+ return status;
+ }
+
+ /* add domain admins */
+ if ((IS_DC || (lp_server_role() == ROLE_DOMAIN_MEMBER))
+ && secrets_fetch_domain_sid(lp_workgroup(), &dom_admins))
+ {
+ sid_append_rid(&dom_admins, DOMAIN_GROUP_RID_ADMINS);
+ status = pdb_add_aliasmem( &global_sid_Builtin_Administrators, &dom_admins );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(0,("create_builtin_administrators: Failed to add Domain Admins"
+ " Administrators\n"));
+ return status;
+ }
+ }
+
+ /* add root */
+ if ( (ctx = talloc_init(NULL)) == NULL ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ fstr_sprintf( root_name, "%s\\root", get_global_sam_name() );
+ ret = lookup_name( ctx, root_name, 0, NULL, NULL, &root_sid, &type );
+ TALLOC_FREE( ctx );
- if (strchr(username, *lp_winbind_separator()) == NULL) {
- NTSTATUS result;
+ if ( ret ) {
+ status = pdb_add_aliasmem( &global_sid_Builtin_Administrators, &root_sid );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(0,("create_builtin_administrators: Failed to add root"
+ " Administrators\n"));
+ return status;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Create a NT token for the user, expanding local aliases
+*******************************************************************/
+
+static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
+ const DOM_SID *user_sid,
+ const DOM_SID *group_sid,
+ BOOL is_guest,
+ int num_groupsids,
+ const DOM_SID *groupsids)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct nt_user_token *result = NULL;
+ int i;
+ NTSTATUS status;
+ gid_t gid;
- become_root();
- result = pdb_enum_group_memberships(username, gid, groups,
- unix_groups, n_groups);
- unbecome_root();
- return result;
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NULL;
}
- /* We have the separator, this must be winbind */
-
- n_unix_groups = winbind_getgroups( username, unix_groups );
+ result = TALLOC_ZERO_P(tmp_ctx, NT_USER_TOKEN);
+ if (result == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ goto done;
+ }
- DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n",
- username, n_unix_groups == -1 ? "FAIL" : "SUCCESS"));
-
- if ( n_unix_groups == -1 )
- return NT_STATUS_NO_SUCH_USER; /* what should this return
- * value be? */
+ /* Add the user and primary group sid */
- debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);
+ add_sid_to_array(result, user_sid,
+ &result->user_sids, &result->num_sids);
+ add_sid_to_array(result, group_sid,
+ &result->user_sids, &result->num_sids);
+
+ /* Add in BUILTIN sids */
- /* now setup the space for storing the 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 (is_guest) {
+ add_sid_to_array(result, &global_sid_Builtin_Guests,
+ &result->user_sids, &result->num_sids);
+ } else {
+ add_sid_to_array(result, &global_sid_Authenticated_Users,
+ &result->user_sids, &result->num_sids);
+ }
- if (n_unix_groups > 0) {
+ /* Now the SIDs we got from authentication. These are the ones from
+ * the info3 struct or from the pdb_enum_group_memberships, depending
+ * on who authenticated the user. */
+
+ for (i=0; i<num_groupsids; i++) {
+ add_sid_to_array_unique(result, &groupsids[i],
+ &result->user_sids, &result->num_sids);
+ }
- *groups = SMB_MALLOC_ARRAY(DOM_SID, n_unix_groups);
-
- if (!*groups) {
- DEBUG(0, ("get_user_group: malloc() failed for DOM_SID list!\n"));
- SAFE_FREE(*unix_groups);
- return NT_STATUS_NO_MEMORY;
+ /* Deal with the BUILTIN\Administrators group. If the SID can
+ be resolved then assume that the add_aliasmem( S-1-5-32 )
+ handled it. */
+
+ if ( !sid_to_gid( &global_sid_Builtin_Administrators, &gid ) ) {
+ /* We can only create a mapping if winbind is running
+ and the nested group functionality has been enabled */
+
+ if ( lp_winbind_nested_groups() && winbind_ping() ) {
+ become_root();
+ status = create_builtin_administrators( );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(0,("create_local_nt_token: Failed to create BUILTIN\\Administrators group!\n"));
+ /* don't fail, just log the message */
+ }
+ unbecome_root();
}
+ else {
+ status = add_builtin_administrators( tmp_ctx, result );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ result = NULL;
+ goto done;
+ }
+ }
}
- *n_groups = n_unix_groups;
+ /* Deal with the BUILTIN\Users group. If the SID can
+ be resolved then assume that the add_aliasmem( S-1-5-32 )
+ handled it. */
- for (i = 0; i < *n_groups; i++) {
- if (!NT_STATUS_IS_OK(gid_to_sid(&(*groups)[i], (*unix_groups)[i]))) {
- DEBUG(1, ("get_user_groups: failed to convert gid %ld to a sid!\n",
- (long int)(*unix_groups)[i+1]));
- SAFE_FREE(*groups);
- SAFE_FREE(*unix_groups);
- return NT_STATUS_NO_SUCH_USER;
+ if ( !sid_to_gid( &global_sid_Builtin_Users, &gid ) ) {
+ /* We can only create a mapping if winbind is running
+ and the nested group functionality has been enabled */
+
+ if ( lp_winbind_nested_groups() && winbind_ping() ) {
+ become_root();
+ status = create_builtin_users( );
+ if ( !NT_STATUS_IS_OK(status) ) {
+ DEBUG(0,("create_local_nt_token: Failed to create BUILTIN\\Administrators group!\n"));
+ /* don't fail, just log the message */
+ }
+ unbecome_root();
}
}
-
- return NT_STATUS_OK;
-}
-/***************************************************************************
- Make a user_info struct
-***************************************************************************/
+ /* Deal with local groups */
+
+ if (lp_winbind_nested_groups()) {
-static NTSTATUS make_server_info(auth_serversupplied_info **server_info)
-{
- *server_info = SMB_MALLOC_P(auth_serversupplied_info);
- if (!*server_info) {
- DEBUG(0,("make_server_info: malloc failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(*server_info);
+ /* Now add the aliases. First the one from our local SAM */
- /* Initialise the uid and gid values to something non-zero
- which may save us from giving away root access if there
- is a bug in allocating these fields. */
+ status = add_aliases(tmp_ctx, get_global_sam_sid(), result);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ result = NULL;
+ goto done;
+ }
- (*server_info)->uid = -1;
- (*server_info)->gid = -1;
+ /* Finally the builtin ones */
- return NT_STATUS_OK;
+ status = add_aliases(tmp_ctx, &global_sid_Builtin, result);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ result = NULL;
+ goto done;
+ }
+ }
+
+
+ get_privileges_for_sids(&result->privileges, result->user_sids,
+ result->num_sids);
+
+ talloc_steal(mem_ctx, result);
+
+ done:
+ TALLOC_FREE(tmp_ctx);
+ return result;
}
-/***************************************************************************
-Fill a server_info struct from a SAM_ACCOUNT with their groups
-***************************************************************************/
+/*
+ * Create the token to use from server_info->sam_account and
+ * server_info->sids (the info3/sam groups). Find the unix gids.
+ */
-static NTSTATUS add_user_groups(auth_serversupplied_info **server_info,
- const char * unix_username,
- SAM_ACCOUNT *sampass,
- uid_t uid, gid_t gid)
+NTSTATUS create_local_token(auth_serversupplied_info *server_info)
{
- NTSTATUS nt_status;
- const DOM_SID *user_sid = pdb_get_user_sid(sampass);
- const DOM_SID *group_sid = pdb_get_group_sid(sampass);
- size_t n_groupSIDs = 0;
- DOM_SID *groupSIDs = NULL;
- gid_t *unix_groups = NULL;
- NT_USER_TOKEN *token;
- BOOL is_guest;
- uint32 rid;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ size_t i;
+
- nt_status = get_user_groups(unix_username, uid, gid,
- &n_groupSIDs, &groupSIDs, &unix_groups);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(4,("get_user_groups_from_local_sam failed\n"));
- free_server_info(server_info);
- return nt_status;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ server_info->ptok = create_local_nt_token(
+ server_info,
+ pdb_get_user_sid(server_info->sam_account),
+ pdb_get_group_sid(server_info->sam_account),
+ server_info->guest,
+ server_info->num_sids, server_info->sids);
+
+ if ( !server_info->ptok ) {
+ return NT_STATUS_NO_SUCH_USER;
}
- is_guest = (sid_peek_rid(user_sid, &rid) && rid == DOMAIN_USER_RID_GUEST);
+ /* Convert the SIDs to gids. */
- if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token(user_sid, group_sid,
- n_groupSIDs, groupSIDs, is_guest,
- &token)))
- {
- DEBUG(4,("create_nt_user_token failed\n"));
- SAFE_FREE(groupSIDs);
- SAFE_FREE(unix_groups);
- free_server_info(server_info);
- return nt_status;
+ server_info->n_groups = 0;
+ server_info->groups = NULL;
+
+ /* Start at index 1, where the groups start. */
+
+ for (i=1; i<server_info->ptok->num_sids; i++) {
+ gid_t gid;
+ DOM_SID *sid = &server_info->ptok->user_sids[i];
+
+ if (!sid_to_gid(sid, &gid)) {
+ DEBUG(10, ("Could not convert SID %s to gid, "
+ "ignoring it\n", sid_string_static(sid)));
+ continue;
+ }
+ add_gid_to_array_unique(server_info, gid, &server_info->groups,
+ &server_info->n_groups);
}
- SAFE_FREE(groupSIDs);
+ debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
- (*server_info)->n_groups = n_groupSIDs;
- (*server_info)->groups = unix_groups;
- (*server_info)->ptok = token;
+ status = log_nt_token(mem_ctx, server_info->ptok);
- return nt_status;
+ TALLOC_FREE(mem_ctx);
+ return status;
}
-/***************************************************************************
- Make (and fill) a user_info struct from a SAM_ACCOUNT
-***************************************************************************/
-
-NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
- SAM_ACCOUNT *sampass)
+/*
+ * Create an artificial NT token given just a username. (Initially indended
+ * for force user)
+ *
+ * We go through lookup_name() to avoid problems we had with 'winbind use
+ * default domain'.
+ *
+ * We have 3 cases:
+ *
+ * unmapped unix users: Go directly to nss to find the user's group.
+ *
+ * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
+ *
+ * If the user is provided by winbind, the primary gid is set to "domain
+ * users" of the user's domain. For an explanation why this is necessary, see
+ * the thread starting at
+ * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
+ */
+
+NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
+ BOOL is_guest,
+ uid_t *uid, gid_t *gid,
+ char **found_username,
+ struct nt_user_token **token)
{
- NTSTATUS nt_status;
- struct passwd *pwd;
+ NTSTATUS result = NT_STATUS_NO_SUCH_USER;
+ TALLOC_CTX *tmp_ctx;
+ DOM_SID user_sid;
+ enum SID_NAME_USE type;
+ gid_t *gids;
+ DOM_SID primary_group_sid;
+ DOM_SID *group_sids;
+ size_t num_group_sids;
- if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info)))
- return nt_status;
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- (*server_info)->sam_account = sampass;
+ if (!lookup_name(tmp_ctx, username, LOOKUP_NAME_ALL,
+ NULL, NULL, &user_sid, &type)) {
+ DEBUG(1, ("lookup_name for %s failed\n", username));
+ goto done;
+ }
- if ( !(pwd = getpwnam_alloc(pdb_get_username(sampass))) ) {
- DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
- pdb_get_username(sampass)));
- free_server_info(server_info);
- return NT_STATUS_NO_SUCH_USER;
+ if (type != SID_NAME_USER) {
+ DEBUG(1, ("%s is a %s, not a user\n", username,
+ sid_type_lookup(type)));
+ goto done;
}
- (*server_info)->unix_name = smb_xstrdup(pwd->pw_name);
- (*server_info)->gid = pwd->pw_gid;
- (*server_info)->uid = pwd->pw_uid;
-
- passwd_free(&pwd);
- if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, pdb_get_username(sampass),
- sampass,
- (*server_info)->uid,
- (*server_info)->gid)))
- {
- free_server_info(server_info);
- return nt_status;
+ if (!sid_to_uid(&user_sid, uid)) {
+ DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
+ username, sid_string_static(&user_sid)));
+ goto done;
}
- (*server_info)->sam_fill_level = SAM_FILL_ALL;
- DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
- pdb_get_username(sampass),
- (*server_info)->unix_name));
+ if (sid_check_is_in_unix_users(&user_sid)) {
- return nt_status;
+ /* This is a unix user not in passdb. We need to ask nss
+ * directly, without consulting passdb */
+
+ struct passwd *pass;
+ size_t i;
+
+ pass = getpwuid_alloc(tmp_ctx, *uid);
+ if (pass == NULL) {
+ DEBUG(1, ("getpwuid(%d) for user %s failed\n",
+ *uid, username));
+ goto done;
+ }
+
+ *gid = pass->pw_gid;
+ gid_to_sid(&primary_group_sid, pass->pw_gid);
+
+ if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
+ &gids, &num_group_sids)) {
+ DEBUG(1, ("getgroups_unix_user for user %s failed\n",
+ username));
+ goto done;
+ }
+
+ 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;
+ }
+
+ for (i=0; i<num_group_sids; i++) {
+ gid_to_sid(&group_sids[i], gids[i]);
+ }
+ *found_username = talloc_strdup(mem_ctx, pass->pw_name);
+
+ } else if (sid_check_is_in_our_domain(&user_sid)) {
+
+ /* This is a passdb user, so ask passdb */
+
+ struct samu *sam_acct = NULL;
+
+ if ( !(sam_acct = samu_new( tmp_ctx )) ) {
+ goto done;
+ }
+
+ if (!pdb_getsampwsid(sam_acct, &user_sid)) {
+ DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
+ sid_string_static(&user_sid), username));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ sid_copy(&primary_group_sid, pdb_get_group_sid(sam_acct));
+
+ result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
+ &group_sids, &gids,
+ &num_group_sids);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("enum_group_memberships failed for %s\n",
+ username));
+ goto done;
+ }
+
+ *found_username = talloc_strdup(mem_ctx,
+ pdb_get_username(sam_acct));
+
+ } else {
+
+ /* This user is from winbind, force the primary gid to the
+ * user's "domain users" group. Under certain circumstances
+ * (user comes from NT4), this might be a loss of
+ * information. But we can not rely on winbind getting the
+ * correct info. AD might prohibit winbind looking up that
+ * information. */
+
+ 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);
+
+ if (!sid_to_gid(&primary_group_sid, gid)) {
+ DEBUG(1, ("sid_to_gid(%s) failed\n",
+ sid_string_static(&primary_group_sid)));
+ goto done;
+ }
+
+ num_group_sids = 0;
+ group_sids = NULL;
+
+ *found_username = talloc_strdup(mem_ctx, username);
+ }
+
+ *token = create_local_nt_token(mem_ctx, &user_sid, &primary_group_sid,
+ is_guest, num_group_sids, group_sids);
+
+ if ((*token == NULL) || (*found_username == NULL)) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ result = NT_STATUS_OK;
+ done:
+ TALLOC_FREE(tmp_ctx);
+ return result;
}
/***************************************************************************
- Make (and fill) a user_info struct from a Kerberos PAC logon_info by conversion
- to a SAM_ACCOUNT
-***************************************************************************/
+ Build upon create_token_from_username:
-NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info,
- char *unix_username,
- struct passwd *pwd,
- PAC_LOGON_INFO *logon_info)
+ 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 nt_status;
- SAM_ACCOUNT *sampass = NULL;
- DOM_SID user_sid, group_sid;
- fstring dom_name;
+ NTSTATUS status;
+ uid_t uid;
+ gid_t gid;
+ char *found_username;
+ struct nt_user_token *token;
+ BOOL result;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {
- return nt_status;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
}
- if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
- return nt_status;
+
+ status = create_token_from_username(mem_ctx, username, False,
+ &uid, &gid, &found_username,
+ &token);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("could not create token for %s\n", username));
+ return False;
}
- /* only copy user_sid, group_sid and domain name out of the PAC for
- * now, we will benefit from more later - Guenther */
+ result = nt_token_check_sid(group_sid, token);
- sid_copy(&user_sid, &logon_info->info3.dom_sid.sid);
- sid_append_rid(&user_sid, logon_info->info3.user_rid);
- pdb_set_user_sid(sampass, &user_sid, PDB_SET);
+ TALLOC_FREE(mem_ctx);
+ return result;
- sid_copy(&group_sid, &logon_info->info3.dom_sid.sid);
- sid_append_rid(&group_sid, logon_info->info3.group_rid);
- pdb_set_group_sid(sampass, &group_sid, PDB_SET);
+}
- unistr2_to_ascii(dom_name, &logon_info->info3.uni_logon_dom, -1);
- pdb_set_domain(sampass, dom_name, PDB_SET);
+BOOL user_in_group(const char *username, const char *groupname)
+{
+ TALLOC_CTX *mem_ctx;
+ DOM_SID group_sid;
+ NTSTATUS status;
+ BOOL ret;
- pdb_set_logon_count(sampass, logon_info->info3.logon_count, PDB_SET);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
- (*server_info)->sam_account = sampass;
+ ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
+ NULL, NULL, &group_sid, NULL);
+ TALLOC_FREE(mem_ctx);
- if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
- sampass, pwd->pw_uid, pwd->pw_gid)))
- {
- return nt_status;
+ if (!ret) {
+ DEBUG(10, ("lookup_name(%s) failed: %s\n", groupname,
+ nt_errstr(status)));
+ return False;
}
- (*server_info)->unix_name = smb_xstrdup(unix_username);
-
- (*server_info)->sam_fill_level = SAM_FILL_ALL;
- (*server_info)->uid = pwd->pw_uid;
- (*server_info)->gid = pwd->pw_gid;
- return nt_status;
+ return user_in_group_sid(username, &group_sid);
}
/***************************************************************************
Make (and fill) a user_info struct from a 'struct passwd' by conversion
- to a SAM_ACCOUNT
+ to a struct samu
***************************************************************************/
NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info,
char *unix_username,
struct passwd *pwd)
{
- NTSTATUS nt_status;
- SAM_ACCOUNT *sampass = NULL;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {
- return nt_status;
+ NTSTATUS status;
+ struct samu *sampass = NULL;
+ gid_t *gids;
+ auth_serversupplied_info *result;
+
+ if ( !(sampass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
}
- if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
- return nt_status;
+
+ status = samu_set_unix( sampass, pwd );
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- (*server_info)->sam_account = sampass;
+ result = make_server_info(NULL);
- if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
- sampass, pwd->pw_uid, pwd->pw_gid)))
- {
- return nt_status;
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(sampass);
+ return status;
}
- (*server_info)->unix_name = smb_xstrdup(unix_username);
+ result->sam_account = sampass;
+ result->unix_name = talloc_strdup(result, unix_username);
+ result->uid = pwd->pw_uid;
+ result->gid = pwd->pw_gid;
- (*server_info)->sam_fill_level = SAM_FILL_ALL;
- (*server_info)->uid = pwd->pw_uid;
- (*server_info)->gid = pwd->pw_gid;
- return nt_status;
+ status = pdb_enum_group_memberships(result, sampass,
+ &result->sids, &gids,
+ &result->num_sids);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(result);
+ return status;
+ }
+
+ /* For now we throw away the gids and convert via sid_to_gid
+ * later. This needs fixing, but I'd like to get the code straight and
+ * simple first. */
+ TALLOC_FREE(gids);
+
+ *server_info = result;
+
+ return NT_STATUS_OK;
}
/***************************************************************************
Make (and fill) a user_info struct for a guest login.
-***************************************************************************/
+ This *must* succeed for smbd to start. If there is no mapping entry for
+ the guest gid, then create one.
+**********************
+*****************************************************/
static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
{
- NTSTATUS nt_status;
- SAM_ACCOUNT *sampass = NULL;
+ NTSTATUS status;
+ struct samu *sampass = NULL;
DOM_SID guest_sid;
+ BOOL ret;
+ static const char zeros[16];
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
- return nt_status;
+ if ( !(sampass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
}
sid_copy(&guest_sid, get_global_sam_sid());
sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
become_root();
- if (!pdb_getsampwsid(sampass, &guest_sid)) {
- unbecome_root();
+ ret = pdb_getsampwsid(sampass, &guest_sid);
+ unbecome_root();
+
+ if (!ret) {
+ TALLOC_FREE(sampass);
return NT_STATUS_NO_SUCH_USER;
}
- unbecome_root();
- nt_status = make_server_info_sam(server_info, sampass);
+ status = make_server_info_sam(server_info, sampass);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(sampass);
+ return status;
+ }
+
+ (*server_info)->guest = True;
- if (NT_STATUS_IS_OK(nt_status)) {
- static const char zeros[16];
- (*server_info)->guest = True;
-
- /* annoying, but the Guest really does have a session key,
- and it is all zeros! */
- (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
- (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
+ status = create_local_token(*server_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("create_local_token failed: %s\n",
+ nt_errstr(status)));
+ return status;
}
- return nt_status;
+ /* annoying, but the Guest really does have a session key, and it is
+ all zeros! */
+ (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
+ (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
+
+ return NT_STATUS_OK;
}
static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
{
auth_serversupplied_info *dst;
- if (!NT_STATUS_IS_OK(make_server_info(&dst)))
+ dst = make_server_info(NULL);
+ if (dst == NULL) {
return NULL;
+ }
dst->guest = src->guest;
dst->uid = src->uid;
dst->gid = src->gid;
dst->n_groups = src->n_groups;
if (src->n_groups != 0)
- dst->groups = memdup(src->groups, sizeof(gid_t)*dst->n_groups);
+ dst->groups = talloc_memdup(dst, src->groups,
+ sizeof(gid_t)*dst->n_groups);
else
dst->groups = NULL;
- dst->ptok = dup_nt_token(src->ptok);
- dst->user_session_key = data_blob(src->user_session_key.data,
- src->user_session_key.length);
- dst->lm_session_key = data_blob(src->lm_session_key.data,
- src->lm_session_key.length);
- pdb_copy_sam_account(src->sam_account, &dst->sam_account);
+
+ dst->ptok = dup_nt_token(dst, src->ptok);
+
+ dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
+ src->user_session_key.length);
+
+ dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
+ src->lm_session_key.length);
+
+ if ( (dst->sam_account = samu_new( NULL )) != NULL )
+ pdb_copy_sam_account(dst->sam_account, src->sam_account);
+
dst->pam_handle = NULL;
- dst->unix_name = smb_xstrdup(src->unix_name);
+ dst->unix_name = talloc_strdup(dst, src->unix_name);
return dst;
}
@@ -1080,7 +1366,7 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
const char *username,
char **found_username,
uid_t *uid, gid_t *gid,
- SAM_ACCOUNT **sam_account)
+ struct samu *account)
{
NTSTATUS nt_status;
fstring dom_user, lower_username;
@@ -1093,14 +1379,11 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(),
lower_username);
- /* get the passwd struct but don't create the user if he/she
- does not exist. We were explicitly called from a following
- a winbindd authentication request so we should assume that
- nss_winbindd is working */
+ /* Get the passwd struct. Try to create the account is necessary. */
map_username( dom_user );
- if ( !(passwd = smb_getpwnam( dom_user, real_username, True )) )
+ if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
return NT_STATUS_NO_SUCH_USER;
*uid = passwd->pw_uid;
@@ -1114,11 +1397,12 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
*found_username = talloc_strdup( mem_ctx, real_username );
- DEBUG(5,("fill_sam_account: located username was [%s]\n",
- *found_username));
+ DEBUG(5,("fill_sam_account: located username was [%s]\n", *found_username));
- nt_status = pdb_init_sam_pw(sam_account, passwd);
- passwd_free(&passwd);
+ nt_status = samu_set_unix( account, passwd );
+
+ TALLOC_FREE(passwd);
+
return nt_status;
}
@@ -1128,7 +1412,8 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
the username if we fallback to the username only.
****************************************************************************/
-struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
+struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
+ fstring save_username, BOOL create )
{
struct passwd *pw = NULL;
char *p;
@@ -1151,7 +1436,7 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
if ( p ) {
fstring strip_username;
- pw = Get_Pwnam_alloc( domuser );
+ pw = Get_Pwnam_alloc( mem_ctx, domuser );
if ( pw ) {
/* make sure we get the case of the username correct */
/* work around 'winbind use default domain = yes' */
@@ -1182,17 +1467,20 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
/* just lookup a plain username */
- pw = Get_Pwnam_alloc(username);
+ pw = Get_Pwnam_alloc(mem_ctx, username);
- /* Create local user if requested. */
+ /* Create local user if requested but only if winbindd
+ is not running. We need to protect against cases
+ where winbindd is failing and then prematurely
+ creating users in /etc/passwd */
- if ( !pw && create ) {
+ if ( !pw && create && !winbind_ping() ) {
/* Don't add a machine account. */
if (username[strlen(username)-1] == '$')
return NULL;
smb_create_user(NULL, username, NULL);
- pw = Get_Pwnam_alloc(username);
+ pw = Get_Pwnam_alloc(mem_ctx, username);
}
/* one last check for a valid passwd struct */
@@ -1220,23 +1508,17 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
char *found_username;
const char *nt_domain;
const char *nt_username;
-
- SAM_ACCOUNT *sam_account = NULL;
+ struct samu *sam_account = NULL;
DOM_SID user_sid;
DOM_SID group_sid;
uid_t uid;
gid_t gid;
- size_t n_lgroupSIDs;
- DOM_SID *lgroupSIDs = NULL;
-
- gid_t *unix_groups = NULL;
- NT_USER_TOKEN *token;
-
- DOM_SID *all_group_SIDs;
size_t i;
+ auth_serversupplied_info *result;
+
/*
Here is where we should check the list of
trusted domains, and verify that the SID
@@ -1254,12 +1536,14 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
}
if (!(nt_username = unistr2_tdup(mem_ctx, &(info3->uni_user_name)))) {
- /* If the server didn't give us one, just use the one we sent them */
+ /* If the server didn't give us one, just use the one we sent
+ * them */
nt_username = sent_nt_username;
}
if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3->uni_logon_dom)))) {
- /* If the server didn't give us one, just use the one we sent them */
+ /* If the server didn't give us one, just use the one we sent
+ * them */
nt_domain = domain;
}
@@ -1268,151 +1552,141 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
We use the _unmapped_ username here in an attempt to provide
consistent username mapping behavior between kerberos and NTLM[SSP]
- authentication in domain mode security. I.E. Username mapping should
- be applied to the fully qualified username (e.g. DOMAIN\user) and
- no just the login name. Yes this mean swe called map_username()
- unnecessarily in make_user_info_map() but that is how the current
- code is designed. Making the change here is the least disruptive
- place. -- jerry */
+ authentication in domain mode security. I.E. Username mapping
+ should be applied to the fully qualified username
+ (e.g. DOMAIN\user) and not just the login name. Yes this means we
+ called map_username() unnecessarily in make_user_info_map() but
+ that is how the current code is designed. Making the change here
+ is the least disruptive place. -- jerry */
+ if ( !(sam_account = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
- &found_username, &uid, &gid, &sam_account);
+ &found_username, &uid, &gid, sam_account);
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
- DEBUG(3,("User %s does not exist, trying to add it\n", internal_username));
+ DEBUG(3,("User %s does not exist, trying to add it\n",
+ internal_username));
smb_create_user( nt_domain, sent_nt_username, NULL);
nt_status = fill_sam_account( mem_ctx, nt_domain, sent_nt_username,
- &found_username, &uid, &gid, &sam_account );
+ &found_username, &uid, &gid, sam_account );
}
/* if we still don't have a valid unix account check for
- 'map to gues = bad uid' */
+ 'map to guest = bad uid' */
if (!NT_STATUS_IS_OK(nt_status)) {
+ TALLOC_FREE( sam_account );
if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
make_server_info_guest(server_info);
return NT_STATUS_OK;
}
-
- DEBUG(0, ("make_server_info_info3: pdb_init_sam failed!\n"));
return nt_status;
}
if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return NT_STATUS_UNSUCCESSFUL;
}
if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return NT_STATUS_UNSUCCESSFUL;
}
- if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)),
+ if (!pdb_set_fullname(sam_account,
+ unistr2_static(&(info3->uni_full_name)),
PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_logon_script(sam_account,
+ unistr2_static(&(info3->uni_logon_script)),
+ PDB_CHANGED)) {
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
- if (!pdb_set_logon_script(sam_account, unistr2_static(&(info3->uni_logon_script)), PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ if (!pdb_set_profile_path(sam_account,
+ unistr2_static(&(info3->uni_profile_path)),
+ PDB_CHANGED)) {
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
- if (!pdb_set_profile_path(sam_account, unistr2_static(&(info3->uni_profile_path)), PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ if (!pdb_set_homedir(sam_account,
+ unistr2_static(&(info3->uni_home_dir)),
+ PDB_CHANGED)) {
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
- if (!pdb_set_homedir(sam_account, unistr2_static(&(info3->uni_home_dir)), PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ if (!pdb_set_dir_drive(sam_account,
+ unistr2_static(&(info3->uni_dir_drive)),
+ PDB_CHANGED)) {
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
- if (!pdb_set_dir_drive(sam_account, unistr2_static(&(info3->uni_dir_drive)), PDB_CHANGED)) {
- pdb_free_sam(&sam_account);
+ if (!pdb_set_acct_ctrl(sam_account, info3->acct_flags, PDB_CHANGED)) {
+ TALLOC_FREE(sam_account);
return NT_STATUS_NO_MEMORY;
}
- if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
+ result = make_server_info(NULL);
+ if (result == NULL) {
DEBUG(4, ("make_server_info failed!\n"));
- pdb_free_sam(&sam_account);
- return nt_status;
+ TALLOC_FREE(sam_account);
+ return NT_STATUS_NO_MEMORY;
}
/* save this here to _net_sam_logon() doesn't fail (it assumes a
- valid SAM_ACCOUNT) */
+ valid struct samu) */
- (*server_info)->sam_account = sam_account;
-
- (*server_info)->unix_name = smb_xstrdup(found_username);
+ result->sam_account = sam_account;
+ result->unix_name = talloc_strdup(result, found_username);
/* Fill in the unix info we found on the way */
- (*server_info)->sam_fill_level = SAM_FILL_ALL;
- (*server_info)->uid = uid;
- (*server_info)->gid = gid;
+ result->uid = uid;
+ result->gid = gid;
- /* Store the user group information in the server_info
- returned to the caller. */
-
- nt_status = get_user_groups((*server_info)->unix_name,
- uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups);
-
- if ( !NT_STATUS_IS_OK(nt_status) ) {
- DEBUG(4,("get_user_groups failed\n"));
- return nt_status;
- }
-
- (*server_info)->groups = unix_groups;
- (*server_info)->n_groups = n_lgroupSIDs;
-
/* Create a 'combined' list of all SIDs we might want in the SD */
-
- all_group_SIDs = SMB_MALLOC_ARRAY(DOM_SID,info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs);
-
- if (!all_group_SIDs) {
- DEBUG(0, ("malloc() failed for DOM_SID list!\n"));
- SAFE_FREE(lgroupSIDs);
- free_server_info(server_info);
- return NT_STATUS_NO_MEMORY;
- }
+
+ result->num_sids = 0;
+ result->sids = NULL;
/* and create (by appending rids) the 'domain' sids */
for (i = 0; i < info3->num_groups2; i++) {
-
- sid_copy(&all_group_SIDs[i], &(info3->dom_sid.sid));
-
- if (!sid_append_rid(&all_group_SIDs[i], info3->gids[i].g_rid)) {
-
- nt_status = NT_STATUS_INVALID_PARAMETER;
-
- DEBUG(3,("could not append additional group rid 0x%x\n",
- info3->gids[i].g_rid));
-
- SAFE_FREE(lgroupSIDs);
- SAFE_FREE(all_group_SIDs);
- free_server_info(server_info);
-
- return nt_status;
-
+ DOM_SID sid;
+ if (!sid_compose(&sid, &info3->dom_sid.sid,
+ info3->gids[i].g_rid)) {
+ DEBUG(3,("could not append additional group rid "
+ "0x%x\n", info3->gids[i].g_rid));
+ TALLOC_FREE(result);
+ return NT_STATUS_INVALID_PARAMETER;
}
+ add_sid_to_array(result, &sid, &result->sids,
+ &result->num_sids);
}
/* Copy 'other' sids. We need to do sid filtering here to
@@ -1422,56 +1696,33 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
*/
for (i = 0; i < info3->num_other_sids; i++) {
- sid_copy(&all_group_SIDs[info3->num_groups2 + i],
- &info3->other_sids[i].sid);
- }
-
-
- /* add local alias sids */
-
- for (i = 0; i < n_lgroupSIDs; i++) {
- sid_copy(&all_group_SIDs[info3->num_groups2 +
- info3->num_other_sids + i],
- &lgroupSIDs[i]);
- }
-
- /* Where are the 'global' sids... */
-
- /* can the user be guest? if yes, where is it stored? */
-
- nt_status = create_nt_user_token(&user_sid, &group_sid,
- info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs,
- all_group_SIDs, False, &token);
-
- if ( !NT_STATUS_IS_OK(nt_status) ) {
- DEBUG(4,("create_nt_user_token failed\n"));
- SAFE_FREE(lgroupSIDs);
- SAFE_FREE(all_group_SIDs);
- free_server_info(server_info);
- return nt_status;
+ add_sid_to_array(result, &info3->other_sids[i].sid,
+ &result->sids,
+ &result->num_sids);
}
- (*server_info)->login_server = unistr2_tdup(mem_ctx,
- &(info3->uni_logon_srv));
-
- (*server_info)->ptok = token;
-
- SAFE_FREE(lgroupSIDs);
- SAFE_FREE(all_group_SIDs);
+ result->login_server = unistr2_tdup(result,
+ &(info3->uni_logon_srv));
/* ensure we are never given NULL session keys */
if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
- (*server_info)->user_session_key = data_blob(NULL, 0);
+ result->user_session_key = data_blob(NULL, 0);
} else {
- (*server_info)->user_session_key = data_blob(info3->user_sess_key, sizeof(info3->user_sess_key));
+ result->user_session_key = data_blob_talloc(
+ result, info3->user_sess_key,
+ sizeof(info3->user_sess_key));
}
if (memcmp(info3->lm_sess_key, zeros, 8) == 0) {
- (*server_info)->lm_session_key = data_blob(NULL, 0);
+ result->lm_session_key = data_blob(NULL, 0);
} else {
- (*server_info)->lm_session_key = data_blob(info3->lm_sess_key, sizeof(info3->lm_sess_key));
- }
+ result->lm_session_key = data_blob_talloc(
+ result, info3->lm_sess_key,
+ sizeof(info3->lm_sess_key));
+ }
+
+ *server_info = result;
return NT_STATUS_OK;
}
@@ -1484,14 +1735,15 @@ void free_user_info(auth_usersupplied_info **user_info)
{
DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
if (*user_info != NULL) {
- if ((*user_info)->smb_name.str) {
- DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
+ if ((*user_info)->smb_name) {
+ DEBUG(10,("structure was created for %s\n",
+ (*user_info)->smb_name));
}
- SAFE_FREE((*user_info)->smb_name.str);
- SAFE_FREE((*user_info)->internal_username.str);
- SAFE_FREE((*user_info)->client_domain.str);
- SAFE_FREE((*user_info)->domain.str);
- SAFE_FREE((*user_info)->wksta_name.str);
+ SAFE_FREE((*user_info)->smb_name);
+ SAFE_FREE((*user_info)->internal_username);
+ SAFE_FREE((*user_info)->client_domain);
+ SAFE_FREE((*user_info)->domain);
+ SAFE_FREE((*user_info)->wksta_name);
data_blob_free(&(*user_info)->lm_resp);
data_blob_free(&(*user_info)->nt_resp);
data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
@@ -1503,38 +1755,19 @@ void free_user_info(auth_usersupplied_info **user_info)
}
/***************************************************************************
- Clear out a server_info struct that has been allocated
-***************************************************************************/
-
-void free_server_info(auth_serversupplied_info **server_info)
-{
- DEBUG(5,("attempting to free (and zero) a server_info structure\n"));
- if (*server_info != NULL) {
- pdb_free_sam(&(*server_info)->sam_account);
-
- /* call pam_end here, unless we know we are keeping it */
- delete_nt_token( &(*server_info)->ptok );
- SAFE_FREE((*server_info)->groups);
- SAFE_FREE((*server_info)->unix_name);
- data_blob_free(&(*server_info)->lm_session_key);
- data_blob_free(&(*server_info)->user_session_key);
- ZERO_STRUCT(**server_info);
- }
- SAFE_FREE(*server_info);
-}
-
-/***************************************************************************
Make an auth_methods struct
***************************************************************************/
BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method)
{
if (!auth_context) {
- smb_panic("no auth_context supplied to make_auth_methods()!\n");
+ smb_panic("no auth_context supplied to "
+ "make_auth_methods()!\n");
}
if (!auth_method) {
- smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
+ smb_panic("make_auth_methods: pointer to auth_method pointer "
+ "is NULL!\n");
}
*auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
@@ -1548,40 +1781,28 @@ BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_me
}
/****************************************************************************
- Delete a SID token.
-****************************************************************************/
-
-void delete_nt_token(NT_USER_TOKEN **pptoken)
-{
- if (*pptoken) {
- NT_USER_TOKEN *ptoken = *pptoken;
-
- SAFE_FREE( ptoken->user_sids );
- ZERO_STRUCTP(ptoken);
- }
- SAFE_FREE(*pptoken);
-}
-
-/****************************************************************************
Duplicate a SID token.
****************************************************************************/
-NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
+NT_USER_TOKEN *dup_nt_token(TALLOC_CTX *mem_ctx, NT_USER_TOKEN *ptoken)
{
NT_USER_TOKEN *token;
if (!ptoken)
return NULL;
- if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
+ token = TALLOC_P(mem_ctx, NT_USER_TOKEN);
+ if (token == NULL) {
+ DEBUG(0, ("talloc failed\n"));
return NULL;
+ }
- ZERO_STRUCTP(token);
-
- token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids );
-
- if ( !token ) {
- SAFE_FREE(token);
+ token->user_sids = talloc_memdup(token, ptoken->user_sids,
+ sizeof(DOM_SID) * ptoken->num_sids );
+
+ if ((ptoken->user_sids != NULL) && (token->user_sids == NULL)) {
+ DEBUG(0, ("talloc_memdup failed\n"));
+ TALLOC_FREE(token);
return NULL;
}
@@ -1590,7 +1811,8 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
/* copy the privileges; don't consider failure to be critical here */
if ( !se_priv_copy( &token->privileges, &ptoken->privileges ) ) {
- DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!. Continuing with 0 privileges assigned.\n"));
+ DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!. "
+ "Continuing with 0 privileges assigned.\n"));
}
return token;
@@ -1600,7 +1822,7 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
Check for a SID in an NT_USER_TOKEN
****************************************************************************/
-BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token )
+BOOL nt_token_check_sid ( const DOM_SID *sid, const NT_USER_TOKEN *token )
{
int i;
@@ -1623,9 +1845,10 @@ BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
a DC or standalone server, use our own SID */
if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
- if ( !secrets_fetch_domain_sid( lp_workgroup(), &domain_sid ) ) {
- DEBUG(1,("nt_token_check_domain_rid: Cannot lookup SID for domain [%s]\n",
- lp_workgroup()));
+ if ( !secrets_fetch_domain_sid( lp_workgroup(),
+ &domain_sid ) ) {
+ DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
+ "SID for domain [%s]\n", lp_workgroup()));
return False;
}
}
@@ -1648,8 +1871,6 @@ BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
BOOL is_trusted_domain(const char* dom_name)
{
DOM_SID trustdom_sid;
- char *pass = NULL;
- time_t lct;
BOOL ret;
/* no trusted domains for a standalone server */
@@ -1661,11 +1882,11 @@ BOOL is_trusted_domain(const char* dom_name)
if ( IS_DC ) {
become_root();
- DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n",
- dom_name ));
- ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct);
+ DEBUG (5,("is_trusted_domain: Checking for domain trust with "
+ "[%s]\n", dom_name ));
+ ret = secrets_fetch_trusted_domain_password(dom_name, NULL,
+ NULL, NULL);
unbecome_root();
- SAFE_FREE(pass);
if (ret)
return True;
}
diff --git a/source/auth/auth_winbind.c b/source/auth/auth_winbind.c
index ad72bd9a1fd..4836d62ef96 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;
+ info3_ndr = response->extra_data.data;
if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) {
return NT_STATUS_NO_MEMORY;
}
@@ -71,13 +71,13 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
if (!auth_context) {
DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n",
- user_info->internal_username.str));
+ user_info->internal_username));
return NT_STATUS_INVALID_PARAMETER;
}
- if (strequal(user_info->domain.str, get_global_sam_name())) {
+ if (strequal(user_info->domain, get_global_sam_name())) {
DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n",
- user_info->domain.str));
+ user_info->domain));
return NT_STATUS_NOT_IMPLEMENTED;
}
@@ -90,12 +90,9 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
request.data.auth_crap.logon_parameters = user_info->logon_parameters;
- fstrcpy(request.data.auth_crap.user,
- user_info->smb_name.str);
- fstrcpy(request.data.auth_crap.domain,
- user_info->domain.str);
- fstrcpy(request.data.auth_crap.workstation,
- user_info->wksta_name.str);
+ fstrcpy(request.data.auth_crap.user, user_info->smb_name);
+ fstrcpy(request.data.auth_crap.domain, user_info->domain);
+ fstrcpy(request.data.auth_crap.workstation, user_info->wksta_name);
memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal));
@@ -127,12 +124,12 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
nt_status = NT_STATUS(response.data.auth.nt_status);
- if (result == NSS_STATUS_SUCCESS && response.extra_data) {
+ if (result == NSS_STATUS_SUCCESS && response.extra_data.data) {
if (NT_STATUS_IS_OK(nt_status)) {
if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) {
nt_status = make_server_info_info3(mem_ctx,
- user_info->internal_username.str,
- user_info->smb_name.str, user_info->domain.str,
+ user_info->internal_username,
+ user_info->smb_name, user_info->domain,
server_info, &info3);
}
@@ -141,7 +138,7 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
nt_status = NT_STATUS_NO_LOGON_SERVERS;
}
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return nt_status;
}
diff --git a/source/client/client.c b/source/client/client.c
index 7ac64970f81..1fbee70645c 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -463,19 +463,17 @@ static void adjust_do_list_queue(void)
static void add_to_do_list_queue(const char* entry)
{
- char *dlq;
long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
while (new_end > do_list_queue_size) {
do_list_queue_size *= 2;
DEBUG(4,("enlarging do_list_queue to %d\n",
(int)do_list_queue_size));
- dlq = SMB_REALLOC(do_list_queue, do_list_queue_size);
- if (! dlq) {
+ do_list_queue = 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);
reset_do_list_queue();
} else {
- do_list_queue = dlq;
memset(do_list_queue + do_list_queue_size / 2,
0, do_list_queue_size / 2);
}
@@ -1338,15 +1336,15 @@ static struct file_list {
Free a file_list structure.
****************************************************************************/
-static void free_file_list (struct file_list * list)
+static void free_file_list (struct file_list *list_head)
{
- struct file_list *tmp;
+ struct file_list *list, *next;
- while (list) {
- tmp = list;
- DLIST_REMOVE(list, list);
- SAFE_FREE(tmp->file_path);
- SAFE_FREE(tmp);
+ for (list = list_head; list; list = next) {
+ next = list->next;
+ DLIST_REMOVE(list_head, list);
+ SAFE_FREE(list->file_path);
+ SAFE_FREE(list);
}
}
@@ -2512,7 +2510,7 @@ static void browse_fn(const char *name, uint32 m,
*typestr=0;
- switch (m)
+ switch (m & 7)
{
case STYPE_DISKTREE:
fstrcpy(typestr,"Disk"); break;
@@ -2534,6 +2532,57 @@ static void browse_fn(const char *name, uint32 m,
}
}
+static BOOL browse_host_rpc(BOOL sort)
+{
+ NTSTATUS status;
+ struct rpc_pipe_client *pipe_hnd;
+ TALLOC_CTX *mem_ctx;
+ ENUM_HND enum_hnd;
+ WERROR werr;
+ SRV_SHARE_INFO_CTR ctr;
+ int i;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ init_enum_hnd(&enum_hnd, 0);
+
+ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &status);
+
+ if (pipe_hnd == NULL) {
+ DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(mem_ctx);
+ return False;
+ }
+
+ werr = rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, 1, &ctr,
+ 0xffffffff, &enum_hnd);
+
+ if (!W_ERROR_IS_OK(werr)) {
+ TALLOC_FREE(mem_ctx);
+ cli_rpc_pipe_close(pipe_hnd);
+ return False;
+ }
+
+ for (i=0; i<ctr.num_entries; i++) {
+ SRV_SHARE_INFO_1 *info = &ctr.share.info1[i];
+ char *name, *comment;
+ name = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &info->info_1_str.uni_netname);
+ comment = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &info->info_1_str.uni_remark);
+ browse_fn(name, info->info_1.type, comment, NULL);
+ }
+
+ TALLOC_FREE(mem_ctx);
+ cli_rpc_pipe_close(pipe_hnd);
+ return True;
+}
+
/****************************************************************************
Try and browse available connections on a host.
****************************************************************************/
@@ -2546,6 +2595,10 @@ static BOOL browse_host(BOOL sort)
d_printf("\t--------- ---- -------\n");
}
+ if (browse_host_rpc(sort)) {
+ return True;
+ }
+
if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1)
d_printf("Error returning browse list: %s\n", cli_errstr(cli));
@@ -2921,16 +2974,22 @@ static char **remote_completion(const char *text, int len)
info.text = text;
info.len = len;
- if (len >= PATH_MAX)
+ if (len >= MIN(PATH_MAX,sizeof(pstring))) {
return(NULL);
+ }
info.matches = SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS);
- if (!info.matches) return NULL;
+ if (!info.matches) {
+ return NULL;
+ }
info.matches[0] = NULL;
- for (i = len-1; i >= 0; i--)
- if ((text[i] == '/') || (text[i] == '\\'))
+ for (i = len-1; i >= 0; i--) {
+ if ((text[i] == '/') || (text[i] == '\\')) {
break;
+ }
+ }
+
info.text = text+i+1;
info.samelen = info.len = len-i-1;
@@ -2938,8 +2997,9 @@ static char **remote_completion(const char *text, int len)
strncpy(info.dirmask, text, i+1);
info.dirmask[i+1] = 0;
pstr_sprintf(dirmask, "%s%*s*", cur_dir, i-1, text);
- } else
+ } else {
pstr_sprintf(dirmask, "%s*", cur_dir);
+ }
if (cli_list(cli, dirmask, aDIR | aSYSTEM | aHIDDEN, completion_remote_filter, &info) < 0)
goto cleanup;
@@ -3449,7 +3509,7 @@ static int do_message_op(void)
if ( override_logfile )
setup_logging( lp_logfile(), False );
- if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
argv[0], dyn_CONFIGFILE);
}
diff --git a/source/client/clitar.c b/source/client/clitar.c
index cd0ce27eb5f..306848bc0cd 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -523,6 +523,8 @@ static BOOL ensurepath(char *fname)
if ((partpath == NULL) || (ffname == NULL)){
DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
+ SAFE_FREE(partpath);
+ SAFE_FREE(ffname);
return(False);
}
@@ -1077,6 +1079,7 @@ static char *get_longfilename(file_info2 finfo)
while (left > 0) {
if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
+ SAFE_FREE(longname);
return(NULL);
}
@@ -1109,6 +1112,7 @@ static void do_tarput(void)
/* Get us to the next block, or the first block first time around */
if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
+ SAFE_FREE(longfilename);
return;
}
@@ -1180,6 +1184,7 @@ static void do_tarput(void)
}
break;
case 'L':
+ SAFE_FREE(longfilename);
longfilename = get_longfilename(finfo);
if (!longfilename) {
DEBUG(0, ("abandoning restore\n"));
@@ -1510,16 +1515,13 @@ static int read_inclusion_file(char *filename)
}
if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) {
- char *ib;
inclusion_buffer_size *= 2;
- ib = SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);
- if (! ib) {
+ inclusion_buffer = SMB_REALLOC(inclusion_buffer,inclusion_buffer_size);
+ if (!inclusion_buffer) {
DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n",
inclusion_buffer_size));
error = 1;
break;
- } else {
- inclusion_buffer = ib;
}
}
@@ -1722,6 +1724,7 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
if ((tmpstr = (char *)SMB_MALLOC(strlen(cliplist[clipcount])+1)) == NULL) {
DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", clipcount));
+ SAFE_FREE(tmplist);
return 0;
}
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index ed88c92c626..23a74d34fad 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -43,14 +43,25 @@
#define MOUNT_CIFS_VERSION_MINOR "10"
#ifndef MOUNT_CIFS_VENDOR_SUFFIX
-#define MOUNT_CIFS_VENDOR_SUFFIX ""
-#endif
+ #ifdef _SAMBA_BUILD_
+ #include "include/version.h"
+ #ifdef SAMBA_VERSION_VENDOR_SUFFIX
+ #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
+ #else
+ #define MOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
+ #endif /* SAMBA_VERSION_OFFICIAL_STRING and SAMBA_VERSION_VENDOR_SUFFIX */
+ #else
+ #define MOUNT_CIFS_VENDOR_SUFFIX ""
+ #endif /* _SAMBA_BUILD_ */
+#endif /* MOUNT_CIFS_VENDOR_SUFFIX */
#ifndef MS_MOVE
#define MS_MOVE 8192
#endif
-char * thisprogram;
+#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
+
+const char *thisprogram;
int verboseflag = 0;
static int got_password = 0;
static int got_user = 0;
@@ -292,7 +303,7 @@ static int get_password_from_file(int file_descript, char * filename)
static int parse_options(char ** optionsp, int * filesys_flags)
{
- char * data;
+ const char * data;
char * percent_char = NULL;
char * value = NULL;
char * next_keyword = NULL;
@@ -745,7 +756,7 @@ static char * parse_server(char ** punc_name)
if(length < 3) {
/* BB add code to find DFS root here */
- printf("\nMounting the DFS root for domain not implemented yet");
+ printf("\nMounting the DFS root for domain not implemented yet\n");
return NULL;
} else {
if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
@@ -852,7 +863,7 @@ int main(int argc, char ** argv)
char * share_name = NULL;
char * ipaddr = NULL;
char * uuid = NULL;
- char * mountpoint;
+ char * mountpoint = NULL;
char * options;
char * resolved_path;
char * temp;
@@ -876,7 +887,11 @@ int main(int argc, char ** argv)
if(argc && argv) {
thisprogram = argv[0];
+ } else {
+ mount_cifs_usage();
+ exit(1);
}
+
if(thisprogram == NULL)
thisprogram = "mount.cifs";
@@ -886,9 +901,10 @@ int main(int argc, char ** argv)
/* #ifdef _GNU_SOURCE
printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
#endif */
-
- share_name = argv[1];
- mountpoint = argv[2];
+ if(argc > 2) {
+ share_name = argv[1];
+ mountpoint = argv[2];
+ }
/* add sharename in opts string as unc= parm */
@@ -1017,8 +1033,10 @@ int main(int argc, char ** argv)
}
}
- if(argc < 3)
+ if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
mount_cifs_usage();
+ exit(1);
+ }
if (getenv("PASSWD")) {
if(mountpassword == NULL)
@@ -1099,6 +1117,8 @@ mount_retry:
optlen += strlen(share_name) + 4;
else {
printf("No server share name specified\n");
+ printf("\nMounting the DFS root for server not implemented yet\n");
+ exit(1);
}
if(user_name)
optlen += strlen(user_name) + 6;
@@ -1197,7 +1217,7 @@ mount_retry:
if(pmntfile) {
mountent.mnt_fsname = share_name;
mountent.mnt_dir = mountpoint;
- mountent.mnt_type = "cifs";
+ mountent.mnt_type = CONST_DISCARD(char *,"cifs");
mountent.mnt_opts = malloc(220);
if(mountent.mnt_opts) {
char * mount_user = getusername();
diff --git a/source/client/smbctool.c b/source/client/smbctool.c
index dc7d2c78f4b..6c89f5ea827 100644
--- a/source/client/smbctool.c
+++ b/source/client/smbctool.c
@@ -544,19 +544,17 @@ static void adjust_do_list_queue(void)
static void add_to_do_list_queue(const char* entry)
{
- char *dlq;
long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
while (new_end > do_list_queue_size) {
do_list_queue_size *= 2;
DEBUG(4,("enlarging do_list_queue to %d\n",
(int)do_list_queue_size));
- dlq = SMB_REALLOC(do_list_queue, do_list_queue_size);
- if (! dlq) {
+ do_list_queue = 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);
reset_do_list_queue();
} else {
- do_list_queue = dlq;
memset(do_list_queue + do_list_queue_size / 2,
0, do_list_queue_size / 2);
}
@@ -3652,7 +3650,7 @@ static int do_message_op(void)
if ( override_logfile )
setup_logging( lp_logfile(), False );
- if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
argv[0], dyn_CONFIGFILE);
}
diff --git a/source/client/smbmount.c b/source/client/smbmount.c
index d0ea18d9835..7a3ccb7630d 100644
--- a/source/client/smbmount.c
+++ b/source/client/smbmount.c
@@ -912,7 +912,7 @@ static void parse_mount_smb(int argc, char **argv)
pstrcpy(username,getenv("LOGNAME"));
}
- if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n",
dyn_CONFIGFILE);
}
diff --git a/source/client/smbspool.c b/source/client/smbspool.c
index 7fe918413d5..af2f7e9180c 100644
--- a/source/client/smbspool.c
+++ b/source/client/smbspool.c
@@ -214,7 +214,7 @@ static int smb_print(struct cli_state *, char *, FILE *);
in_client = True; /* Make sure that we tell lp_load we are */
- if (!lp_load(dyn_CONFIGFILE, True, False, False))
+ if (!lp_load(dyn_CONFIGFILE, True, False, False, True))
{
fprintf(stderr, "ERROR: Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
return (1);
@@ -299,15 +299,15 @@ list_devices(void)
static
char * get_ticket_cache( uid_t uid )
{
+ char *ticket_file = NULL;
SMB_STRUCT_DIR *tcdir; /* directory where ticket caches are stored */
SMB_STRUCT_DIRENT *dirent; /* directory entry */
char *filename = NULL; /* holds file names on the tmp directory */
SMB_STRUCT_STAT buf;
char user_cache_prefix[CC_MAX_FILE_LEN];
char file_path[CC_MAX_FILE_PATH_LEN];
- char *ticket_file = NULL;
time_t t = 0;
-
+
snprintf(user_cache_prefix, CC_MAX_FILE_LEN, "%s%d", CC_PREFIX, uid );
tcdir = sys_opendir( TICKET_CC_DIR );
if ( tcdir == NULL )
@@ -375,9 +375,14 @@ static struct cli_state
return NULL;
}
-
+ /* We pretty much guarentee password must be valid or a pointer
+ to a 0 char. */
+ if (!password) {
+ return NULL;
+ }
+
if ( (username) && (*username) &&
- ((!password) || ((password) && (strlen(password) == 0 ))) &&
+ (strlen(password) == 0 ) &&
(cli->use_kerberos) )
{
/* Use kerberos authentication */
diff --git a/source/client/umount.cifs.c b/source/client/umount.cifs.c
index 3a6c1aa9566..e762be8f062 100644
--- a/source/client/umount.cifs.c
+++ b/source/client/umount.cifs.c
@@ -34,14 +34,22 @@
#include <errno.h>
#include <string.h>
#include <mntent.h>
-#include <fstab.h>
#define UNMOUNT_CIFS_VERSION_MAJOR "0"
#define UNMOUNT_CIFS_VERSION_MINOR "5"
#ifndef UNMOUNT_CIFS_VENDOR_SUFFIX
-#define UNMOUNT_CIFS_VENDOR_SUFFIX ""
-#endif
+ #ifdef _SAMBA_BUILD_
+ #include "include/version.h"
+ #ifdef SAMBA_VERSION_VENDOR_SUFFIX
+ #define UNMOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING"-"SAMBA_VERSION_VENDOR_SUFFIX
+ #else
+ #define UNMOUNT_CIFS_VENDOR_SUFFIX "-"SAMBA_VERSION_OFFICIAL_STRING
+ #endif /* SAMBA_VERSION_OFFICIAL_STRING and SAMBA_VERSION_VENDOR_SUFFIX */
+ #else
+ #define UNMOUNT_CIFS_VENDOR_SUFFIX ""
+ #endif /* _SAMBA_BUILD_ */
+#endif /* UNMOUNT_CIFS_VENDOR_SUFFIX */
#ifndef MNT_DETACH
#define MNT_DETACH 0x02
@@ -75,7 +83,7 @@ static struct option longopts[] = {
{ NULL, 0, NULL, 0 }
};
-char * thisprogram;
+const char * thisprogram;
int verboseflg = 0;
static void umount_cifs_usage(void)
diff --git a/source/configure.in b/source/configure.in
index b011361a4df..c479d2d290f 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -22,12 +22,14 @@ fi
# ones...
AC_PREFIX_DEFAULT(/usr/local/samba)
+rootsbindir="\${SBINDIR}"
lockdir="\${VARDIR}/locks"
piddir="\${VARDIR}/locks"
-mandir="\${prefix}/man"
+test "${mandir}" || mandir="\${prefix}/man"
logfilebase="\${VARDIR}"
privatedir="\${prefix}/private"
-libdir="\${prefix}/lib"
+test "${libdir}" || libdir="\${prefix}/lib"
+pammodulesdir="\${LIBDIR}/security"
configdir="\${LIBDIR}"
swatdir="\${prefix}/swat"
@@ -63,6 +65,22 @@ AC_ARG_WITH(privatedir,
esac])
#################################################
+# set root sbin directory location
+AC_ARG_WITH(rootsbindir,
+[ --with-rootsbindir=DIR Which directory to use for root sbin ($ac_default_prefix/sbin)],
+[ case "$withval" in
+ yes|no)
+ #
+ # Just in case anybody calls it without argument
+ #
+ AC_MSG_WARN([--with-rootsbindir called without argument - will use default])
+ ;;
+ * )
+ rootsbindir="$withval"
+ ;;
+ esac])
+
+#################################################
# set lock directory location
AC_ARG_WITH(lockdir,
[ --with-lockdir=DIR Where to put lock files ($ac_default_prefix/var/locks)],
@@ -159,7 +177,23 @@ AC_ARG_WITH(libdir,
esac])
#################################################
-# set lib directory location
+# set PAM modules directory location
+AC_ARG_WITH(pammodulesdir,
+[ --with-pammodulesdir=DIR Which directory to use for PAM modules ($ac_default_prefix/$libdir/security)],
+[ case "$withval" in
+ yes|no)
+ #
+ # Just in case anybody calls it without argument
+ #
+ AC_MSG_WARN([--with-pammodulesdir called without argument - will use default])
+ ;;
+ * )
+ pammodulesdir="$withval"
+ ;;
+ esac])
+
+#################################################
+# set man directory location
AC_ARG_WITH(mandir,
[ --with-mandir=DIR Where to put man pages ($mandir)],
[ case "$withval" in
@@ -201,12 +235,14 @@ AC_SUBST(privatedir)
AC_SUBST(swatdir)
AC_SUBST(bindir)
AC_SUBST(sbindir)
+AC_SUBST(rootsbindir)
+AC_SUBST(pammodulesdir)
dnl Unique-to-Samba variables we'll be playing with.
AC_SUBST(SHELL)
AC_SUBST(LDSHFLAGS)
AC_SUBST(SONAMEFLAG)
-AC_SUBST(SONAMEVERSIONSUFFIX)
+AC_SUBST(NSSSONAMEVERSIONSUFFIX)
AC_SUBST(SHLD)
AC_SUBST(HOST_OS)
AC_SUBST(PICFLAGS)
@@ -217,10 +253,14 @@ AC_SUBST(PIE_LDFLAGS)
AC_SUBST(SHLIBEXT)
AC_SUBST(INSTALLLIBCMD_SH)
AC_SUBST(INSTALLLIBCMD_A)
+AC_SUBST(UNINSTALLLIBCMD_SH)
+AC_SUBST(UNINSTALLLIBCMD_A)
AC_SUBST(INSTALL_LIBMSRPC)
+AC_SUBST(UNINSTALL_LIBMSRPC)
AC_SUBST(LIBMSRPC_SHARED)
AC_SUBST(LIBMSRPC)
AC_SUBST(INSTALL_LIBSMBCLIENT)
+AC_SUBST(UNINSTALL_LIBSMBCLIENT)
AC_SUBST(LIBSMBCLIENT_SHARED)
AC_SUBST(LIBSMBCLIENT)
AC_SUBST(INSTALL_LIBSMBSHAREMODES)
@@ -234,13 +274,20 @@ AC_SUBST(IDMAP_LIBS)
AC_SUBST(KRB5_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)
+AC_SUBST(UNINSTALL_CIFSMOUNT)
AC_SUBST(EXTRA_SBIN_PROGS)
AC_SUBST(EXTRA_ALL_TARGETS)
AC_SUBST(CONFIG_LIBS)
+AC_SUBST(NSCD_LIBS)
# Set defaults
PIE_CFLAGS=""
@@ -281,6 +328,41 @@ AC_ARG_ENABLE(socket-wrapper,
SOCKWRAP="\$(SOCKET_WRAPPER_OBJ)"
fi])
+#################################################
+# set prefix for 'make test'
+selftest_prefix="./"
+AC_SUBST(selftest_prefix)
+AC_ARG_WITH(selftest-prefix,
+[ --with-selftest-prefix=DIR The prefix where make test will be runned ($selftest_prefix)],
+[ case "$withval" in
+ yes|no)
+ AC_MSG_WARN([--with-selftest-prefix called without argument - will use default])
+ ;;
+ * )
+ selftest_prefix="$withval"
+ ;;
+ esac
+])
+
+#################################################
+# set path of samba4's smbtorture
+smbtorture4_path=""
+AC_SUBST(smbtorture4_path)
+AC_ARG_WITH(smbtorture4_path,
+[ --with-smbtorture4-path=PATH The path to a samba4 smbtorture for make test (none)],
+[ case "$withval" in
+ yes|no)
+ AC_MSG_ERROR([--with-smbtorture4-path should take a path])
+ ;;
+ * )
+ smbtorture4_path="$withval"
+ if test -z "$smbtorture4_path" -a ! -f $smbtorture4_path; then
+ AC_MSG_ERROR(['$smbtorture_path' does not exist!])
+ fi
+ ;;
+ 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"
@@ -463,7 +545,7 @@ DYNEXP=
dnl Add modules that have to be built by default here
dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
+default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
dnl These are preferably build shared, and static if dlopen() is not available
default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_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"
@@ -745,8 +827,9 @@ 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/syslog.h syslog.h execinfo.h)
+AC_CHECK_HEADERS(sys/syslog.h syslog.h)
AC_CHECK_HEADERS(langinfo.h locale.h)
+AC_CHECK_HEADERS(sys/dmi.h xfs/dmapi.h sys/jfsdmapi.h sys/dmapi.h)
AC_CHECK_HEADERS(rpcsvc/yp_prot.h,,,[[
#if HAVE_RPC_RPC_H
@@ -795,8 +878,11 @@ 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(sys/capability.h 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 sys/proplist.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)
+AC_CHECK_HEADERS(sys/ea.h sys/proplist.h)
+
AC_CHECK_HEADERS(sys/cdefs.h glob.h)
AC_CHECK_HEADERS(netinet/ip.h,,,[[
@@ -828,6 +914,7 @@ AC_CHECK_HEADERS(utmp.h utmpx.h lastlog.h)
AC_CHECK_SIZEOF(int,cross)
AC_CHECK_SIZEOF(long,cross)
+AC_CHECK_SIZEOF(long long,cross)
AC_CHECK_SIZEOF(short,cross)
AC_C_CONST
@@ -1151,15 +1238,54 @@ 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(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)
# setbuffer, shmget, shm_open are needed for smbtorture
-AC_CHECK_FUNCS(setbuffer shmget shm_open backtrace_symbols)
-AC_CHECK_HEADERS(libexc.h)
+AC_CHECK_FUNCS(setbuffer shmget shm_open)
+
+# Find a method of generating a stack trace
+AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
+AC_CHECK_FUNCS(backtrace_symbols)
AC_CHECK_LIB(exc, trace_back_stack)
+# 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.
+AC_MSG_CHECKING([for libunwind])
+save_LIBS=$LIBS
+if test x"$UNAME_P" != xunknown ; then
+ # This probably won't link without the platform-specific libunwind.
+ LIBS="$LIBS -lunwind"
+else
+ # Add the platform-specific libunwind module. uname -p seems the most
+ # plausible option and works for ia64, where libunwind is most useful.
+ LIBS="$LIBS -lunwind -lunwind-$UNAME_P"
+fi
+
+AC_TRY_LINK(
+ [
+#ifdef HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+ ],
+ [
+ unw_context_t ctx; unw_cursor_t cur;
+ char buf[256]; unw_word_t off;
+ unw_getcontext(&ctx); unw_init_local(&cur, &ctx);
+ unw_get_proc_name(&cur, buf, sizeof(buf), &off);
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LIBUNWIND, 1, [Whether libunwind is available])
+ ],
+ [
+ AC_MSG_RESULT(no)
+ LIBS=$save_LIBS
+ ])
+
# syscall() is needed for smbwrapper.
AC_CHECK_FUNCS(syscall)
@@ -1170,7 +1296,7 @@ AC_CHECK_FUNCS(__xstat __fxstat __lxstat)
AC_CHECK_FUNCS(_stat _lstat _fstat __stat __lstat __fstat)
AC_CHECK_FUNCS(_acl __acl _facl __facl _open __open _chdir __chdir)
AC_CHECK_FUNCS(_close __close _fchdir __fchdir _fcntl __fcntl)
-AC_CHECK_FUNCS(getdents _getdents __getdents _lseek __lseek _read __read)
+AC_CHECK_FUNCS(getdents __getdents _lseek __lseek _read __read)
AC_CHECK_FUNCS(getdirentries _write __write _fork __fork)
AC_CHECK_FUNCS(_stat64 __stat64 _fstat64 __fstat64 _lstat64 __lstat64)
AC_CHECK_FUNCS(__sys_llseek llseek _llseek __llseek readdir64 _readdir64 __readdir64)
@@ -1316,6 +1442,45 @@ if test x"$samba_stat_hires" = x"yes" ; then
[whether struct stat has sub-second timestamps])
fi
+AC_CACHE_CHECK([whether struct stat has sub-second timestamps without struct timespec], samba_stat_hires_notimespec,
+ [
+ AC_TRY_COMPILE(
+ [
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+ ],
+ [
+ struct timespec t;
+ struct stat s = {0};
+ t.tv_sec = s.st_mtime;
+ t.tv_nsec = s.st_mtimensec;
+ t.tv_sec = s.st_ctime;
+ t.tv_nsec = s.st_ctimensec;
+ t.tv_sec = s.st_atime;
+ t.tv_nsec = s.st_atimensec;
+ ],
+ samba_stat_hires=yes, samba_stat_hires=no)
+ ])
+
+if test x"$samba_stat_hires_notimespec" = x"yes" ; then
+ AC_DEFINE(HAVE_STAT_ST_MTIMENSEC, 1, [whether struct stat contains st_mtimensec])
+ AC_DEFINE(HAVE_STAT_ST_ATIMENSEC, 1, [whether struct stat contains st_atimensec])
+ AC_DEFINE(HAVE_STAT_ST_CTIMENSEC, 1, [whether struct stat contains st_ctimensec])
+ AC_DEFINE(HAVE_STAT_HIRES_TIMESTAMPS, 1,
+ [whether struct stat has sub-second timestamps without struct timespec])
+fi
+
#####################################
# we might need the resolv library on some systems
AC_CHECK_LIB(resolv, dn_expand)
@@ -1344,6 +1509,8 @@ AC_LIBTESTFUNC(sec, bigcrypt)
AC_LIBTESTFUNC(security, getprpwnam)
AC_LIBTESTFUNC(sec, getprpwnam)
+AC_CHECK_FUNCS(strsignal)
+
############################################
# Check if we have libattr
case "$host_os" in
@@ -1356,6 +1523,8 @@ case "$host_os" in
*)
AC_SEARCH_LIBS(getxattr, [attr])
AC_CHECK_FUNCS(getxattr lgetxattr fgetxattr listxattr llistxattr)
+ AC_CHECK_FUNCS(getea fgetea lgetea listea flistea llistea)
+ AC_CHECK_FUNCS(removeea fremoveea lremoveea setea fsetea lsetea)
AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr)
AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr)
AC_CHECK_FUNCS(attr_get attr_list attr_set attr_remove)
@@ -1383,7 +1552,7 @@ BLDSHARED="false"
HOST_OS="$host_os"
LDSHFLAGS="-shared"
SONAMEFLAG="#"
-SONAMEVERSIONSUFFIX=""
+NSSSONAMEVERSIONSUFFIX=""
SHLD="\${CC} \${CFLAGS}"
PICFLAGS=""
PICSUFFIX="po"
@@ -1408,7 +1577,7 @@ if test "$enable_shared" = "yes"; then
DYNEXP="-Wl,--export-dynamic"
PICFLAGS="-fPIC"
SONAMEFLAG="-Wl,-soname="
- SONAMEVERSIONSUFFIX=".2"
+ NSSSONAMEVERSIONSUFFIX=".2"
AC_DEFINE(STAT_ST_BLOCKSIZE,512)
;;
*solaris*) AC_DEFINE(SUNOS5,1,[Whether the host os is solaris])
@@ -1417,6 +1586,8 @@ if test "$enable_shared" = "yes"; then
SONAMEFLAG="-h "
if test "${GCC}" = "yes"; then
PICFLAGS="-fPIC"
+ SONAMEFLAG="-Wl,-soname="
+ NSSSONAMEVERSIONSUFFIX=".1"
if test "${ac_cv_prog_gnu_ld}" = "yes"; then
DYNEXP="-Wl,-E"
fi
@@ -1473,7 +1644,7 @@ if test "$enable_shared" = "yes"; then
;;
*aix*) AC_DEFINE(AIX,1,[Whether the host os is aix])
BLDSHARED="true"
- LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-bnoentry,-berok"
+ LDSHFLAGS="-Wl,-G,-bexpall"
DYNEXP="-Wl,-brtl,-bexpall,-bbigtoc"
PICFLAGS="-O2"
if test "${GCC}" != "yes"; then
@@ -1847,15 +2018,15 @@ 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
-AC_CACHE_CHECK([for broken readdir],samba_cv_HAVE_BROKEN_READDIR,[
+AC_CACHE_CHECK([for broken readdir name],samba_cv_HAVE_BROKEN_READDIR_NAME,[
AC_TRY_RUN([#include <sys/types.h>
#include <dirent.h>
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) exit(0); exit(1);} ],
-samba_cv_HAVE_BROKEN_READDIR=yes,samba_cv_HAVE_BROKEN_READDIR=no,samba_cv_HAVE_BROKEN_READDIR=cross)])
-if test x"$samba_cv_HAVE_BROKEN_READDIR" = x"yes"; then
- AC_DEFINE(HAVE_BROKEN_READDIR,1,[Whether readdir() is broken])
+samba_cv_HAVE_BROKEN_READDIR_NAME=yes,samba_cv_HAVE_BROKEN_READDIR_NAME=no,samba_cv_HAVE_BROKEN_READDIR_NAME=cross)])
+if test x"$samba_cv_HAVE_BROKEN_READDIR_NAME" = x"yes"; then
+ AC_DEFINE(HAVE_BROKEN_READDIR_NAME,1,[Whether readdir() returns the wrong name offset])
fi
AC_CACHE_CHECK([for utimbuf],samba_cv_HAVE_UTIMBUF,[
@@ -2177,6 +2348,65 @@ if test x"$samba_cv_HAVE_KERNEL_CHANGE_NOTIFY" = x"yes"; then
AC_DEFINE(HAVE_KERNEL_CHANGE_NOTIFY,1,[Whether kernel notifies changes])
fi
+#################################################
+# Check if FAM notifications are available. For FAM info, see
+# http://oss.sgi.com/projects/fam/
+# http://savannah.nongnu.org/projects/fam/
+
+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
+
+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]),
+ [])
+fi
+
+#################################################
+# Check for DMAPI interfaces in libdm/libjfsdm/libxsdm
+
+AC_CHECK_LIB(dm, dm_get_eventlist,
+ [samba_cv_HAVE_LIBDM=yes; samba_dmapi_libs="-ldm"],
+ [samba_cv_HAVE_LIBDM=no])
+
+if test x"$samba_cv_HAVE_LIBDM" = x"yes" ; then
+ AC_DEFINE(HAVE_LIBDM, 1, [Whether dmapi libdm is available])
+fi
+
+AC_CHECK_LIB(jfsdm, dm_get_eventlist,
+ [samba_cv_HAVE_LIBJFSDM=yes; samba_dmapi_libs="-ljfsdm"],
+ [samba_cv_HAVE_LIBJFSDM=no])
+
+if test x"$samba_cv_HAVE_LIBJFSDM" = x"yes" ; then
+ AC_DEFINE(HAVE_LIBJFSDM, 1, [Whether dmapi libjfsdm is available])
+fi
+
+AC_CHECK_LIB(xdsm, dm_get_eventlist,
+ [samba_cv_HAVE_LIBXDSM=yes; samba_dmapi_libs="-lxdsm"],
+ [samba_cv_HAVE_LIBXDSM=no])
+
+if test x"$samba_cv_HAVE_LIBXDSM" = x"yes" ; then
+ AC_DEFINE(HAVE_LIBXDSM, 1, [Whether dmapi libxdsm is available])
+fi
+
AC_CACHE_CHECK([for kernel share modes],samba_cv_HAVE_KERNEL_SHARE_MODES,[
AC_TRY_RUN([
#include <sys/types.h>
@@ -2197,8 +2427,6 @@ if test x"$samba_cv_HAVE_KERNEL_SHARE_MODES" = x"yes"; then
fi
-
-
AC_CACHE_CHECK([for IRIX kernel oplock type definitions],samba_cv_HAVE_KERNEL_OPLOCKS_IRIX,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <fcntl.h>],
@@ -2208,22 +2436,46 @@ if test x"$samba_cv_HAVE_KERNEL_OPLOCKS_IRIX" = x"yes"; then
AC_DEFINE(HAVE_KERNEL_OPLOCKS_IRIX,1,[Whether IRIX kernel oplock type definitions are available])
fi
-AC_CACHE_CHECK([for irix specific capabilities],samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES,[
-AC_TRY_RUN([#include <sys/types.h>
+#################################################
+# Check for POSIX capability support
+
+AC_CHECK_HEADER(sys/capability.h, [samba_cv_HAVE_SYS_CAPABILITY_H=yes;
+ AC_DEFINE(HAVE_SYS_CAPABILITY_H, 1, Whether sys/capability.h is present)],
+ [], [])
+
+if test x"$samba_cv_HAVE_SYS_CAPABILITY_H" = x"yes"; then
+
+ ac_save_LIBS=$LIBS
+ AC_LIBTESTFUNC(cap, cap_get_proc)
+
+ AC_CACHE_CHECK([for POSIX capabilities],
+ samba_cv_HAVE_POSIX_CAPABILITIES,
+ [
+ AC_TRY_RUN([
+#include <sys/types.h>
#include <sys/capability.h>
main() {
cap_t cap;
- if ((cap = cap_get_proc()) == NULL)
+ cap_value_t vals[1];
+ if (!(cap = cap_get_proc()))
exit(1);
- cap->cap_effective |= CAP_NETWORK_MGT;
- cap->cap_inheritable |= CAP_NETWORK_MGT;
+ vals[0] = CAP_CHOWN;
+ cap_set_flag(cap, CAP_INHERITABLE, 1, vals, CAP_CLEAR);
cap_set_proc(cap);
exit(0);
-}
-],
-samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=yes,samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=no,samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=cross)])
-if test x"$samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES" = x"yes"; then
- AC_DEFINE(HAVE_IRIX_SPECIFIC_CAPABILITIES,1,[Whether IRIX specific capabilities are available])
+}],
+ samba_cv_HAVE_POSIX_CAPABILITIES=yes,
+ samba_cv_HAVE_POSIX_CAPABILITIES=no,
+ samba_cv_HAVE_POSIX_CAPABILITIES=cross)
+ ])
+
+if test x"$samba_cv_HAVE_POSIX_CAPABILITIES" = x"yes"; then
+ AC_DEFINE(HAVE_POSIX_CAPABILITIES, 1,
+ [Whether POSIX capabilities are available])
+else
+ LIBS=$ac_save_LIBS
+fi
+
fi
#
@@ -2383,6 +2635,24 @@ if test x"$samba_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
AC_DEFINE(HAVE_SECURE_MKSTEMP,1,[Whether mkstemp is secure])
fi
+AC_CACHE_CHECK([for broken readdir],samba_cv_HAVE_BROKEN_READDIR,[
+ AC_TRY_RUN([#include "${srcdir-.}/tests/os2_delete.c"],
+ [samba_cv_HAVE_BROKEN_READDIR=no],
+ [samba_cv_HAVE_BROKEN_READDIR=yes],
+ [samba_cv_HAVE_BROKEN_READDIR="assuming not"])])
+
+if test x"$samba_cv_HAVE_BROKEN_READDIR" = x"yes"; then
+AC_CACHE_CHECK([for replacing readdir],samba_cv_REPLACE_READDIR,[
+ AC_TRY_RUN([
+#include "${srcdir-.}/lib/repdir.c"
+#include "${srcdir-.}/tests/os2_delete.c"],
+ samba_cv_REPLACE_READDIR=yes,samba_cv_REPLACE_READDIR=no)])
+fi
+
+if test x"$samba_cv_REPLACE_READDIR" = x"yes"; then
+ AC_DEFINE(REPLACE_READDIR,1,[replace readdir])
+fi
+
AC_CACHE_CHECK([for sysconf(_SC_NGROUPS_MAX)],samba_cv_SYSCONF_SC_NGROUPS_MAX,[
AC_TRY_RUN([#include <unistd.h>
main() { exit(sysconf(_SC_NGROUPS_MAX) == -1 ? 1 : 0); }],
@@ -2849,6 +3119,8 @@ 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)
+
if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes"; then
AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED"
@@ -2893,42 +3165,52 @@ FOUND_KRB5=no
KRB5_LIBS=""
if test x"$with_ldap_support" != x"yes"; then
+
if test x"$with_ads_support" = x"yes"; then
AC_MSG_ERROR(Active Directory Support requires LDAP support)
- elif test x"$with_ads_support" != x"no"; then
- AC_MSG_WARN(Active Directory Support requires LDAP support)
+ elif test x"$with_ads_support" = x"auto"; then
+ AC_MSG_WARN(Disabling Active Directory support (requires LDAP support))
+ with_ads_support=no
fi
- with_ads_support=no
-fi
-AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS)
+else
-if test x"$ac_cv_func_ext_ldap_initialize" != x"yes"; then
- if test x"$with_ads_support" = x"yes"; then
- AC_MSG_ERROR(Active Directory Support requires ldap_initialize)
+ # Check to see whether there is enough LDAP functionality to be able
+ # to build AD support.
+
+ AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS)
+
+ if test x"$ac_cv_func_ext_ldap_initialize" != x"yes"; then
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(Active Directory support requires ldap_initialize)
+ elif test x"$with_ads_support" = x"auto"; then
+ AC_MSG_WARN(Disabling Active Directory support (requires ldap_initialize))
+ with_ads_support=no
+ fi
fi
- AC_MSG_WARN(Active Directory Support requires ldap_initialize)
- with_ads_support=no
-fi
-AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS)
+ AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS)
-if test x"$ac_cv_func_ext_ldap_domain2hostlist" != x"yes"; then
- if test x"$with_ads_support" = x"yes"; then
- AC_MSG_ERROR(Active Directory Support requires ldap_domain2hostlist)
+ if test x"$ac_cv_func_ext_ldap_domain2hostlist" != x"yes"; then
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(Active Directory support requires ldap_domain2hostlist)
+ elif test x"$with_ads_support" = x"auto"; then
+ AC_MSG_WARN(Disabling Active Directory support (requires ldap_domain2hostlist))
+ with_ads_support=no
+ fi
fi
- AC_MSG_WARN(Active Directory Support requires ldap_domain2hostlist)
- with_ads_support=no
-fi
-AC_CHECK_FUNC_EXT(ldap_add_result_entry,$LDAP_LIBS)
+ AC_CHECK_FUNC_EXT(ldap_add_result_entry,$LDAP_LIBS)
-if test x"$ac_cv_func_ext_ldap_add_result_entry" != x"yes"; then
- if test x"$with_ads_support" = x"yes"; then
- AC_MSG_ERROR(Active Directory Support requires ldap_add_result_entry)
+ if test x"$ac_cv_func_ext_ldap_add_result_entry" != x"yes"; then
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(Active Directory support requires ldap_add_result_entry)
+ elif test x"$with_ads_support" = x"auto"; then
+ AC_MSG_WARN(Disabling Active Directory support (requires ldap_add_result_entry))
+ with_ads_support=no
+ fi
fi
- AC_MSG_WARN(Active Directory Support requires ldap_add_result_entry)
- with_ads_support=no
+
fi
if test x"$with_ads_support" != x"no"; then
@@ -3122,6 +3404,9 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_principal_compare_any_realm, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_parse_name_norealm, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_princ_size, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_get_init_creds_opt_set_pac_request, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_get_renewed_creds, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_get_kdc_cred, $KRB5_LIBS)
LIBS="$KRB5_LIBS $LIBS"
@@ -3423,47 +3708,7 @@ if test x"$with_ads_support" != x"no"; then
LIBS="$ac_save_LIBS"
fi
-########################################################
-# Compile experimental passdb backends?
-# (pdb_xml, pdb_mysql, pdb_pgsql)
-AC_MSG_CHECKING(whether to build experimental passdb libraries)
-AC_ARG_WITH(expsam,
-[ --with-expsam=<list> Include experimental passdb libraries (default=no)]
-[ Valid choices include (comma separated list): ]
-[ xml, mysql & pgsql],
-[ expsam_pdb_modules=`echo "$withval" | sed 's/,/ /g'`
- if test "z$expsam_pdb_modules" = "zyes"; then
- expsam_pdb_modules="xml mysql pgsql"
- fi
- AC_MSG_RESULT($expsam_pdb_modules)
- for i in $expsam_pdb_modules
- do
- case "$i" in
- xml|all|yes)
- ## pdb_xml
- AM_PATH_XML2([2.0.0],[default_shared_modules="$default_shared_modules pdb_xml"],[AC_MSG_ERROR([Can't find XML libraries while XML support is requested])])
- CFLAGS="$CFLAGS $XML_CFLAGS"
- ;;
- mysql|all|yes)
- ## pdb_mysql
- AM_PATH_MYSQL([default_shared_modules="$default_shared_modules pdb_mysql"],[AC_MSG_ERROR([Can't find MySQL libraries while MySQL support is requested])])
- CFLAGS="$CFLAGS $MYSQL_CFLAGS"
- ;;
- pgsql|all|yes)
- ## pdb_pgsql
- AM_PATH_PGSQL([default_shared_modules="$default_shared_modules pdb_pgsql"],[])
- CFLAGS="$CFLAGS $PGSQL_CFLAGS"
- ;;
- no)
- ;;
- *)
- echo "Unknown module name \"$i\"! Exiting..."
- exit 1
- ;;
- esac
- done ],
- AC_MSG_RESULT(no)
-)
+AC_CHECK_LIB_EXT(nscd, NSCD_LIBS, nscd_flush_cache)
#################################################
# check for automount support
@@ -3507,6 +3752,46 @@ AC_ARG_WITH(smbmount,
AC_MSG_RESULT(no)
)
+#################################################
+# check for mount- and umount.cifs support
+CIFSMOUNT_PROGS=""
+INSTALL_CIFSMOUNT=""
+UNINSTALL_CIFSMOUNT=""
+AC_MSG_CHECKING(whether to build mount.cifs and umount.cifs)
+AC_ARG_WITH(cifsmount,
+[ --with-cifsmount Include mount.cifs and umount.cifs (Linux only) support (default=yes)],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ case "$host_os" in
+ *linux*)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(WITH_CIFSMOUNT,1,[Whether to build mount.cifs and umount.cifs])
+ CIFSMOUNT_PROGS="bin/mount.cifs bin/umount.cifs"
+ INSTALL_CIFSMOUNT="installcifsmount"
+ UNINSTALL_CIFSMOUNT="uninstallcifsmount"
+ ;;
+ *)
+ AC_MSG_ERROR(not on a linux system!)
+ ;;
+ esac
+ ;;
+ esac ],
+[ case "$host_os" in
+ *linux*)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(WITH_CIFSMOUNT,1,[Whether to build mount.cifs and umount.cifs])
+ CIFSMOUNT_PROGS="bin/mount.cifs bin/umount.cifs"
+ INSTALL_CIFSMOUNT="installcifsmount"
+ UNINSTALL_CIFSMOUNT="uninstallcifsmount"
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+ esac ]
+)
#################################################
@@ -3541,6 +3826,9 @@ AC_CHECK_LIB(pam, pam_get_data, [AC_DEFINE(HAVE_LIBPAM,1,[Whether libpam is avai
#################################################
# check for pam_smbpass support
+PAM_MODULES=""
+INSTALL_PAM_MODULES=""
+UNINSTALL_PAM_MODULES=""
AC_MSG_CHECKING(whether to use pam_smbpass)
AC_ARG_WITH(pam_smbpass,
[ --with-pam_smbpass Build PAM module for authenticating against passdb backends (default=no)],
@@ -3558,7 +3846,9 @@ AC_ARG_WITH(pam_smbpass,
AC_MSG_ERROR([No libpam found])
else
AUTH_LIBS="$AUTH_LIBS -lpam"
- SHLIB_PROGS="$SHLIB_PROGS bin/pam_smbpass.$SHLIBEXT"
+ PAM_MODULES="pam_smbpass"
+ INSTALL_PAM_MODULES="installpammodules"
+ UNINSTALL_PAM_MODULES="uninstallpammodules"
fi
;;
*)
@@ -4025,17 +4315,22 @@ fi
INSTALLLIBCMD_SH=:
INSTALLLIBCMD_A=:
+UNINSTALLLIBCMD_SH=:
+UNINSTALLLIBCMD_A=:
if test $BLDSHARED = true; then
INSTALLLIBCMD_SH="\$(INSTALLCMD)"
+ UNINSTALLLIBCMD_SH="rm -f"
fi
if test $enable_static = yes; then
INSTALLLIBCMD_A="\$(INSTALLCMD)"
+ UNINSTALLLIBCMD_A="rm -f"
fi
#################################################
# should we build libmsrpc?
INSTALL_LIBMSRPC=
+UNINSTALL_LIBMSRPC=
LIBMSRPC_SHARED=
LIBMSRPC=
AC_MSG_CHECKING(whether to build the libmsrpc shared library)
@@ -4058,6 +4353,7 @@ AC_ARG_WITH(libmsrpc,
LIBMSRPC=libmsrpc
fi
INSTALL_LIBMSRPC=installlibmsrpc
+ UNINSTALL_LIBMSRPC=uninstalllibmsrpc
;;
esac ],
[
@@ -4074,11 +4370,13 @@ AC_ARG_WITH(libmsrpc,
LIBMSRPC=libmsrpc
fi]
INSTALL_LIBMSRPC=installlibmsrpc
+ UNINSTALL_LIBMSRPC=uninstalllibmsrpc
)
#################################################
# should we build libsmbclient?
INSTALL_LIBSMBCLIENT=
+UNINSTALL_LIBSMBCLIENT=
LIBSMBCLIENT_SHARED=
LIBSMBCLIENT=
AC_MSG_CHECKING(whether to build the libsmbclient shared library)
@@ -4101,6 +4399,7 @@ AC_ARG_WITH(libsmbclient,
LIBSMBCLIENT=libsmbclient
fi
INSTALL_LIBSMBCLIENT=installclientlib
+ UNINSTALL_LIBSMBCLIENT=uninstallclientlib
;;
esac ],
[
@@ -4117,6 +4416,7 @@ AC_ARG_WITH(libsmbclient,
LIBSMBCLIENT=libsmbclient
fi]
INSTALL_LIBSMBCLIENT=installclientlib
+ UNINSTALL_LIBSMBCLIENT=uninstallclientlib
)
INSTALL_LIBSMBSHAREMODES=
@@ -4994,7 +5294,9 @@ if test x"$HAVE_WINBIND" = x"yes"; then
SHLIB_PROGS="$SHLIB_PROGS $WINBIND_NSS $WINBIND_WINS_NSS"
if test x"$with_pam" = x"yes"; then
- SHLIB_PROGS="$SHLIB_PROGS nsswitch/pam_winbind.$SHLIBEXT"
+ PAM_MODULES="$PAM_MODULES pam_winbind"
+ INSTALL_PAM_MODULES="installpammodules"
+ UNINSTALL_PAM_MODULES="uninstallpammodules"
fi
fi
else
@@ -5061,6 +5363,43 @@ AC_SUBST(POPTLIBS)
AC_SUBST(FLAGS1)
#################################################
+# Check to see if we should use the included iniparser
+
+AC_ARG_WITH(included-iniparser,
+[ --with-included-iniparser use bundled iniparser library, not from system],
+[
+ case "$withval" in
+ yes)
+ INCLUDED_INIPARSER=yes
+ ;;
+ no)
+ INCLUDED_INIPARSER=no
+ ;;
+ esac ],
+)
+if test x"$INCLUDED_INIPARSER" != x"yes"; then
+ AC_CHECK_LIB(iniparser, iniparser_load,
+ INCLUDED_INIPARSER=no, INCLUDED_INIPARSER=yes)
+fi
+
+AC_MSG_CHECKING(whether to use included iniparser)
+if test x"$INCLUDED_INIPARSER" = x"yes"; then
+ AC_MSG_RESULT(yes)
+ BUILD_INIPARSER='$(INIPARSER_OBJ)'
+ INIPARSERLIBS=""
+ FLAGS1="$FLAGS1 -I$srcdir/iniparser/src"
+else
+ AC_MSG_RESULT(no)
+ BUILD_INIPARSER=""
+ INIPARSERLIBS="-liniparser"
+fi
+AC_SUBST(BUILD_INIPARSER)
+AC_SUBST(INIPARSERLIBS)
+AC_SUBST(FLAGS1)
+
+
+
+#################################################
# Check if the user wants Python
# At the moment, you can use this to set which Python binary to link
@@ -5104,7 +5443,6 @@ do
done
dnl Always built these modules static
-MODULE_pdb_guest=STATIC
MODULE_rpc_spoolss=STATIC
MODULE_rpc_srv=STATIC
MODULE_idmap_tdb=STATIC
@@ -5127,24 +5465,10 @@ AC_ARG_WITH(shared-modules,
done
fi ])
-###########################################################################
-## contributed pdb_modules
-
-SMB_MODULE(pdb_xml, passdb/pdb_xml.o, "bin/xml.$SHLIBEXT", PDB,
- [ PASSDB_LIBS="$PASSDB_LIBS $XML_LIBS" ] )
-SMB_MODULE(pdb_mysql, passdb/pdb_mysql.o, "bin/mysql.$SHLIBEXT", PDB,
- [ PASSDB_LIBS="$PASSDB_LIBS $MYSQL_LIBS" ] )
-SMB_MODULE(pdb_pgsql, passdb/pdb_pgsql.o, "bin/pgsql.$SHLIBEXT", PDB,
- [ PASSDB_LIBS="$PASSDB_LIBS $PGSQL_LIBS" ] )
-
-## end of contributed pdb_modules
-###########################################################################
-
SMB_MODULE(pdb_ldap, passdb/pdb_ldap.o passdb/pdb_nds.o, "bin/ldapsam.$SHLIBEXT", PDB,
[ PASSDB_LIBS="$PASSDB_LIBS $LDAP_LIBS" ] )
SMB_MODULE(pdb_smbpasswd, passdb/pdb_smbpasswd.o, "bin/smbpasswd.$SHLIBEXT", PDB)
SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB)
-SMB_MODULE(pdb_guest, passdb/pdb_guest.o, "bin/guest.$SHLIBEXT", PDB)
SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o)
@@ -5155,7 +5479,7 @@ SMB_MODULE(rpc_wks, \$(RPC_WKS_OBJ), "bin/librpc_wkssvc.$SHLIBEXT", RPC)
SMB_MODULE(rpc_svcctl, \$(RPC_SVCCTL_OBJ), "bin/librpc_svcctl.$SHLIBEXT", RPC)
SMB_MODULE(rpc_ntsvcs, \$(RPC_NTSVCS_OBJ), "bin/librpc_ntsvcs.$SHLIBEXT", RPC)
SMB_MODULE(rpc_net, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RPC)
-SMB_MODULE(rpc_dfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
+SMB_MODULE(rpc_netdfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC)
SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC)
SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC)
@@ -5234,6 +5558,11 @@ AC_TRY_RUN([#include "${srcdir-.}/tests/summary.c"],
builddir=`pwd`
AC_SUBST(builddir)
+# Stuff the smbd-only libraries at the end of the smbd link
+# path (if we have them).
+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)
@@ -5242,7 +5571,7 @@ dnl Remove -I/usr/include/? from CFLAGS and CPPFLAGS
CFLAGS_REMOVE_USR_INCLUDE(CFLAGS)
CFLAGS_REMOVE_USR_INCLUDE(CPPFLAGS)
-AC_OUTPUT(include/stamp-h Makefile script/findsmb smbadduser script/gen-8bit-gap.sh)
+AC_OUTPUT(include/stamp-h Makefile script/findsmb smbadduser script/gen-8bit-gap.sh script/installbin.sh script/uninstallbin.sh)
#################################################
# Print very concise instructions on building/use
diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c
index 1e8586786cd..c701ef165dd 100644
--- a/source/groupdb/mapping.c
+++ b/source/groupdb/mapping.c
@@ -3,6 +3,8 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
* 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
@@ -35,89 +37,11 @@ static TDB_CONTEXT *tdb; /* used for driver files */
*/
#define MEMBEROF_PREFIX "MEMBEROF/"
-/****************************************************************************
-dump the mapping group mapping to a text file
-****************************************************************************/
-char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
-{
- static fstring group_type;
-
- switch(name_use) {
- case SID_NAME_USER:
- fstrcpy(group_type,"User");
- break;
- case SID_NAME_DOM_GRP:
- fstrcpy(group_type,"Domain group");
- break;
- case SID_NAME_DOMAIN:
- fstrcpy(group_type,"Domain");
- break;
- case SID_NAME_ALIAS:
- fstrcpy(group_type,"Local group");
- break;
- case SID_NAME_WKN_GRP:
- fstrcpy(group_type,"Builtin group");
- break;
- case SID_NAME_DELETED:
- fstrcpy(group_type,"Deleted");
- break;
- case SID_NAME_INVALID:
- fstrcpy(group_type,"Invalid");
- break;
- case SID_NAME_UNKNOWN:
- default:
- fstrcpy(group_type,"Unknown type");
- break;
- }
-
- fstrcpy(group, group_type);
- return group_type;
-}
-
-/****************************************************************************
-initialise first time the mapping list - called from init_group_mapping()
-****************************************************************************/
-static BOOL default_group_mapping(void)
-{
- DOM_SID sid_admins;
- DOM_SID sid_users;
- DOM_SID sid_guests;
- fstring str_admins;
- fstring str_users;
- fstring str_guests;
-
- /* Add the Wellknown groups */
-
- add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "");
- add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "");
- add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "");
- add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "");
- add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "");
- add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "");
- add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "");
- add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "");
- add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "");
-
- /* Add the defaults domain groups */
-
- sid_copy(&sid_admins, get_global_sam_sid());
- sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
- sid_to_string(str_admins, &sid_admins);
- add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "");
-
- sid_copy(&sid_users, get_global_sam_sid());
- sid_append_rid(&sid_users, DOMAIN_GROUP_RID_USERS);
- sid_to_string(str_users, &sid_users);
- add_initial_entry(-1, str_users, SID_NAME_DOM_GRP, "Domain Users", "");
-
- sid_copy(&sid_guests, get_global_sam_sid());
- sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
- sid_to_string(str_guests, &sid_guests);
- add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "");
-
- return True;
-}
+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.
****************************************************************************/
@@ -126,9 +50,12 @@ 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"));
@@ -136,7 +63,7 @@ static BOOL init_group_mapping(void)
}
/* handle a Samba upgrade */
- tdb_lock_bystring(tdb, vstring, 0);
+ tdb_lock_bystring(tdb, vstring);
/* Cope with byte-reversed older versions of the db. */
vers_id = tdb_fetch_int32(tdb, vstring);
@@ -146,6 +73,8 @@ static BOOL init_group_mapping(void)
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);
@@ -153,9 +82,20 @@ static BOOL init_group_mapping(void)
tdb_unlock_bystring(tdb, vstring);
- /* write a list of default groups */
- if(!default_group_mapping())
- return False;
+ /* 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;
}
@@ -196,19 +136,19 @@ static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
/****************************************************************************
initialise first time the mapping list
****************************************************************************/
-BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
+NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
{
GROUP_MAP map;
if(!init_group_mapping()) {
DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
+ return NT_STATUS_UNSUCCESSFUL;
}
map.gid=gid;
if (!string_to_sid(&map.sid, sid)) {
DEBUG(0, ("string_to_sid failed: %s", sid));
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
map.sid_name_use=sid_name_use;
@@ -219,6 +159,64 @@ BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_us
}
/****************************************************************************
+ Map a unix group to a newly created mapping
+****************************************************************************/
+NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap)
+{
+ NTSTATUS status;
+ GROUP_MAP map;
+ const char *grpname, *dom, *name;
+ uint32 rid;
+
+ if (pdb_getgrgid(&map, grp->gr_gid)) {
+ return NT_STATUS_GROUP_EXISTS;
+ }
+
+ map.gid = grp->gr_gid;
+ grpname = grp->gr_name;
+
+ if (lookup_name(tmp_talloc_ctx(), grpname, LOOKUP_NAME_ISOLATED,
+ &dom, &name, NULL, NULL)) {
+
+ const char *tmp = talloc_asprintf(
+ tmp_talloc_ctx(), "Unix Group %s", grp->gr_name);
+
+ DEBUG(5, ("%s exists as %s\\%s, retrying as \"%s\"\n",
+ grpname, dom, name, tmp));
+ grpname = tmp;
+ }
+
+ if (lookup_name(tmp_talloc_ctx(), grpname, LOOKUP_NAME_ISOLATED,
+ NULL, NULL, NULL, NULL)) {
+ DEBUG(3, ("\"%s\" exists, can't map it\n", grp->gr_name));
+ return NT_STATUS_GROUP_EXISTS;
+ }
+
+ fstrcpy(map.nt_name, grpname);
+
+ if (pdb_rid_algorithm()) {
+ rid = pdb_gid_to_group_rid( grp->gr_gid );
+ } else {
+ if (!pdb_new_rid(&rid)) {
+ DEBUG(3, ("Could not get a new RID for %s\n",
+ grp->gr_name));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ sid_compose(&map.sid, get_global_sam_sid(), rid);
+ map.sid_name_use = SID_NAME_DOM_GRP;
+ fstrcpy(map.comment, talloc_asprintf(tmp_talloc_ctx(), "Unix Group %s",
+ grp->gr_name));
+
+ status = pdb_add_group_mapping_entry(&map);
+ if (NT_STATUS_IS_OK(status)) {
+ *pmap = map;
+ }
+ return status;
+}
+
+/****************************************************************************
Return the sid and the type of the unix group.
****************************************************************************/
@@ -255,7 +253,7 @@ static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
return False;
}
-
+
sid_copy(&map->sid, &sid);
return True;
@@ -352,7 +350,7 @@ static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
return False;
}
- if (StrCaseCmp(name, map->nt_name)==0) {
+ if ( strequal(name, map->nt_name) ) {
SAFE_FREE(kbuf.dptr);
return True;
}
@@ -400,16 +398,17 @@ static BOOL group_map_remove(const DOM_SID *sid)
Enumerate the group mapping.
****************************************************************************/
-static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap,
+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;
- fstring group_type;
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"));
@@ -453,19 +452,30 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rm
continue;
}
- string_to_sid(&map.sid, string_sid);
+ string_to_sid(&grpsid, string_sid);
+ sid_copy( &map.sid, &grpsid );
- decode_sid_name_use(group_type, map.sid_name_use);
- DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type));
+ 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;
+ }
- mapt= SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
- if (!mapt) {
+ 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"));
- SAFE_FREE(*pp_rmap);
return False;
}
- else
- (*pp_rmap) = mapt;
+
+ mapt = (*pp_rmap);
mapt[entries].gid = map.gid;
sid_copy( &mapt[entries].sid, &map.sid);
@@ -804,8 +814,24 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
ret = pdb_getgrsid(map, sid);
unbecome_root();
- if ( !ret )
+ /* special case check for rid 513 */
+
+ if ( !ret ) {
+ uint32 rid;
+
+ sid_peek_rid( &sid, &rid );
+
+ if ( rid == DOMAIN_GROUP_RID_USERS ) {
+ fstrcpy( map->nt_name, "None" );
+ fstrcpy( map->comment, "Ordinary Users" );
+ sid_copy( &map->sid, &sid );
+ map->sid_name_use = SID_NAME_DOM_GRP;
+
+ return True;
+ }
+
return False;
+ }
DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
@@ -833,132 +859,11 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
return True;
}
-
-/* get a local (alias) group from it's SID */
-
-BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
-{
- BOOL ret;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- /* The group is in the mapping table */
- become_root();
- ret = pdb_getgrsid(map, *sid);
- unbecome_root();
-
- if ( !ret )
- return False;
-
- if ( ( (map->sid_name_use != SID_NAME_ALIAS) &&
- (map->sid_name_use != SID_NAME_WKN_GRP) )
- || (map->gid == -1)
- || (getgrgid(map->gid) == NULL) )
- {
- return False;
- }
-
-#if 1 /* JERRY */
- /* local groups only exist in the group mapping DB so this
- is not necessary */
-
- else {
- /* the group isn't in the mapping table.
- * make one based on the unix information */
- uint32 alias_rid;
- struct group *grp;
-
- sid_peek_rid(sid, &alias_rid);
- map->gid=pdb_group_rid_to_gid(alias_rid);
-
- grp = getgrgid(map->gid);
- if ( !grp ) {
- DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid));
- return False;
- }
-
- map->sid_name_use=SID_NAME_ALIAS;
-
- fstrcpy(map->nt_name, grp->gr_name);
- fstrcpy(map->comment, "Local Unix Group");
-
- sid_copy(&map->sid, sid);
- }
-#endif
-
- return True;
-}
-
-/* get a builtin group from it's SID */
-
-BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
-{
- BOOL ret;
-
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- become_root();
- ret = pdb_getgrsid(map, *sid);
- unbecome_root();
-
- if ( !ret )
- return False;
-
- if (map->sid_name_use!=SID_NAME_WKN_GRP) {
- return False;
- }
-
- if (map->gid==-1) {
- return False;
- }
-
- if ( getgrgid(map->gid) == NULL) {
- return False;
- }
-
- return True;
-}
-
-
-
-/****************************************************************************
-Returns a GROUP_MAP struct based on the gid.
-****************************************************************************/
-BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
-{
- BOOL ret;
-
- if(!init_group_mapping()) {
- DEBUG(0,("failed to initialize group mapping\n"));
- return(False);
- }
-
- if ( getgrgid(gid) == NULL)
- return False;
-
- become_root();
- ret = pdb_getgrgid(map, gid);
- unbecome_root();
-
- if ( !ret ) {
- return False;
- }
-
- return True;
-}
-
/****************************************************************************
Create a UNIX group on demand.
****************************************************************************/
-int smb_create_group(char *unix_group, gid_t *new_gid)
+int smb_create_group(const char *unix_group, gid_t *new_gid)
{
pstring add_script;
int ret = -1;
@@ -971,7 +876,7 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
if ( *lp_addgroup_script() ) {
pstrcpy(add_script, lp_addgroup_script());
pstring_sub(add_script, "%g", unix_group);
- ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
+ ret = smbrun(add_script, &fd);
DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
if (ret != 0)
return ret;
@@ -1003,7 +908,7 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
Delete a UNIX group on demand.
****************************************************************************/
-int smb_delete_group(char *unix_group)
+int smb_delete_group(const char *unix_group)
{
pstring del_script;
int ret;
@@ -1049,7 +954,7 @@ int smb_set_primary_group(const char *unix_group, const char* unix_user)
Add a user to a UNIX group.
****************************************************************************/
-int smb_add_user_group(char *unix_group, char *unix_user)
+int smb_add_user_group(const char *unix_group, const char *unix_user)
{
pstring add_script;
int ret;
@@ -1135,11 +1040,11 @@ NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
}
NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
- enum SID_NAME_USE sid_name_use,
+ const DOM_SID *sid, enum SID_NAME_USE sid_name_use,
GROUP_MAP **pp_rmap, size_t *p_num_entries,
BOOL unix_only)
{
- return enum_group_mapping(sid_name_use, pp_rmap, p_num_entries, unix_only) ?
+ return enum_group_mapping(sid, sid_name_use, pp_rmap, p_num_entries, unix_only) ?
NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
@@ -1166,14 +1071,38 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
enum SID_NAME_USE type;
uint32 new_rid;
gid_t gid;
-
+ BOOL exists;
GROUP_MAP map;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+
+ DEBUG(10, ("Trying to create alias %s\n", name));
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- if (lookup_name(get_global_sam_name(), name, &sid, &type))
+ exists = lookup_name(mem_ctx, name, LOOKUP_NAME_ISOLATED,
+ NULL, NULL, &sid, &type);
+ TALLOC_FREE(mem_ctx);
+
+ if (exists) {
return NT_STATUS_ALIAS_EXISTS;
+ }
- if (!winbind_allocate_rid_and_gid(&new_rid, &gid))
+ if (!winbind_allocate_gid(&gid)) {
+ DEBUG(3, ("Could not get a gid out of winbind\n"));
return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!pdb_new_rid(&new_rid)) {
+ DEBUG(0, ("Could not allocate a RID -- wasted a gid :-(\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ DEBUG(10, ("Creating alias %s with gid %d and rid %d\n",
+ name, gid, new_rid));
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, new_rid);
@@ -1184,10 +1113,12 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
fstrcpy(map.nt_name, name);
fstrcpy(map.comment, "");
- if (!pdb_add_group_mapping_entry(&map)) {
- DEBUG(0, ("Could not add group mapping entry for alias %s\n",
- name));
- return NT_STATUS_ACCESS_DENIED;
+ status = pdb_add_group_mapping_entry(&map);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Could not add group mapping entry for alias %s "
+ "(%s)\n", name, nt_errstr(status)));
+ return status;
}
*rid = new_rid;
@@ -1198,8 +1129,7 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
const DOM_SID *sid)
{
- return pdb_delete_group_mapping_entry(*sid) ?
- NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+ return pdb_delete_group_mapping_entry(*sid);
}
NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
@@ -1211,6 +1141,14 @@ NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
if (!pdb_getgrsid(&map, *sid))
return NT_STATUS_NO_SUCH_ALIAS;
+ if ((map.sid_name_use != SID_NAME_ALIAS) &&
+ (map.sid_name_use != SID_NAME_WKN_GRP)) {
+ DEBUG(2, ("%s is a %s, expected an alias\n",
+ sid_string_static(sid),
+ sid_type_lookup(map.sid_name_use)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
fstrcpy(info->acct_name, map.nt_name);
fstrcpy(info->acct_desc, map.comment);
sid_peek_rid(&map.sid, &info->rid);
@@ -1226,12 +1164,10 @@ NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
if (!pdb_getgrsid(&map, *sid))
return NT_STATUS_NO_SUCH_ALIAS;
+ fstrcpy(map.nt_name, info->acct_name);
fstrcpy(map.comment, info->acct_desc);
- if (!pdb_update_group_mapping_entry(&map))
- return NT_STATUS_ACCESS_DENIED;
-
- return NT_STATUS_OK;
+ return pdb_update_group_mapping_entry(&map);
}
NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
@@ -1371,7 +1307,65 @@ BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info)
fstrcpy(map.nt_name, info->acct_name);
fstrcpy(map.comment, info->acct_desc);
- return pdb_update_group_mapping_entry(&map);
+ return NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map));
+}
+
+/********************************************************************
+ Really just intended to be called by smbd
+********************************************************************/
+
+NTSTATUS pdb_create_builtin_alias(uint32 rid)
+{
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ gid_t gid;
+ GROUP_MAP map;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ const char *name = NULL;
+ fstring groupname;
+
+ DEBUG(10, ("Trying to create builtin alias %d\n", rid));
+
+ if ( !sid_compose( &sid, &global_sid_Builtin, rid ) ) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ if ( (mem_ctx = talloc_new(NULL)) == NULL ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( !lookup_sid(mem_ctx, &sid, NULL, &name, &type) ) {
+ TALLOC_FREE( mem_ctx );
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ /* validate RID so copy the name and move on */
+
+ fstrcpy( groupname, name );
+ TALLOC_FREE( mem_ctx );
+
+ if (!winbind_allocate_gid(&gid)) {
+ DEBUG(3, ("pdb_create_builtin_alias: Could not get a gid out of winbind\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ DEBUG(10,("Creating alias %s with gid %d\n", name, gid));
+
+ map.gid = gid;
+ sid_copy(&map.sid, &sid);
+ map.sid_name_use = SID_NAME_ALIAS;
+ fstrcpy(map.nt_name, name);
+ fstrcpy(map.comment, "");
+
+ status = pdb_add_group_mapping_entry(&map);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("pdb_create_builtin_alias: Could not add group mapping entry for alias %d "
+ "(%s)\n", rid, nt_errstr(status)));
+ }
+
+ return status;
}
diff --git a/source/include/ads.h b/source/include/ads.h
index 82a413a72b6..2c7999e24fd 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -30,6 +30,7 @@ typedef struct {
unsigned flags;
int time_offset;
time_t expire;
+ time_t renewable;
} auth;
/* info derived from the servers config */
@@ -92,6 +93,7 @@ typedef void **ADS_MODLIST;
#define ADS_NO_REFERRALS_OID "1.2.840.113556.1.4.1339"
#define ADS_SERVER_SORT_OID "1.2.840.113556.1.4.473"
#define ADS_PERMIT_MODIFY_OID "1.2.840.113556.1.4.1413"
+#define ADS_ASQ_OID "1.2.840.113556.1.4.1504"
/* ldap attribute oids (Services for Unix) */
#define ADS_ATTR_SFU_UIDNUMBER_OID "1.2.840.113556.1.6.18.1.310"
@@ -133,9 +135,9 @@ typedef void **ADS_MODLIST;
#define UF_NOT_DELEGATED 0x00100000
#define UF_USE_DES_KEY_ONLY 0x00200000
#define UF_DONT_REQUIRE_PREAUTH 0x00400000
-#define UF_UNUSED_5 0x00800000
+#define UF_PASSWORD_EXPIRED 0x00800000
-#define UF_UNUSED_6 0x01000000
+#define UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 0x01000000
#define UF_NO_AUTH_DATA_REQUIRED 0x02000000
#define UF_UNUSED_8 0x04000000
#define UF_UNUSED_9 0x08000000
diff --git a/source/include/auth.h b/source/include/auth.h
index 03206c03c6a..465892905a6 100644
--- a/source/include/auth.h
+++ b/source/include/auth.h
@@ -20,12 +20,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* AUTH_STR - string */
-typedef struct normal_string {
- int len;
- char *str;
-} AUTH_STR;
-
typedef struct auth_usersupplied_info {
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
@@ -35,25 +29,24 @@ typedef struct auth_usersupplied_info {
BOOL encrypted;
- AUTH_STR client_domain; /* domain name string */
- AUTH_STR domain; /* domain name after mapping */
- AUTH_STR internal_username; /* username after mapping */
- AUTH_STR smb_name; /* username before mapping */
- AUTH_STR wksta_name; /* workstation name (netbios calling name) unicode string */
+ char *client_domain; /* domain name string */
+ char *domain; /* domain name after mapping */
+ char *internal_username; /* username after mapping */
+ char *smb_name; /* username before mapping */
+ char *wksta_name; /* workstation name (netbios calling
+ * name) unicode string */
uint32 logon_parameters;
} auth_usersupplied_info;
-#define SAM_FILL_NAME 0x01
-#define SAM_FILL_INFO3 0x02
-#define SAM_FILL_SAM 0x04
-#define SAM_FILL_UNIX 0x08
-#define SAM_FILL_ALL (SAM_FILL_NAME | SAM_FILL_INFO3 | SAM_FILL_SAM | SAM_FILL_UNIX)
-
typedef struct auth_serversupplied_info {
BOOL guest;
+ DOM_SID *sids; /* These SIDs are preliminary between
+ check_ntlm_password and the token creation. */
+ size_t num_sids;
+
uid_t uid;
gid_t gid;
@@ -70,9 +63,7 @@ typedef struct auth_serversupplied_info {
char *login_server; /* which server authorized the login? */
- uint32 sam_fill_level; /* How far is this structure filled? */
-
- SAM_ACCOUNT *sam_account;
+ struct samu *sam_account;
void *pam_handle;
diff --git a/source/include/debug.h b/source/include/debug.h
index b6fb50a9acb..ae9fbeba92f 100644
--- a/source/include/debug.h
+++ b/source/include/debug.h
@@ -102,6 +102,7 @@ extern int DEBUGLEVEL;
#define DBGC_ACLS 15
#define DBGC_LOCKING 16
#define DBGC_MSDFS 17
+#define DBGC_DMAPI 18
/* So you can define DBGC_CLASS before including debug.h */
#ifndef DBGC_CLASS
@@ -207,4 +208,8 @@ extern BOOL *DEBUGLEVEL_CLASS_ISSET;
DEBUGLEVEL_CLASS[ DBGC_ALL ] >= (level)) ) \
&& (dbgtext body) )
+/* Print a separator to the debug log. */
+#define DEBUGSEP(level)\
+ DEBUG((level),("===============================================================\n"))
+
#endif
diff --git a/source/ubiqx/debugparse.h b/source/include/debugparse.h
index 458eee74558..fb7f00f7792 100644
--- a/source/ubiqx/debugparse.h
+++ b/source/include/debugparse.h
@@ -31,7 +31,7 @@
* ========================================================================== **
*/
-#include "sys_include.h"
+#include "includes.h"
/* This module compiles quite nicely outside of the Samba environment.
* You'll need the following headers:
diff --git a/source/include/doserr.h b/source/include/doserr.h
index 62c1e4fa22d..8f8ea066964 100644
--- a/source/include/doserr.h
+++ b/source/include/doserr.h
@@ -200,6 +200,7 @@
#define WERR_SERVICE_NEVER_STARTED W_ERROR(1077)
#define WERR_MACHINE_LOCKED W_ERROR(1271)
#define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338)
+#define WERR_TIME_SKEW W_ERROR(1398)
#define WERR_EVENTLOG_FILE_CORRUPT W_ERROR(1500)
#define WERR_SERVER_UNAVAILABLE W_ERROR(1722)
#define WERR_INVALID_FORM_NAME W_ERROR(1902)
diff --git a/source/include/event.h b/source/include/event.h
new file mode 100644
index 00000000000..fdb990678db
--- /dev/null
+++ b/source/include/event.h
@@ -0,0 +1,31 @@
+/*
+ Unix SMB/CIFS implementation.
+ event handling
+ Copyright (C) Andrew Tridgell 1992-1998
+ 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.
+*/
+
+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;
+};
+
diff --git a/source/include/gpo.h b/source/include/gpo.h
new file mode 100644
index 00000000000..65c96c31e6b
--- /dev/null
+++ b/source/include/gpo.h
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+
+enum GPO_LINK_TYPE {
+ GP_LINK_UNKOWN,
+ GP_LINK_MACHINE,
+ GP_LINK_SITE,
+ GP_LINK_DOMAIN,
+ GP_LINK_OU
+};
+
+/* GPO_OPTIONS */
+#define GPO_FLAG_DISABLE 0x00000001
+#define GPO_FLAG_FORCE 0x00000002
+
+/* GPO_LIST_FLAGS */
+#define GPO_LIST_FLAG_MACHINE 0x00000001
+#define GPO_LIST_FLAG_SITEONLY 0x00000002
+
+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;
+ const char *name;
+ const char *link;
+ uint32 link_type; /* GPO_LINK_TYPE */
+ const char *user_extensions;
+ const char *machine_extensions;
+ struct GROUP_POLICY_OBJECT *next, *prev;
+};
+
+/* the following is seen on the DS (see adssearch.pl for details) */
+
+/* the type field in a 'gPLink', the same as GPO_FLAG ? */
+#define GPO_LINK_OPT_NONE 0x00000000
+#define GPO_LINK_OPT_DISABLED 0x00000001
+#define GPO_LINK_OPT_ENFORCED 0x00000002
+
+/* GPO_LINK_OPT_ENFORCED takes precedence over GPOPTIONS_BLOCK_INHERITANCE */
+
+/* 'gPOptions', maybe a bitmask as well */
+enum GPO_INHERIT {
+ GPOPTIONS_INHERIT,
+ GPOPTIONS_BLOCK_INHERITANCE
+};
+
+/* 'flags' in a 'groupPolicyContainer' object */
+#define GPFLAGS_ALL_ENABLED 0x00000000
+#define GPFLAGS_USER_SETTINGS_DISABLED 0x00000001
+#define GPFLAGS_MACHINE_SETTINGS_DISABLED 0x00000002
+#define GPFLAGS_ALL_DISABLED (GPFLAGS_USER_SETTINGS_DISABLED | \
+ GPFLAGS_MACHINE_SETTINGS_DISABLED)
+
+struct GP_LINK {
+ const char *gp_link; /* raw link name */
+ uint32 gp_opts; /* inheritance options GPO_INHERIT */
+ uint32 num_links; /* number of links */
+ char **link_names; /* array of parsed link names */
+ uint32 *link_opts; /* array of parsed link opts GPO_LINK_OPT_* */
+};
+
+struct GP_EXT {
+ const char *gp_extension; /* raw extension name */
+ uint32 num_exts;
+ char **extensions;
+ char **extensions_guid;
+ char **snapins;
+ char **snapins_guid;
+};
diff --git a/source/include/hmacmd5.h b/source/include/hmacmd5.h
index 6b53a6fd074..89ea3fed803 100644
--- a/source/include/hmacmd5.h
+++ b/source/include/hmacmd5.h
@@ -21,12 +21,10 @@
#ifndef _HMAC_MD5_H
-typedef struct
-{
- struct MD5Context ctx;
- uchar k_ipad[65];
- uchar k_opad[65];
-
+typedef struct {
+ struct MD5Context ctx;
+ unsigned char k_ipad[65];
+ unsigned char k_opad[65];
} HMACMD5Context;
#endif /* _HMAC_MD5_H */
diff --git a/source/include/idmap.h b/source/include/idmap.h
index c81b94a718a..474982f2926 100644
--- a/source/include/idmap.h
+++ b/source/include/idmap.h
@@ -24,6 +24,9 @@
Boston, MA 02111-1307, USA.
*/
+/* idmap version determines auto-conversion */
+#define IDMAP_VERSION 2
+
#define SMB_IDMAP_INTERFACE_VERSION 2
@@ -43,7 +46,6 @@ struct idmap_methods {
/* Called when backend is first loaded */
NTSTATUS (*init)( char *params );
- NTSTATUS (*allocate_rid)(uint32 *rid, int rid_type);
NTSTATUS (*allocate_id)(unid_t *id, int id_type);
NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type);
NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid);
diff --git a/source/include/includes.h b/source/include/includes.h
index 6849970d7cd..a5f261282ce 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -21,14 +21,18 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* work around broken krb5.h on sles9 */
+#ifdef SIZEOF_LONG
+#undef SIZEOF_LONG
+#endif
+
#ifndef NO_CONFIG_H /* for some tests */
#include "config.h"
#endif
#ifndef __cplusplus
#define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
-/* allow to build with newer heimdal releases */
-/* #define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES */
+#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
#define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
#define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
#define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
@@ -359,28 +363,6 @@
#include <poll.h>
#endif
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
-#ifdef HAVE_SYS_CAPABILITY_H
-
-#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
-#define _I386_STATFS_H
-#define _PPC_STATFS_H
-#define BROKEN_REDHAT_7_STATFS_WORKAROUND
-#endif
-
-#include <sys/capability.h>
-
-#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
-#undef _I386_STATFS_H
-#undef _PPC_STATFS_H
-#undef BROKEN_REDHAT_7_STATFS_WORKAROUND
-#endif
-
-#endif
-
#if defined(HAVE_RPC_RPC_H)
/*
* Check for AUTH_ERROR define conflict with rpc/rpc.h in prot.h.
@@ -471,6 +453,16 @@
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS 0
#endif
+/* Solaris 8 and maybe other LDAP implementations spell this "..._INPROGRESS": */
+#if defined(LDAP_SASL_BIND_INPROGRESS) && !defined(LDAP_SASL_BIND_IN_PROGRESS)
+#define LDAP_SASL_BIND_IN_PROGRESS LDAP_SASL_BIND_INPROGRESS
+#endif
+/* Solaris 8 defines SSL_LDAP_PORT, not LDAPS_PORT and it only does so if
+ LDAP_SSL is defined - but SSL is not working. We just want the
+ port number! Let's just define LDAPS_PORT correct. */
+#if !defined(LDAPS_PORT)
+#define LDAPS_PORT 636
+#endif
#else
#undef HAVE_LDAP
#endif
@@ -498,6 +490,10 @@
#include <sys/xattr.h>
#endif
+#ifdef HAVE_SYS_EA_H
+#include <sys/ea.h>
+#endif
+
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
@@ -648,6 +644,19 @@ typedef int socklen_t;
#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
+
+
+/*
* Types for devices, inodes and offsets.
*/
@@ -882,8 +891,6 @@ extern int errno;
/* Lists, trees, caching, database... */
#include "xfile.h"
#include "intl.h"
-#include "ubi_sLinkList.h"
-#include "ubi_dLinkList.h"
#include "dlinklist.h"
#include "tdb/tdb.h"
#include "tdb/spinlock.h"
@@ -906,10 +913,6 @@ extern int errno;
#include "util_getent.h"
-#ifndef UBI_BINTREE_H
-#include "ubi_Cache.h"
-#endif /* UBI_BINTREE_H */
-
#include "debugparse.h"
#include "version.h"
@@ -997,6 +1000,8 @@ extern int errno;
#include "rpc_client.h"
+#include "event.h"
+
/*
* Type for wide character dirent structure.
* Only d_name is defined by POSIX.
@@ -1026,6 +1031,11 @@ struct functable {
int (*fn)(int argc, const char **argv);
};
+struct functable2 {
+ const char *funcname;
+ int (*fn)(int argc, const char **argv);
+ const char *helptext;
+};
/* Defines for wisXXX functions. */
#define UNI_UPPER 0x1
@@ -1516,8 +1526,12 @@ 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);
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname);
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);
+NTSTATUS krb5_to_nt_status(krb5_error_code kerberos_error);
+krb5_error_code nt_status_to_krb5(NTSTATUS nt_status);
#endif /* HAVE_KRB5 */
@@ -1553,4 +1567,18 @@ LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to);
#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
#define CONST_ADD(type, ptr) ((type) ((const void *) (ptr)))
+#ifndef NORETURN_ATTRIBUTE
+#if (__GNUC__ >= 3)
+#define NORETURN_ATTRIBUTE __attribute__ ((noreturn))
+#else
+#define NORETURN_ATTRIBUTE
+#endif
+#endif
+
+void smb_panic( const char *why ) NORETURN_ATTRIBUTE ;
+void dump_core(void) NORETURN_ATTRIBUTE ;
+void exit_server(const char *const reason) NORETURN_ATTRIBUTE ;
+void exit_server_cleanly(const char *const reason) NORETURN_ATTRIBUTE ;
+void exit_server_fault(void) NORETURN_ATTRIBUTE ;
+
#endif /* _INCLUDES_H */
diff --git a/source/include/libmsrpc.h b/source/include/libmsrpc.h
index 9fbd57a8d32..36bae441775 100644
--- a/source/include/libmsrpc.h
+++ b/source/include/libmsrpc.h
@@ -1761,7 +1761,7 @@ struct SamEnumUsers {
POLICY_HND *dom_hnd;
/**Enumerate users with specific ACB. If 0, all users will be enumerated*/
- uint16 acb_mask;
+ uint32 acb_mask;
} in;
struct {
diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h
index 04264303288..5aca12554f3 100644
--- a/source/include/libsmb_internal.h
+++ b/source/include/libsmb_internal.h
@@ -79,6 +79,18 @@ struct smbc_internal_data {
* Log to standard error instead of the more typical standard output
*/
BOOL _debug_stderr;
+
+ /*
+ * Authentication function which includes the context. This will be
+ * used if set; otherwise context->callbacks.auth_fn() will be used.
+ */
+ smbc_get_auth_data_with_context_fn _auth_fn_with_context;
+
+ /*
+ * An opaque (to this library) user data handle which can be set
+ * and retrieved with smbc_option_set() and smbc_option_get().
+ */
+ void * _user_data;
};
diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h
index 6d3a0cda09d..ba92259f701 100644
--- a/source/include/libsmbclient.h
+++ b/source/include/libsmbclient.h
@@ -204,7 +204,7 @@ typedef struct _SMBCCTX SMBCCTX;
/**@ingroup callback
- * Authentication callback function type.
+ * Authentication callback function type (traditional method)
*
* Type for the the authentication function called by the library to
* obtain authentication credentals
@@ -237,6 +237,43 @@ typedef void (*smbc_get_auth_data_fn)(const char *srv,
char *wg, int wglen,
char *un, int unlen,
char *pw, int pwlen);
+/**@ingroup callback
+ * Authentication callback function type (method that includes context)
+ *
+ * Type for the the authentication function called by the library to
+ * obtain authentication credentals
+ *
+ * @param c Pointer to the smb context
+ *
+ * @param srv Server being authenticated to
+ *
+ * @param shr Share being authenticated to
+ *
+ * @param wg Pointer to buffer containing a "hint" for the
+ * workgroup to be authenticated. Should be filled in
+ * with the correct workgroup if the hint is wrong.
+ *
+ * @param wglen The size of the workgroup buffer in bytes
+ *
+ * @param un Pointer to buffer containing a "hint" for the
+ * user name to be use for authentication. Should be
+ * filled in with the correct workgroup if the hint is
+ * wrong.
+ *
+ * @param unlen The size of the username buffer in bytes
+ *
+ * @param pw Pointer to buffer containing to which password
+ * copied
+ *
+ * @param pwlen The size of the password buffer in bytes
+ *
+ */
+typedef void (*smbc_get_auth_data_with_context_fn)(SMBCCTX *c,
+ const char *srv,
+ const char *shr,
+ char *wg, int wglen,
+ char *un, int unlen,
+ char *pw, int pwlen);
/**@ingroup callback
@@ -422,14 +459,15 @@ struct _SMBCCTX {
int (*unlink_print_job)(SMBCCTX *c, const char *fname, int id);
- /** Callbacks
- * These callbacks _always_ have to be initialized because they will not be checked
- * at dereference for increased speed.
- */
+ /*
+ ** Callbacks
+ * These callbacks _always_ have to be initialized because they will
+ * not be checked at dereference for increased speed.
+ */
struct _smbc_callbacks {
/** authentication function callback: called upon auth requests
*/
- smbc_get_auth_data_fn auth_fn;
+ smbc_get_auth_data_fn auth_fn;
/** check if a server is still good
*/
@@ -579,22 +617,60 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx);
/**@ingroup misc
+ * Each time the context structure is changed, we have binary backward
+ * compatibility issues. Instead of modifying the public portions of the
+ * context structure to add new options, instead, we put them in the internal
+ * portion of the context structure and provide a set function for these new
+ * options.
+ *
+ * @param context A pointer to a SMBCCTX obtained from smbc_new_context()
+ *
+ * @param option_name
+ * The name of the option for which the value is to be set
+ *
+ * @param option_value
+ * The new value of the option being set
+ *
+ */
+void
+smbc_option_set(SMBCCTX *context,
+ char *option_name,
+ void *option_value);
+/*
+ * Retrieve the current value of an option
+ *
+ * @param context A pointer to a SMBCCTX obtained from smbc_new_context()
+ *
+ * @param option_name
+ * The name of the option for which the value is to be
+ * retrieved
+ *
+ * @return The value of the specified option.
+ */
+void *
+smbc_option_get(SMBCCTX *context,
+ char *option_name);
+
+/**@ingroup misc
* Initialize a SBMCCTX (a context).
*
* Must be called before using any SMBCCTX API function
*
* @param context A pointer to a SMBCCTX obtained from smbc_new_context()
*
- * @return A pointer to the given SMBCCTX on success, NULL on error with errno set:
+ * @return A pointer to the given SMBCCTX on success,
+ * NULL on error with errno set:
* - EBADF NULL context given
* - ENOMEM Out of memory
* - ENOENT The smb.conf file would not load
*
* @see smbc_new_context()
*
- * @note my_context = smbc_init_context(smbc_new_context()) is perfectly safe,
- * but it might leak memory on smbc_context_init() failure. Avoid this.
- * You'll have to call smbc_free_context() yourself on failure.
+ * @note my_context = smbc_init_context(smbc_new_context())
+ * is perfectly safe, but it might leak memory on
+ * smbc_context_init() failure. Avoid this.
+ * You'll have to call smbc_free_context() yourself
+ * on failure.
*/
SMBCCTX * smbc_init_context(SMBCCTX * context);
diff --git a/source/include/local.h b/source/include/local.h
index c9b54ab1a21..fb931976362 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -236,6 +236,15 @@
#define MAX_LDAP_REPLICATION_SLEEP_TIME 5000 /* In milliseconds. */
/* tdb hash size for the open database. */
-#define SMB_OPEN_DATABASE_TDB_HASH_SIZE 1049
+#define SMB_OPEN_DATABASE_TDB_HASH_SIZE 10007
+
+/* Characters we disallow in sharenames. */
+#define INVALID_SHARENAME_CHARS "%<>*?|/\\+=;:\","
+
+/* Seconds between connection attempts to a remote server. */
+#define FAILED_CONNECTION_CACHE_TIMEOUT 30
+
+/* Default hash size for the winbindd cache. */
+#define WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE 5000
#endif
diff --git a/source/include/messages.h b/source/include/messages.h
index 4b1732d42d1..6a739c0bcc7 100644
--- a/source/include/messages.h
+++ b/source/include/messages.h
@@ -69,10 +69,13 @@
#define MSG_SMB_OPEN_RETRY 3009
#define MSG_SMB_KERNEL_BREAK 3010
#define MSG_SMB_FILE_RENAME 3011
+#define MSG_SMB_INJECT_FAULT 3012
/* winbind messages */
#define MSG_WINBIND_FINISHED 4001
#define MSG_WINBIND_FORGET_STATE 4002
+#define MSG_WINBIND_ONLINE 4003
+#define MSG_WINBIND_OFFLINE 4004
/* Flags to classify messages - used in message_send_all() */
/* Sender will filter by flag. */
diff --git a/source/include/nameserv.h b/source/include/nameserv.h
index ec3d56c06b7..9f6bf76a093 100644
--- a/source/include/nameserv.h
+++ b/source/include/nameserv.h
@@ -217,7 +217,7 @@ struct nmb_data {
/* This structure represents an entry in a local netbios name list. */
struct name_record {
- ubi_trNode node[1];
+ struct name_record *prev, *next;
struct subnet_record *subnet;
struct nmb_name name; /* The netbios name. */
struct nmb_data data; /* The netbios data. */
@@ -225,7 +225,7 @@ struct name_record {
/* Browser cache for synchronising browse lists. */
struct browse_cache_record {
- ubi_dlNode node[1];
+ struct browse_cache_record *prev, *next;
unstring lmb_name;
unstring work_group;
struct in_addr ip;
@@ -425,7 +425,7 @@ struct subnet_record {
enum subnet_type type; /* To catagorize the subnet. */
struct work_record *workgrouplist; /* List of workgroups. */
- ubi_trRoot namelist[1]; /* List of netbios names. */
+ struct name_record *namelist; /* List of netbios names. */
struct response_record *responselist; /* List of responses expected. */
BOOL namelist_changed;
diff --git a/source/include/nt_printing.h b/source/include/nt_printing.h
index f0d50878ce4..5bd64ae7be3 100644
--- a/source/include/nt_printing.h
+++ b/source/include/nt_printing.h
@@ -348,6 +348,28 @@ typedef struct
#define SAMBA_PRINTER_PORT_NAME "Samba Printer Port"
#endif
+
+/*
+ * Structures for the XcvDataPort() calls
+ */
+
+#define PORT_PROTOCOL_DIRECT 1
+#define PORT_PROTOCOL_LPR 2
+
+typedef struct {
+ fstring name;
+ uint32 version;
+ uint32 protocol;
+ fstring hostaddr;
+ fstring snmpcommunity;
+ fstring queue;
+ uint32 dblspool;
+ fstring ipaddr;
+ uint32 port;
+ BOOL enable_snmp;
+ uint32 snmp_index;
+} NT_PORT_DATA_1;
+
/* DOS header format */
#define DOS_HEADER_SIZE 64
#define DOS_HEADER_MAGIC_OFFSET 0
@@ -421,8 +443,10 @@ typedef struct {
SPOOLSS_NOTIFY_MSG_GROUP *msg_groups;
} SPOOLSS_NOTIFY_MSG_CTR;
-#define PRINTER_HANDLE_IS_PRINTER 0
-#define PRINTER_HANDLE_IS_PRINTSERVER 1
+#define SPLHND_PRINTER 1
+#define SPLHND_SERVER 2
+#define SPLHND_PORTMON_TCP 3
+#define SPLHND_PORTMON_LOCAL 4
/* structure to store the printer handles */
/* and a reference to what it's pointing to */
diff --git a/source/include/nt_status.h b/source/include/nt_status.h
index ab768258df1..14c83eba4b3 100644
--- a/source/include/nt_status.h
+++ b/source/include/nt_status.h
@@ -61,4 +61,10 @@ typedef uint32 WERROR;
#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))
+#define NT_STATUS_HAVE_NO_MEMORY(x) do { \
+ if (!(x)) {\
+ return NT_STATUS_NO_MEMORY;\
+ }\
+} while (0)
+
#endif
diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h
index a30b7243727..c27ec3675b4 100644
--- a/source/include/ntdomain.h
+++ b/source/include/ntdomain.h
@@ -140,8 +140,8 @@ struct dcinfo {
DOM_CHAL clnt_chal; /* Client credential */
DOM_CHAL srv_chal; /* Server credential */
- uchar sess_key[8]; /* Session key */
- uchar mach_pw[16]; /* md4(machine password) */
+ unsigned char sess_key[16]; /* Session key - 8 bytes followed by 8 zero bytes */
+ unsigned char mach_pw[16]; /* md4(machine password) */
fstring mach_acct; /* Machine name we've authenticated. */
@@ -187,7 +187,7 @@ struct kerberos_auth_struct {
/* auth state for schannel. */
struct schannel_auth_struct {
- uchar sess_key[16];
+ unsigned char sess_key[16];
uint32 seq_num;
};
diff --git a/source/include/ntlmssp.h b/source/include/ntlmssp.h
index 30a37e06c3e..a2dac7dc0ba 100644
--- a/source/include/ntlmssp.h
+++ b/source/include/ntlmssp.h
@@ -60,6 +60,7 @@ enum NTLM_MESSAGE_TYPE
#define NTLMSSP_CHAL_NON_NT_SESSION_KEY 0x00040000
#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
#define NTLMSSP_CHAL_TARGET_INFO 0x00800000
+#define NTLMSSP_UNKNOWN_02000000 0x02000000
#define NTLMSSP_NEGOTIATE_128 0x20000000 /* 128-bit encryption */
#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
#define NTLMSSP_NEGOTIATE_56 0x80000000
diff --git a/source/include/passdb.h b/source/include/passdb.h
index 0589b9a7cd4..432976412db 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -62,7 +62,7 @@
#define ACCT_OWF_PWD 0x20000000
/*
- * bit flags representing initialized fields in SAM_ACCOUNT
+ * bit flags representing initialized fields in struct samu
*/
enum pdb_elements {
PDB_UNINIT,
@@ -130,98 +130,70 @@ enum pdb_value_state {
/* cache for bad password lockout data, to be used on replicated SAMs */
typedef struct logon_cache_struct {
time_t entry_timestamp;
- uint16 acct_ctrl;
+ uint32 acct_ctrl;
uint16 bad_password_count;
time_t bad_password_time;
} LOGIN_CACHE;
-typedef struct sam_passwd {
- TALLOC_CTX *mem_ctx;
-
- void (*free_fn)(struct sam_passwd **);
-
+struct samu {
struct pdb_methods *methods;
- struct user_data {
- /* initialization flags */
- struct bitmap *change_flags;
- struct bitmap *set_flags;
-
- time_t logon_time; /* logon time */
- time_t logoff_time; /* logoff time */
- time_t kickoff_time; /* kickoff time */
- time_t bad_password_time; /* last bad password entered */
- time_t pass_last_set_time; /* password last set time */
- time_t pass_can_change_time; /* password can change time */
- time_t pass_must_change_time; /* password must change time */
-
- const char * username; /* UNIX username string */
- const char * domain; /* Windows Domain name */
- const char * nt_username; /* Windows username string */
- const char * full_name; /* user's full name string */
- const char * unix_home_dir; /* UNIX home directory string */
- const char * home_dir; /* home directory string */
- const char * dir_drive; /* home directory drive string */
- const char * logon_script; /* logon script string */
- 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 * munged_dial; /* munged path name and dial-back tel number */
+ /* initialization flags */
+ struct bitmap *change_flags;
+ struct bitmap *set_flags;
+
+ time_t logon_time; /* logon time */
+ time_t logoff_time; /* logoff time */
+ time_t kickoff_time; /* kickoff time */
+ time_t bad_password_time; /* last bad password entered */
+ time_t pass_last_set_time; /* password last set time */
+ time_t pass_can_change_time; /* password can change time */
+ time_t pass_must_change_time; /* password must change time */
- DOM_SID user_sid; /* Primary User SID */
- DOM_SID group_sid; /* Primary Group SID */
+ const char *username; /* UNIX username string */
+ const char *domain; /* Windows Domain name */
+ const char *nt_username; /* Windows username string */
+ const char *full_name; /* user's full name string */
+ const char *home_dir; /* home directory string */
+ const char *dir_drive; /* home directory drive string */
+ const char *logon_script; /* logon script string */
+ 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 *munged_dial; /* munged path name and dial-back tel number */
- DATA_BLOB lm_pw; /* .data is Null if no password */
- DATA_BLOB nt_pw; /* .data is Null if no password */
- DATA_BLOB nt_pw_his; /* nt hashed password history .data is Null if not available */
- char* plaintext_pw; /* is Null if not available */
+ DOM_SID user_sid;
+ DOM_SID *group_sid;
- uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
- uint32 fields_present; /* 0x00ff ffff */
+ DATA_BLOB lm_pw; /* .data is Null if no password */
+ DATA_BLOB nt_pw; /* .data is Null if no password */
+ DATA_BLOB nt_pw_his; /* nt hashed password history .data is Null if not available */
+ char* plaintext_pw; /* is Null if not available */
- uint16 logon_divs; /* 168 - number of hours in a week */
- uint32 hours_len; /* normally 21 bytes */
- uint8 hours[MAX_HOURS_LEN];
+ uint32 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
+ uint32 fields_present; /* 0x00ff ffff */
- /* Was unknown_5. */
- uint16 bad_password_count;
- uint16 logon_count;
-
- uint32 unknown_6; /* 0x0000 04ec */
- /* a tag for who added the private methods */
- const struct pdb_methods *backend_private_methods;
- void *backend_private_data;
- void (*backend_private_data_free_fn)(void **);
- } private_u;
-
- /* Lets see if the remaining code can get the hint that you
- are meant to use the pdb_...() functions. */
-
-} SAM_ACCOUNT;
-
-typedef struct sam_group {
- TALLOC_CTX *mem_ctx;
+ uint16 logon_divs; /* 168 - number of hours in a week */
+ uint32 hours_len; /* normally 21 bytes */
+ uint8 hours[MAX_HOURS_LEN];
- void (*free_fn)(struct sam_group **);
-
- struct pdb_methods *methods;
-
- struct group_data {
- /* initialization flags */
- struct bitmap *change_flags;
- struct bitmap *set_flags;
+ /* Was unknown_5. */
+ uint16 bad_password_count;
+ uint16 logon_count;
- const char *name; /* Windows group name string */
+ uint32 unknown_6; /* 0x0000 04ec */
- DOM_SID sid; /* Group SID */
- enum SID_NAME_USE sid_name_use; /* Group type */
+ /* a tag for who added the private methods */
- uint32 mem_num; /* Number of member SIDs */
- DOM_SID *members; /* SID array */
- } private_g;
+ const struct pdb_methods *backend_private_methods;
+ void *backend_private_data;
+ void (*backend_private_data_free_fn)(void **);
+
+ /* maintain a copy of the user's struct passwd */
-} SAM_GROUP;
+ struct passwd *unix_pw;
+};
struct acct_info {
fstring acct_name; /* account name */
@@ -232,7 +204,7 @@ struct acct_info {
struct samr_displayentry {
uint32 idx;
uint32 rid;
- uint16 acct_flags;
+ uint32 acct_flags;
const char *account_name;
const char *fullname;
const char *description;
@@ -270,163 +242,38 @@ struct pdb_search {
* the pdb module. Remove the latter, this might happen more often. VL.
*/
-#define PASSDB_INTERFACE_VERSION 12
-
-typedef struct pdb_context
-{
- struct pdb_methods *pdb_methods;
- struct pdb_methods *pwent_methods;
-
- /* These functions are wrappers for the functions listed above.
- They may do extra things like re-reading a SAM_ACCOUNT on update */
-
- NTSTATUS (*pdb_setsampwent)(struct pdb_context *, BOOL update, uint16 acb_mask);
-
- void (*pdb_endsampwent)(struct pdb_context *);
-
- NTSTATUS (*pdb_getsampwent)(struct pdb_context *, SAM_ACCOUNT *user);
-
- NTSTATUS (*pdb_getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username);
-
- NTSTATUS (*pdb_getsampwsid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const DOM_SID *sid);
-
- NTSTATUS (*pdb_add_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass);
-
- NTSTATUS (*pdb_update_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass);
-
- NTSTATUS (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username);
-
- NTSTATUS (*pdb_rename_sam_account)(struct pdb_context *, SAM_ACCOUNT *oldname, const char *newname);
-
- NTSTATUS (*pdb_update_login_attempts)(struct pdb_context *context, SAM_ACCOUNT *sam_acct, BOOL success);
-
- NTSTATUS (*pdb_getgrsid)(struct pdb_context *context, GROUP_MAP *map, DOM_SID sid);
-
- NTSTATUS (*pdb_getgrgid)(struct pdb_context *context, GROUP_MAP *map, gid_t gid);
-
- NTSTATUS (*pdb_getgrnam)(struct pdb_context *context, GROUP_MAP *map, const char *name);
-
- NTSTATUS (*pdb_add_group_mapping_entry)(struct pdb_context *context,
- GROUP_MAP *map);
-
- NTSTATUS (*pdb_update_group_mapping_entry)(struct pdb_context *context,
- GROUP_MAP *map);
-
- NTSTATUS (*pdb_delete_group_mapping_entry)(struct pdb_context *context,
- DOM_SID sid);
-
- NTSTATUS (*pdb_enum_group_mapping)(struct pdb_context *context,
- enum SID_NAME_USE sid_name_use,
- GROUP_MAP **pp_rmap, size_t *p_num_entries,
- BOOL unix_only);
-
- NTSTATUS (*pdb_enum_group_members)(struct pdb_context *context,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *group,
- uint32 **pp_member_rids,
- size_t *p_num_members);
-
- NTSTATUS (*pdb_enum_group_memberships)(struct pdb_context *context,
- const char *username,
- gid_t primary_gid,
- DOM_SID **pp_sids, gid_t **pp_gids,
- size_t *p_num_groups);
-
- NTSTATUS (*pdb_find_alias)(struct pdb_context *context,
- const char *name, DOM_SID *sid);
-
- NTSTATUS (*pdb_create_alias)(struct pdb_context *context,
- const char *name, uint32 *rid);
-
- NTSTATUS (*pdb_delete_alias)(struct pdb_context *context,
- const DOM_SID *sid);
-
- NTSTATUS (*pdb_get_aliasinfo)(struct pdb_context *context,
- const DOM_SID *sid,
- struct acct_info *info);
-
- NTSTATUS (*pdb_set_aliasinfo)(struct pdb_context *context,
- const DOM_SID *sid,
- struct acct_info *info);
-
- NTSTATUS (*pdb_add_aliasmem)(struct pdb_context *context,
- const DOM_SID *alias,
- const DOM_SID *member);
-
- NTSTATUS (*pdb_del_aliasmem)(struct pdb_context *context,
- const DOM_SID *alias,
- const DOM_SID *member);
-
- NTSTATUS (*pdb_enum_aliasmem)(struct pdb_context *context,
- const DOM_SID *alias,
- DOM_SID **pp_members, size_t *p_num_members);
-
- NTSTATUS (*pdb_enum_alias_memberships)(struct pdb_context *context,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *domain_sid,
- const DOM_SID *members,
- size_t num_members,
- uint32 **pp_alias_rids,
- size_t *p_num_alias_rids);
-
- NTSTATUS (*pdb_lookup_rids)(struct pdb_context *context,
- const DOM_SID *domain_sid,
- size_t num_rids,
- uint32 *rids,
- const char **pp_names,
- uint32 *attrs);
-
- NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context,
- int policy_index, uint32 *value);
-
- NTSTATUS (*pdb_set_account_policy)(struct pdb_context *context,
- int policy_index, uint32 value);
-
- NTSTATUS (*pdb_get_seq_num)(struct pdb_context *context, time_t *seq_num);
-
- BOOL (*pdb_search_users)(struct pdb_context *context,
- struct pdb_search *search,
- uint16 acct_flags);
- BOOL (*pdb_search_groups)(struct pdb_context *context,
- struct pdb_search *search);
- BOOL (*pdb_search_aliases)(struct pdb_context *context,
- struct pdb_search *search,
- const DOM_SID *sid);
-
- void (*free_fn)(struct pdb_context **);
-
- TALLOC_CTX *mem_ctx;
-
-} PDB_CONTEXT;
+#define PASSDB_INTERFACE_VERSION 13
-typedef struct pdb_methods
+struct pdb_methods
{
const char *name; /* What name got this module */
- struct pdb_context *parent;
-
- /* Use macros from dlinklist.h on these two */
- struct pdb_methods *next;
- struct pdb_methods *prev;
- NTSTATUS (*setsampwent)(struct pdb_methods *, BOOL update, uint16 acb_mask);
+ NTSTATUS (*setsampwent)(struct pdb_methods *, BOOL update, uint32 acb_mask);
void (*endsampwent)(struct pdb_methods *);
- NTSTATUS (*getsampwent)(struct pdb_methods *, SAM_ACCOUNT *user);
+ NTSTATUS (*getsampwent)(struct pdb_methods *, struct samu *user);
- NTSTATUS (*getsampwnam)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, const char *username);
+ NTSTATUS (*getsampwnam)(struct pdb_methods *, struct samu *sam_acct, const char *username);
- NTSTATUS (*getsampwsid)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, const DOM_SID *sid);
+ NTSTATUS (*getsampwsid)(struct pdb_methods *, struct samu *sam_acct, const DOM_SID *sid);
+
+ NTSTATUS (*create_user)(struct pdb_methods *, TALLOC_CTX *tmp_ctx,
+ const char *name, uint32 acct_flags,
+ uint32 *rid);
+
+ NTSTATUS (*delete_user)(struct pdb_methods *, TALLOC_CTX *tmp_ctx,
+ struct samu *sam_acct);
- NTSTATUS (*add_sam_account)(struct pdb_methods *, SAM_ACCOUNT *sampass);
+ NTSTATUS (*add_sam_account)(struct pdb_methods *, struct samu *sampass);
- NTSTATUS (*update_sam_account)(struct pdb_methods *, SAM_ACCOUNT *sampass);
+ NTSTATUS (*update_sam_account)(struct pdb_methods *, struct samu *sampass);
- NTSTATUS (*delete_sam_account)(struct pdb_methods *, SAM_ACCOUNT *username);
+ NTSTATUS (*delete_sam_account)(struct pdb_methods *, struct samu *username);
- NTSTATUS (*rename_sam_account)(struct pdb_methods *, SAM_ACCOUNT *oldname, const char *newname);
+ NTSTATUS (*rename_sam_account)(struct pdb_methods *, struct samu *oldname, const char *newname);
- NTSTATUS (*update_login_attempts)(struct pdb_methods *methods, SAM_ACCOUNT *sam_acct, BOOL success);
+ NTSTATUS (*update_login_attempts)(struct pdb_methods *methods, struct samu *sam_acct, BOOL success);
NTSTATUS (*getgrsid)(struct pdb_methods *methods, GROUP_MAP *map, DOM_SID sid);
@@ -434,6 +281,13 @@ typedef struct pdb_methods
NTSTATUS (*getgrnam)(struct pdb_methods *methods, GROUP_MAP *map, const char *name);
+ NTSTATUS (*create_dom_group)(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx, const char *name,
+ uint32 *rid);
+
+ NTSTATUS (*delete_dom_group)(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx, uint32 rid);
+
NTSTATUS (*add_group_mapping_entry)(struct pdb_methods *methods,
GROUP_MAP *map);
@@ -444,7 +298,7 @@ typedef struct pdb_methods
DOM_SID sid);
NTSTATUS (*enum_group_mapping)(struct pdb_methods *methods,
- enum SID_NAME_USE sid_name_use,
+ const DOM_SID *sid, enum SID_NAME_USE sid_name_use,
GROUP_MAP **pp_rmap, size_t *p_num_entries,
BOOL unix_only);
@@ -455,11 +309,23 @@ typedef struct pdb_methods
size_t *p_num_members);
NTSTATUS (*enum_group_memberships)(struct pdb_methods *methods,
- const char *username,
- gid_t primary_gid,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user,
DOM_SID **pp_sids, gid_t **pp_gids,
size_t *p_num_groups);
+ NTSTATUS (*set_unix_primary_group)(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user);
+
+ NTSTATUS (*add_groupmem)(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 member_rid);
+
+ NTSTATUS (*del_groupmem)(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 member_rid);
+
NTSTATUS (*find_alias)(struct pdb_methods *methods,
const char *name, DOM_SID *sid);
@@ -499,6 +365,13 @@ typedef struct pdb_methods
const char **pp_names,
uint32 *attrs);
+ NTSTATUS (*lookup_names)(struct pdb_methods *methods,
+ const DOM_SID *domain_sid,
+ int num_names,
+ const char **pp_names,
+ uint32 *rids,
+ uint32 *attrs);
+
NTSTATUS (*get_account_policy)(struct pdb_methods *methods,
int policy_index, uint32 *value);
@@ -509,30 +382,37 @@ typedef struct pdb_methods
BOOL (*search_users)(struct pdb_methods *methods,
struct pdb_search *search,
- uint16 acct_flags);
+ uint32 acct_flags);
BOOL (*search_groups)(struct pdb_methods *methods,
struct pdb_search *search);
BOOL (*search_aliases)(struct pdb_methods *methods,
struct pdb_search *search,
const DOM_SID *sid);
+ BOOL (*uid_to_rid)(struct pdb_methods *methods, uid_t uid,
+ uint32 *rid);
+ 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);
+
+ BOOL (*rid_algorithm)(struct pdb_methods *methods);
+ BOOL (*new_rid)(struct pdb_methods *methods, uint32 *rid);
+
void *private_data; /* Private data of some kind */
void (*free_private_data)(void **);
+};
-} PDB_METHODS;
-
-typedef NTSTATUS (*pdb_init_function)(struct pdb_context *,
- struct pdb_methods **,
- const char *);
+typedef NTSTATUS (*pdb_init_function)(struct pdb_methods **, const char *);
struct pdb_init_function_entry {
const char *name;
+
/* Function to create a member of the pdb_methods list */
pdb_init_function init;
+
struct pdb_init_function_entry *prev, *next;
};
-enum sql_search_field { SQL_SEARCH_NONE = 0, SQL_SEARCH_USER_SID = 1, SQL_SEARCH_USER_NAME = 2};
-
#endif /* _PASSDB_H */
diff --git a/source/include/rpc_dce.h b/source/include/rpc_dce.h
index e718d92271c..b4d350ee6fa 100644
--- a/source/include/rpc_dce.h
+++ b/source/include/rpc_dce.h
@@ -82,6 +82,16 @@ enum RPC_PKT_TYPE {
#define RPC_PIPE_AUTH_SEAL_LEVEL 0x6
#endif
+#define DCERPC_FAULT_OP_RNG_ERROR 0x1c010002
+#define DCERPC_FAULT_UNK_IF 0x1c010003
+#define DCERPC_FAULT_INVALID_TAG 0x1c000006
+#define DCERPC_FAULT_CONTEXT_MISMATCH 0x1c00001a
+#define DCERPC_FAULT_OTHER 0x00000001
+#define DCERPC_FAULT_ACCESS_DENIED 0x00000005
+#define DCERPC_FAULT_CANT_PERFORM 0x000006d8
+#define DCERPC_FAULT_NDR 0x000006f7
+
+
/* Netlogon schannel auth type and level */
#define SCHANNEL_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
#define SCHANNEL_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
@@ -90,12 +100,17 @@ enum RPC_PKT_TYPE {
#define RPC_AUTH_SCHANNEL_SIGN_ONLY_CHK_LEN 0x18
+#define NETLOGON_NEG_ARCFOUR 0x00000004
+#define NETLOGON_NEG_128BIT 0x00004000
+#define NETLOGON_NEG_SCHANNEL 0x40000000
+
/* The 7 here seems to be required to get Win2k not to downgrade us
to NT4. Actually, anything other than 1ff would seem to do... */
#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff
-
-#define NETLOGON_NEG_SCHANNEL 0x40000000
#define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT 0x2010b000
+
+/* these are the flags that ADS clients use */
+#define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL)
enum schannel_direction {
SENDER_IS_INITIATOR,
diff --git a/source/include/rpc_dfs.h b/source/include/rpc_dfs.h
index 7aee208c14b..adf25c9938b 100644
--- a/source/include/rpc_dfs.h
+++ b/source/include/rpc_dfs.h
@@ -1,164 +1,396 @@
-/*
- Unix SMB/CIFS implementation.
- Samba parameters and setup
- Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Luke Kenneth Casson Leighton 1996 - 2000
- Copyright (C) Shirish Kalele 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.
-*/
-
-#ifndef _RPC_DFS_H
-#define _RPC_DFS_H
-
-/* NETDFS pipe: calls */
-#define DFS_EXIST 0x00
-#define DFS_ADD 0x01
-#define DFS_REMOVE 0x02
-#define DFS_GET_INFO 0x04
-#define DFS_ENUM 0x05
-
-/* dfsadd flags */
-#define DFSFLAG_ADD_VOLUME 0x00000001
-#define DFSFLAG_RESTORE_VOLUME 0x00000002
-
-typedef struct dfs_q_dfs_exist {
- uint32 dummy;
-} DFS_Q_DFS_EXIST;
-
-/* status == 1 if dfs exists. */
-typedef struct dfs_r_dfs_exist {
- uint32 status; /* Not a WERROR or NTSTATUS code */
-} DFS_R_DFS_EXIST;
-
-typedef struct dfs_q_dfs_add {
- uint32 ptr_DfsEntryPath;
- UNISTR2 DfsEntryPath;
- uint32 ptr_ServerName;
- UNISTR2 ServerName;
- uint32 ptr_ShareName;
- UNISTR2 ShareName;
- uint32 ptr_Comment;
- UNISTR2 Comment;
- uint32 Flags;
-} DFS_Q_DFS_ADD;
-
-typedef struct dfs_r_dfs_add {
- WERROR status;
-} DFS_R_DFS_ADD;
-
-/********************************************/
-typedef struct dfs_q_dfs_remove {
- UNISTR2 DfsEntryPath;
- uint32 ptr_ServerName;
- UNISTR2 ServerName;
- uint32 ptr_ShareName;
- UNISTR2 ShareName;
-} DFS_Q_DFS_REMOVE;
-
-typedef struct dfs_r_dfs_remove {
- WERROR status;
-} DFS_R_DFS_REMOVE;
-
-/********************************************/
-typedef struct dfs_info_1 {
- uint32 ptr_entrypath;
- UNISTR2 entrypath;
-} DFS_INFO_1;
-
-typedef struct dfs_info_2 {
- uint32 ptr_entrypath;
- UNISTR2 entrypath;
- uint32 ptr_comment;
+/*
+ * Unix SMB/CIFS implementation.
+ * header auto-generated by pidl. DO NOT MODIFY!
+ */
+
+
+#ifndef _RPC_NETDFS_H
+#define _RPC_NETDFS_H
+
+#define DFS_GETMANAGERVERSION 0
+#define DFS_ADD 1
+#define DFS_REMOVE 2
+#define DFS_SETINFO 3
+#define DFS_GETINFO 4
+#define DFS_ENUM 5
+#define DFS_RENAME 6
+#define DFS_MOVE 7
+#define DFS_MANAGERGETCONFIGINFO 8
+#define DFS_MANAGERSENDSITEINFO 9
+#define DFS_ADDFTROOT 10
+#define DFS_REMOVEFTROOT 11
+#define DFS_ADDSTDROOT 12
+#define DFS_REMOVESTDROOT 13
+#define DFS_MANAGERINITIALIZE 14
+#define DFS_ADDSTDROOTFORCED 15
+#define DFS_GETDCADDRESS 16
+#define DFS_SETDCADDRESS 17
+#define DFS_FLUSHFTTABLE 18
+#define DFS_ADD2 19
+#define DFS_REMOVE2 20
+#define DFS_ENUMEX 21
+#define DFS_SETINFO2 22
+
+typedef struct netdfs_dfs_Info0 {
+ uint32 dummy;
+} NETDFS_DFS_INFO0;
+
+typedef struct netdfs_dfs_Info1 {
+ uint32 ptr0_path;
+ UNISTR2 path;
+} NETDFS_DFS_INFO1;
+
+typedef struct netdfs_dfs_Info2 {
+ uint32 ptr0_path;
+ UNISTR2 path;
+ uint32 ptr0_comment;
UNISTR2 comment;
uint32 state;
- uint32 num_storages;
-} DFS_INFO_2;
+ uint32 num_stores;
+} NETDFS_DFS_INFO2;
-typedef struct dfs_storage_info {
+typedef struct netdfs_dfs_StorageInfo {
uint32 state;
- uint32 ptr_servername;
- UNISTR2 servername;
- uint32 ptr_sharename;
- UNISTR2 sharename;
-} DFS_STORAGE_INFO;
-
-typedef struct dfs_info_3 {
- uint32 ptr_entrypath;
- UNISTR2 entrypath;
- uint32 ptr_comment;
+ uint32 ptr0_server;
+ UNISTR2 server;
+ uint32 ptr0_share;
+ UNISTR2 share;
+} NETDFS_DFS_STORAGEINFO;
+
+typedef struct netdfs_dfs_Info3 {
+ uint32 ptr0_path;
+ UNISTR2 path;
+ uint32 ptr0_comment;
UNISTR2 comment;
uint32 state;
- uint32 num_storages;
- uint32 ptr_storages;
- uint32 num_storage_infos;
- DFS_STORAGE_INFO* storages;
-} DFS_INFO_3;
+ uint32 num_stores;
+ uint32 ptr0_stores;
+ uint32 size_stores;
+ NETDFS_DFS_STORAGEINFO *stores;
+} NETDFS_DFS_INFO3;
+
+typedef struct netdfs_dfs_Info4 {
+ uint32 ptr0_path;
+ UNISTR2 path;
+ uint32 ptr0_comment;
+ UNISTR2 comment;
+ uint32 state;
+ uint32 timeout;
+ struct uuid guid;
+ uint32 num_stores;
+ uint32 ptr0_stores;
+ uint32 size_stores;
+ NETDFS_DFS_STORAGEINFO *stores;
+} NETDFS_DFS_INFO4;
+
+typedef struct netdfs_dfs_Info100 {
+ uint32 ptr0_comment;
+ UNISTR2 comment;
+} NETDFS_DFS_INFO100;
+
+typedef struct netdfs_dfs_Info101 {
+ uint32 state;
+} NETDFS_DFS_INFO101;
-typedef struct dfs_info_ctr {
+typedef struct netdfs_dfs_Info102 {
+ uint32 timeout;
+} NETDFS_DFS_INFO102;
+
+typedef struct netdfs_dfs_Info200 {
+ uint32 ptr0_dom_root;
+ UNISTR2 dom_root;
+} NETDFS_DFS_INFO200;
+
+typedef struct netdfs_dfs_Info300 {
+ uint32 flags;
+ uint32 ptr0_dom_root;
+ UNISTR2 dom_root;
+} NETDFS_DFS_INFO300;
+
+typedef struct netdfs_dfs_Info_ctr {
uint32 switch_value;
- uint32 num_entries;
- uint32 ptr_dfs_ctr; /* pointer to dfs info union */
- union {
- DFS_INFO_1 *info1;
- DFS_INFO_2 *info2;
- DFS_INFO_3 *info3;
- } dfs;
-} DFS_INFO_CTR;
-
-typedef struct dfs_q_dfs_get_info {
- UNISTR2 uni_path;
-
- uint32 ptr_server;
- UNISTR2 uni_server;
-
- uint32 ptr_share;
- UNISTR2 uni_share;
-
- uint32 level;
-} DFS_Q_DFS_GET_INFO;
+ uint32 ptr0;
+ union netdfs_dfs_Info {
+ NETDFS_DFS_INFO0 info0;
+ NETDFS_DFS_INFO1 info1;
+ NETDFS_DFS_INFO2 info2;
+ NETDFS_DFS_INFO3 info3;
+ NETDFS_DFS_INFO4 info4;
+ NETDFS_DFS_INFO100 info100;
+ NETDFS_DFS_INFO101 info101;
+ NETDFS_DFS_INFO102 info102;
+ } u;
+} NETDFS_DFS_INFO_CTR;
+
+typedef struct netdfs_dfs_EnumArray1 {
+ uint32 count;
+ uint32 ptr0_s;
+ uint32 size_s;
+ NETDFS_DFS_INFO1 *s;
+} NETDFS_DFS_ENUMARRAY1;
+
+typedef struct netdfs_dfs_EnumArray2 {
+ uint32 count;
+ uint32 ptr0_s;
+ uint32 size_s;
+ NETDFS_DFS_INFO2 *s;
+} NETDFS_DFS_ENUMARRAY2;
+
+typedef struct netdfs_dfs_EnumArray3 {
+ uint32 count;
+ uint32 ptr0_s;
+ uint32 size_s;
+ NETDFS_DFS_INFO3 *s;
+} NETDFS_DFS_ENUMARRAY3;
-typedef struct dfs_r_dfs_get_info {
+typedef struct netdfs_dfs_EnumArray4 {
+ uint32 count;
+ uint32 ptr0_s;
+ uint32 size_s;
+ NETDFS_DFS_INFO4 *s;
+} NETDFS_DFS_ENUMARRAY4;
+
+typedef struct netdfs_dfs_EnumArray200 {
+ uint32 count;
+ uint32 ptr0_s;
+ uint32 size_s;
+ NETDFS_DFS_INFO200 *s;
+} NETDFS_DFS_ENUMARRAY200;
+
+typedef struct netdfs_dfs_EnumArray300 {
+ uint32 count;
+ uint32 ptr0_s;
+ uint32 size_s;
+ NETDFS_DFS_INFO300 *s;
+} NETDFS_DFS_ENUMARRAY300;
+
+typedef struct netdfs_dfs_EnumInfo_ctr {
+ uint32 switch_value;
+ uint32 ptr0;
+ union netdfs_dfs_EnumInfo {
+ NETDFS_DFS_ENUMARRAY1 info1;
+ NETDFS_DFS_ENUMARRAY2 info2;
+ NETDFS_DFS_ENUMARRAY3 info3;
+ NETDFS_DFS_ENUMARRAY4 info4;
+ NETDFS_DFS_ENUMARRAY200 info200;
+ NETDFS_DFS_ENUMARRAY300 info300;
+ } u;
+} NETDFS_DFS_ENUMINFO_CTR;
+
+typedef struct netdfs_dfs_EnumStruct {
uint32 level;
- uint32 ptr_ctr;
- DFS_INFO_CTR ctr;
+ NETDFS_DFS_ENUMINFO_CTR e;
+} NETDFS_DFS_ENUMSTRUCT;
+
+typedef struct netdfs_q_dfs_GetManagerVersion {
+ uint32 dummy;
+} NETDFS_Q_DFS_GETMANAGERVERSION;
+
+typedef struct netdfs_r_dfs_GetManagerVersion {
+ uint32 exist_flag;
+} NETDFS_R_DFS_GETMANAGERVERSION;
+
+typedef struct netdfs_q_dfs_Add {
+ UNISTR2 path;
+ UNISTR2 server;
+ uint32 ptr0_share;
+ UNISTR2 share;
+ uint32 ptr0_comment;
+ UNISTR2 comment;
+ uint32 flags;
+} NETDFS_Q_DFS_ADD;
+
+typedef struct netdfs_r_dfs_Add {
+ WERROR status;
+} NETDFS_R_DFS_ADD;
+
+typedef struct netdfs_q_dfs_Remove {
+ UNISTR2 path;
+ uint32 ptr0_server;
+ UNISTR2 server;
+ uint32 ptr0_share;
+ UNISTR2 share;
+} NETDFS_Q_DFS_REMOVE;
+
+typedef struct netdfs_r_dfs_Remove {
WERROR status;
-} DFS_R_DFS_GET_INFO;
+} NETDFS_R_DFS_REMOVE;
-typedef struct dfs_q_dfs_enum {
+typedef struct netdfs_q_dfs_SetInfo {
+ uint32 dummy;
+} NETDFS_Q_DFS_SETINFO;
+
+typedef struct netdfs_r_dfs_SetInfo {
+ WERROR status;
+} NETDFS_R_DFS_SETINFO;
+
+typedef struct netdfs_q_dfs_GetInfo {
+ UNISTR2 path;
+ uint32 ptr0_server;
+ UNISTR2 server;
+ uint32 ptr0_share;
+ UNISTR2 share;
uint32 level;
- uint32 maxpreflen;
- uint32 ptr_buffer;
- uint32 level2;
- uint32 ptr_num_entries;
- uint32 num_entries;
- uint32 ptr_num_entries2;
- uint32 num_entries2;
- ENUM_HND reshnd;
-} DFS_Q_DFS_ENUM;
-
-typedef struct dfs_r_dfs_enum {
- DFS_INFO_CTR *ctr;
- uint32 ptr_buffer;
+} NETDFS_Q_DFS_GETINFO;
+
+typedef struct netdfs_r_dfs_GetInfo {
+ NETDFS_DFS_INFO_CTR info;
+ WERROR status;
+} NETDFS_R_DFS_GETINFO;
+
+typedef struct netdfs_q_dfs_Enum {
uint32 level;
- uint32 level2;
- uint32 ptr_num_entries;
- uint32 num_entries;
- uint32 ptr_num_entries2;
- uint32 num_entries2;
- ENUM_HND reshnd;
- WERROR status;
-} DFS_R_DFS_ENUM;
-#endif
+ uint32 bufsize;
+ uint32 ptr0_info;
+ NETDFS_DFS_ENUMSTRUCT info;
+ uint32 ptr0_unknown;
+ uint32 unknown;
+ uint32 ptr0_total;
+ uint32 total;
+} NETDFS_Q_DFS_ENUM;
+
+typedef struct netdfs_r_dfs_Enum {
+ uint32 ptr0_info;
+ NETDFS_DFS_ENUMSTRUCT info;
+ uint32 ptr0_total;
+ uint32 total;
+ WERROR status;
+} NETDFS_R_DFS_ENUM;
+
+typedef struct netdfs_q_dfs_Rename {
+ uint32 dummy;
+} NETDFS_Q_DFS_RENAME;
+
+typedef struct netdfs_r_dfs_Rename {
+ WERROR status;
+} NETDFS_R_DFS_RENAME;
+
+typedef struct netdfs_q_dfs_Move {
+ uint32 dummy;
+} NETDFS_Q_DFS_MOVE;
+
+typedef struct netdfs_r_dfs_Move {
+ WERROR status;
+} NETDFS_R_DFS_MOVE;
+
+typedef struct netdfs_q_dfs_ManagerGetConfigInfo {
+ uint32 dummy;
+} NETDFS_Q_DFS_MANAGERGETCONFIGINFO;
+
+typedef struct netdfs_r_dfs_ManagerGetConfigInfo {
+ WERROR status;
+} NETDFS_R_DFS_MANAGERGETCONFIGINFO;
+
+typedef struct netdfs_q_dfs_ManagerSendSiteInfo {
+ uint32 dummy;
+} NETDFS_Q_DFS_MANAGERSENDSITEINFO;
+
+typedef struct netdfs_r_dfs_ManagerSendSiteInfo {
+ WERROR status;
+} NETDFS_R_DFS_MANAGERSENDSITEINFO;
+
+typedef struct netdfs_q_dfs_AddFtRoot {
+ uint32 dummy;
+} NETDFS_Q_DFS_ADDFTROOT;
+
+typedef struct netdfs_r_dfs_AddFtRoot {
+ WERROR status;
+} NETDFS_R_DFS_ADDFTROOT;
+
+typedef struct netdfs_q_dfs_RemoveFtRoot {
+ uint32 dummy;
+} NETDFS_Q_DFS_REMOVEFTROOT;
+
+typedef struct netdfs_r_dfs_RemoveFtRoot {
+ WERROR status;
+} NETDFS_R_DFS_REMOVEFTROOT;
+
+typedef struct netdfs_q_dfs_AddStdRoot {
+ uint32 dummy;
+} NETDFS_Q_DFS_ADDSTDROOT;
+
+typedef struct netdfs_r_dfs_AddStdRoot {
+ WERROR status;
+} NETDFS_R_DFS_ADDSTDROOT;
+
+typedef struct netdfs_q_dfs_RemoveStdRoot {
+ uint32 dummy;
+} NETDFS_Q_DFS_REMOVESTDROOT;
+
+typedef struct netdfs_r_dfs_RemoveStdRoot {
+ WERROR status;
+} NETDFS_R_DFS_REMOVESTDROOT;
+
+typedef struct netdfs_q_dfs_ManagerInitialize {
+ uint32 dummy;
+} NETDFS_Q_DFS_MANAGERINITIALIZE;
+
+typedef struct netdfs_r_dfs_ManagerInitialize {
+ WERROR status;
+} NETDFS_R_DFS_MANAGERINITIALIZE;
+
+typedef struct netdfs_q_dfs_AddStdRootForced {
+ uint32 dummy;
+} NETDFS_Q_DFS_ADDSTDROOTFORCED;
+
+typedef struct netdfs_r_dfs_AddStdRootForced {
+ WERROR status;
+} NETDFS_R_DFS_ADDSTDROOTFORCED;
+
+typedef struct netdfs_q_dfs_GetDcAddress {
+ uint32 dummy;
+} NETDFS_Q_DFS_GETDCADDRESS;
+
+typedef struct netdfs_r_dfs_GetDcAddress {
+ WERROR status;
+} NETDFS_R_DFS_GETDCADDRESS;
+
+typedef struct netdfs_q_dfs_SetDcAddress {
+ uint32 dummy;
+} NETDFS_Q_DFS_SETDCADDRESS;
+
+typedef struct netdfs_r_dfs_SetDcAddress {
+ WERROR status;
+} NETDFS_R_DFS_SETDCADDRESS;
+
+typedef struct netdfs_q_dfs_FlushFtTable {
+ uint32 dummy;
+} NETDFS_Q_DFS_FLUSHFTTABLE;
+
+typedef struct netdfs_r_dfs_FlushFtTable {
+ WERROR status;
+} NETDFS_R_DFS_FLUSHFTTABLE;
+
+typedef struct netdfs_q_dfs_Add2 {
+ uint32 dummy;
+} NETDFS_Q_DFS_ADD2;
+
+typedef struct netdfs_r_dfs_Add2 {
+ WERROR status;
+} NETDFS_R_DFS_ADD2;
+
+typedef struct netdfs_q_dfs_Remove2 {
+ uint32 dummy;
+} NETDFS_Q_DFS_REMOVE2;
+
+typedef struct netdfs_r_dfs_Remove2 {
+ WERROR status;
+} NETDFS_R_DFS_REMOVE2;
+
+typedef struct netdfs_q_dfs_EnumEx {
+ uint32 dummy;
+} NETDFS_Q_DFS_ENUMEX;
+
+typedef struct netdfs_r_dfs_EnumEx {
+ WERROR status;
+} NETDFS_R_DFS_ENUMEX;
+
+typedef struct netdfs_q_dfs_SetInfo2 {
+ uint32 dummy;
+} NETDFS_Q_DFS_SETINFO2;
+
+typedef struct netdfs_r_dfs_SetInfo2 {
+ WERROR status;
+} NETDFS_R_DFS_SETINFO2;
+
+#endif /* _RPC_NETDFS_H */
diff --git a/source/include/rpc_lsa.h b/source/include/rpc_lsa.h
index dd255c28d5d..c4ce9e021d1 100644
--- a/source/include/rpc_lsa.h
+++ b/source/include/rpc_lsa.h
@@ -26,12 +26,6 @@
/* Opcodes available on PIPE_LSARPC */
-#if 0 /* UNIMPLEMENTED */
-
-#define LSA_LOOKUPSIDS2 0x39
-
-#endif
-
#define LSA_CLOSE 0x00
#define LSA_DELETE 0x01
#define LSA_ENUM_PRIVS 0x02
@@ -57,7 +51,7 @@
#define LSA_SETQUOTAS 0x16
#define LSA_GETSYSTEMACCOUNT 0x17
#define LSA_SETSYSTEMACCOUNT 0x18
-#define LSA_OPENTRUSTDOM 0x19 /* TODO: implement this one -- jerry */
+#define LSA_OPENTRUSTDOM 0x19
#define LSA_QUERYTRUSTDOMINFO 0x1a
#define LSA_SETINFOTRUSTDOM 0x1b
#define LSA_OPENSECRET 0x1c /* TODO: implement this one -- jerry */
@@ -80,26 +74,53 @@
#define LSA_UNK_GET_CONNUSER 0x2d /* LsaGetConnectedCredentials ? */
#define LSA_QUERYINFO2 0x2e
#define LSA_QUERYTRUSTDOMINFOBYNAME 0x30
+#define LSA_QUERYDOMINFOPOL 0x35
#define LSA_OPENTRUSTDOMBYNAME 0x37
+#define LSA_LOOKUPSIDS2 0x39
+#define LSA_LOOKUPNAMES2 0x3a
+#define LSA_LOOKUPNAMES3 0x44
+#define LSA_LOOKUPSIDS3 0x4c
+#define LSA_LOOKUPNAMES4 0x4d
+
/* XXXX these are here to get a compile! */
#define LSA_LOOKUPRIDS 0xFD
-/* DOM_QUERY - info class 3 and 5 LSA Query response */
-typedef struct dom_query_info
-{
- uint16 uni_dom_max_len; /* domain name string length * 2 */
- uint16 uni_dom_str_len; /* domain name string length * 2 */
- uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */
- uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */
- UNISTR2 uni_domain_name; /* domain name (unicode string) */
- DOM_SID2 dom_sid; /* domain SID */
-
-} DOM_QUERY;
+#define LSA_AUDIT_NUM_CATEGORIES_NT4 7
+#define LSA_AUDIT_NUM_CATEGORIES_WIN2K 9
+
+#define LSA_AUDIT_NUM_CATEGORIES LSA_AUDIT_NUM_CATEGORIES_NT4
+
+#define LSA_AUDIT_POLICY_NONE 0x00
+#define LSA_AUDIT_POLICY_SUCCESS 0x01
+#define LSA_AUDIT_POLICY_FAILURE 0x02
+#define LSA_AUDIT_POLICY_ALL (LSA_AUDIT_POLICY_SUCCESS|LSA_AUDIT_POLICY_FAILURE)
+#define LSA_AUDIT_POLICY_CLEAR 0x04
+
+enum lsa_audit_categories {
+ LSA_AUDIT_CATEGORY_SYSTEM = 0,
+ LSA_AUDIT_CATEGORY_LOGON = 1,
+ LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS,
+ LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS,
+ LSA_AUDIT_CATEGORY_PROCCESS_TRACKING,
+ LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES,
+ LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT,
+ LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS, /* only in win2k/2k3 */
+ LSA_AUDIT_CATEGORY_ACCOUNT_LOGON /* only in win2k/2k3 */
+};
+
+/* level 1 is auditing settings */
+typedef struct dom_query_1
+{
+ uint32 percent_full;
+ uint32 log_size;
+ NTTIME retention_time;
+ uint8 shutdown_in_progress;
+ NTTIME time_to_shutdown;
+ uint32 next_audit_record;
+ uint32 unknown;
+} DOM_QUERY_1;
-/* level 5 is same as level 3. */
-typedef DOM_QUERY DOM_QUERY_3;
-typedef DOM_QUERY DOM_QUERY_5;
/* level 2 is auditing settings */
typedef struct dom_query_2
@@ -107,15 +128,62 @@ typedef struct dom_query_2
uint32 auditing_enabled;
uint32 count1; /* usualy 7, at least on nt4sp4 */
uint32 count2; /* the same */
+ uint32 ptr;
uint32 *auditsettings;
} DOM_QUERY_2;
+/* DOM_QUERY - info class 3 and 5 LSA Query response */
+typedef struct dom_query_info_3
+{
+ uint16 uni_dom_max_len; /* domain name string length * 2 */
+ uint16 uni_dom_str_len; /* domain name string length * 2 */
+ uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */
+ uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */
+ UNISTR2 uni_domain_name; /* domain name (unicode string) */
+ DOM_SID2 dom_sid; /* domain SID */
+
+} DOM_QUERY_3;
+
+/* level 5 is same as level 3. */
+typedef DOM_QUERY_3 DOM_QUERY_5;
+
/* level 6 is server role information */
typedef struct dom_query_6
{
uint16 server_role; /* 2=backup, 3=primary */
} DOM_QUERY_6;
+/* level 10 is audit full set info */
+typedef struct dom_query_10
+{
+ uint8 shutdown_on_full;
+} DOM_QUERY_10;
+
+/* level 11 is audit full query info */
+typedef struct dom_query_11
+{
+ uint16 unknown;
+ uint8 shutdown_on_full;
+ uint8 log_is_full;
+} DOM_QUERY_11;
+
+/* level 12 is DNS domain info */
+typedef struct lsa_dns_dom_info
+{
+ UNIHDR hdr_nb_dom_name; /* netbios domain name */
+ UNIHDR hdr_dns_dom_name;
+ UNIHDR hdr_forest_name;
+
+ struct uuid dom_guid; /* domain GUID */
+
+ UNISTR2 uni_nb_dom_name;
+ UNISTR2 uni_dns_dom_name;
+ UNISTR2 uni_forest_name;
+
+ uint32 ptr_dom_sid;
+ DOM_SID2 dom_sid; /* domain SID */
+} DOM_QUERY_12;
+
typedef struct seq_qos_info
{
uint32 len; /* 12 */
@@ -244,67 +312,56 @@ typedef struct r_lsa_query_sec_obj_info
typedef struct lsa_query_info
{
POLICY_HND pol; /* policy handle */
- uint16 info_class; /* info class */
+ uint16 info_class; /* info class */
} LSA_Q_QUERY_INFO;
-/* LSA_INFO_UNION */
-typedef union lsa_info_union
-{
- DOM_QUERY_2 id2;
- DOM_QUERY_3 id3;
- DOM_QUERY_5 id5;
- DOM_QUERY_6 id6;
-} LSA_INFO_UNION;
-
-/* LSA_R_QUERY_INFO - response to LSA query info policy */
-typedef struct lsa_r_query_info
+/* LSA_INFO_CTR */
+typedef struct lsa_info_ctr
{
- uint32 undoc_buffer; /* undocumented buffer pointer */
- uint16 info_class; /* info class (same as info class in request) */
-
- LSA_INFO_UNION dom;
+ uint16 info_class;
+ union {
+ DOM_QUERY_1 id1;
+ DOM_QUERY_2 id2;
+ DOM_QUERY_3 id3;
+ DOM_QUERY_5 id5;
+ DOM_QUERY_6 id6;
+ DOM_QUERY_10 id10;
+ DOM_QUERY_11 id11;
+ DOM_QUERY_12 id12;
+ } info;
- NTSTATUS status; /* return code */
+} LSA_INFO_CTR;
-} LSA_R_QUERY_INFO;
+typedef LSA_INFO_CTR LSA_INFO_CTR2;
-/* LSA_DNS_DOM_INFO - DNS domain info - info class 12*/
-typedef struct lsa_dns_dom_info
+/* LSA_Q_SET_INFO - LSA set info policy */
+typedef struct lsa_set_info
{
- UNIHDR hdr_nb_dom_name; /* netbios domain name */
- UNIHDR hdr_dns_dom_name;
- UNIHDR hdr_forest_name;
+ POLICY_HND pol; /* policy handle */
+ uint16 info_class; /* info class */
+ LSA_INFO_CTR ctr;
- struct uuid dom_guid; /* domain GUID */
+} LSA_Q_SET_INFO;
- UNISTR2 uni_nb_dom_name;
- UNISTR2 uni_dns_dom_name;
- UNISTR2 uni_forest_name;
+/* LSA_R_SET_INFO - response to LSA set info policy */
+typedef struct lsa_r_set_info
+{
+ NTSTATUS status; /* return code */
- uint32 ptr_dom_sid;
- DOM_SID2 dom_sid; /* domain SID */
-} LSA_DNS_DOM_INFO;
+} LSA_R_SET_INFO;
-typedef union lsa_info2_union
+/* LSA_R_QUERY_INFO - response to LSA query info policy */
+typedef struct lsa_r_query_info
{
- LSA_DNS_DOM_INFO dns_dom_info;
-} LSA_INFO2_UNION;
+ uint32 dom_ptr; /* undocumented buffer pointer */
+ LSA_INFO_CTR ctr;
+ NTSTATUS status; /* return code */
-/* LSA_Q_QUERY_INFO2 - LSA query info */
-typedef struct lsa_q_query_info2
-{
- POLICY_HND pol; /* policy handle */
- uint16 info_class; /* info class */
-} LSA_Q_QUERY_INFO2;
+} LSA_R_QUERY_INFO;
-typedef struct lsa_r_query_info2
-{
- uint32 ptr; /* pointer to info struct */
- uint16 info_class;
- LSA_INFO2_UNION info; /* so far the only one */
- NTSTATUS status;
-} LSA_R_QUERY_INFO2;
+typedef LSA_Q_QUERY_INFO LSA_Q_QUERY_INFO2;
+typedef LSA_R_QUERY_INFO LSA_R_QUERY_INFO2;
/*******************************************************/
@@ -371,13 +428,13 @@ typedef struct dom_trust_info
/* DOM_R_REF */
typedef struct dom_ref_info
{
- uint32 num_ref_doms_1; /* num referenced domains */
- uint32 ptr_ref_dom; /* pointer to referenced domains */
- uint32 max_entries; /* 32 - max number of entries */
- uint32 num_ref_doms_2; /* num referenced domains */
+ uint32 num_ref_doms_1; /* num referenced domains */
+ uint32 ptr_ref_dom; /* pointer to referenced domains */
+ uint32 max_entries; /* 32 - max number of entries */
+ uint32 num_ref_doms_2; /* num referenced domains */
- DOM_TRUST_HDR hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domains */
- DOM_TRUST_INFO ref_dom [MAX_REF_DOMAINS]; /* referenced domains */
+ DOM_TRUST_HDR hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domains */
+ DOM_TRUST_INFO ref_dom [MAX_REF_DOMAINS]; /* referenced domains */
} DOM_R_REF;
@@ -392,8 +449,18 @@ typedef struct lsa_trans_name_info
} LSA_TRANS_NAME;
+/* LSA_TRANS_NAME2 - translated name */
+typedef struct lsa_trans_name_info2
+{
+ uint16 sid_name_use; /* value is 5 for a well-known group; 2 for a domain group; 1 for a user... */
+ UNIHDR hdr_name;
+ uint32 domain_idx; /* index into DOM_R_REF array of SIDs */
+ uint32 unknown;
+
+} LSA_TRANS_NAME2;
+
/* This number is based on Win2k and later maximum response allowed */
-#define MAX_LOOKUP_SIDS 20480
+#define MAX_LOOKUP_SIDS 20480 /* 0x5000 */
/* LSA_TRANS_NAME_ENUM - LSA Translated Name Enumeration container */
typedef struct lsa_trans_name_enum_info
@@ -407,6 +474,18 @@ typedef struct lsa_trans_name_enum_info
} LSA_TRANS_NAME_ENUM;
+/* LSA_TRANS_NAME_ENUM2 - LSA Translated Name Enumeration container 2 */
+typedef struct lsa_trans_name_enum_info2
+{
+ uint32 num_entries;
+ uint32 ptr_trans_names;
+ uint32 num_entries2;
+
+ LSA_TRANS_NAME2 *name; /* translated names */
+ UNISTR2 *uni_name;
+
+} LSA_TRANS_NAME_ENUM2;
+
/* LSA_SID_ENUM - LSA SID enumeration container */
typedef struct lsa_sid_enum_info
{
@@ -443,6 +522,57 @@ typedef struct lsa_r_lookup_sids
} LSA_R_LOOKUP_SIDS;
+/* LSA_Q_LOOKUP_SIDS2 - LSA Lookup SIDs 2*/
+typedef struct lsa_q_lookup_sids2
+{
+ POLICY_HND pol; /* policy handle */
+ LSA_SID_ENUM sids;
+ LSA_TRANS_NAME_ENUM2 names;
+ uint16 level;
+ uint32 mapped_count;
+ uint32 unknown1;
+ uint32 unknown2;
+
+} LSA_Q_LOOKUP_SIDS2;
+
+/* LSA_R_LOOKUP_SIDS2 - response to LSA Lookup SIDs 2*/
+typedef struct lsa_r_lookup_sids2
+{
+ uint32 ptr_dom_ref;
+ DOM_R_REF *dom_ref; /* domain reference info */
+
+ LSA_TRANS_NAME_ENUM2 *names;
+ uint32 mapped_count;
+
+ NTSTATUS status; /* return code */
+
+} LSA_R_LOOKUP_SIDS2;
+
+/* LSA_Q_LOOKUP_SIDS3 - LSA Lookup SIDs 3 */
+typedef struct lsa_q_lookup_sids3
+{
+ LSA_SID_ENUM sids;
+ LSA_TRANS_NAME_ENUM2 names;
+ uint16 level;
+ uint32 mapped_count;
+ uint32 unknown1;
+ uint32 unknown2;
+
+} LSA_Q_LOOKUP_SIDS3;
+
+/* LSA_R_LOOKUP_SIDS3 - response to LSA Lookup SIDs 3 */
+typedef struct lsa_r_lookup_sids3
+{
+ uint32 ptr_dom_ref;
+ DOM_R_REF *dom_ref; /* domain reference info */
+
+ LSA_TRANS_NAME_ENUM2 *names;
+ uint32 mapped_count;
+
+ NTSTATUS status; /* return code */
+
+} LSA_R_LOOKUP_SIDS3;
+
/* LSA_Q_LOOKUP_NAMES - LSA Lookup NAMEs */
typedef struct lsa_q_lookup_names
{
@@ -454,7 +584,7 @@ typedef struct lsa_q_lookup_names
uint32 num_trans_entries;
uint32 ptr_trans_sids; /* undocumented domain SID buffer pointer */
- uint32 lookup_level;
+ uint16 lookup_level;
uint32 mapped_count;
} LSA_Q_LOOKUP_NAMES;
@@ -468,13 +598,122 @@ typedef struct lsa_r_lookup_names
uint32 num_entries;
uint32 ptr_entries;
uint32 num_entries2;
- DOM_RID2 *dom_rid; /* domain RIDs being looked up */
+ DOM_RID *dom_rid; /* domain RIDs being looked up */
uint32 mapped_count;
NTSTATUS status; /* return code */
} LSA_R_LOOKUP_NAMES;
+/* LSA_Q_LOOKUP_NAMES2 - LSA Lookup NAMEs 2*/
+typedef struct lsa_q_lookup_names2
+{
+ POLICY_HND pol; /* policy handle */
+ uint32 num_entries;
+ uint32 num_entries2;
+ UNIHDR *hdr_name; /* name buffer pointers */
+ UNISTR2 *uni_name; /* names to be looked up */
+
+ uint32 num_trans_entries;
+ uint32 ptr_trans_sids; /* undocumented domain SID buffer pointer */
+ uint16 lookup_level;
+ uint32 mapped_count;
+ uint32 unknown1;
+ uint32 unknown2;
+
+} LSA_Q_LOOKUP_NAMES2;
+
+/* LSA_R_LOOKUP_NAMES2 - response to LSA Lookup NAMEs by name 2 */
+typedef struct lsa_r_lookup_names2
+{
+ uint32 ptr_dom_ref;
+ DOM_R_REF *dom_ref; /* domain reference info */
+
+ uint32 num_entries;
+ uint32 ptr_entries;
+ uint32 num_entries2;
+ DOM_RID2 *dom_rid; /* domain RIDs being looked up */
+
+ uint32 mapped_count;
+
+ NTSTATUS status; /* return code */
+} LSA_R_LOOKUP_NAMES2;
+
+/* LSA_Q_LOOKUP_NAMES3 - LSA Lookup NAMEs 3 */
+typedef struct lsa_q_lookup_names3
+{
+ POLICY_HND pol; /* policy handle */
+ uint32 num_entries;
+ uint32 num_entries2;
+ UNIHDR *hdr_name; /* name buffer pointers */
+ UNISTR2 *uni_name; /* names to be looked up */
+
+ uint32 num_trans_entries;
+ uint32 ptr_trans_sids; /* undocumented domain SID buffer pointer */
+ uint16 lookup_level;
+ uint32 mapped_count;
+ uint32 unknown1;
+ uint32 unknown2;
+
+} LSA_Q_LOOKUP_NAMES3;
+
+/* Sid type used in lookupnames3 and lookupnames4. */
+typedef struct lsa_translatedsid3 {
+ uint8 sid_type;
+ DOM_SID2 *sid2;
+ uint32 sid_idx;
+ uint32 unknown;
+} LSA_TRANSLATED_SID3;
+
+/* LSA_R_LOOKUP_NAMES3 - response to LSA Lookup NAMEs by name 3 */
+typedef struct lsa_r_lookup_names3
+{
+ uint32 ptr_dom_ref;
+ DOM_R_REF *dom_ref; /* domain reference info */
+
+ uint32 num_entries;
+ uint32 ptr_entries;
+ uint32 num_entries2;
+ LSA_TRANSLATED_SID3 *trans_sids;
+
+ uint32 mapped_count;
+
+ NTSTATUS status; /* return code */
+} LSA_R_LOOKUP_NAMES3;
+
+/* LSA_Q_LOOKUP_NAMES4 - LSA Lookup NAMEs 4 */
+typedef struct lsa_q_lookup_names4
+{
+ uint32 num_entries;
+ uint32 num_entries2;
+ UNIHDR *hdr_name; /* name buffer pointers */
+ UNISTR2 *uni_name; /* names to be looked up */
+
+ uint32 num_trans_entries;
+ uint32 ptr_trans_sids; /* undocumented domain SID buffer pointer */
+ uint16 lookup_level;
+ uint32 mapped_count;
+ uint32 unknown1;
+ uint32 unknown2;
+
+} LSA_Q_LOOKUP_NAMES4;
+
+/* LSA_R_LOOKUP_NAMES3 - response to LSA Lookup NAMEs by name 4 */
+typedef struct lsa_r_lookup_names4
+{
+ uint32 ptr_dom_ref;
+ DOM_R_REF *dom_ref; /* domain reference info */
+
+ uint32 num_entries;
+ uint32 ptr_entries;
+ uint32 num_entries2;
+ LSA_TRANSLATED_SID3 *trans_sids;
+
+ uint32 mapped_count;
+
+ NTSTATUS status; /* return code */
+} LSA_R_LOOKUP_NAMES4;
+
typedef struct lsa_enum_priv_entry
{
UNIHDR hdr_name;
@@ -750,6 +989,25 @@ typedef struct {
/*******************************************************/
+/* LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME - LSA Query Open Trusted Domain by Name*/
+typedef struct lsa_q_open_trusted_domain_by_name
+{
+ POLICY_HND pol; /* policy handle */
+ LSA_STRING name; /* domain name */
+ uint32 access_mask; /* access mask */
+
+} LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME;
+
+/* LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME - response to LSA Query Open Trusted Domain by Name */
+typedef struct {
+ POLICY_HND handle; /* trustdom policy handle */
+ NTSTATUS status; /* return code */
+} LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME;
+
+
+/*******************************************************/
+
+
typedef struct {
POLICY_HND handle;
UNISTR4 secretname;
@@ -955,4 +1213,38 @@ typedef struct r_lsa_query_trusted_domain_info
NTSTATUS status;
} LSA_R_QUERY_TRUSTED_DOMAIN_INFO;
+typedef struct dom_info_kerberos {
+ uint32 enforce_restrictions;
+ NTTIME service_tkt_lifetime;
+ NTTIME user_tkt_lifetime;
+ NTTIME user_tkt_renewaltime;
+ NTTIME clock_skew;
+ NTTIME unknown6;
+} LSA_DOM_INFO_POLICY_KERBEROS;
+
+typedef struct dom_info_efs {
+ uint32 blob_len;
+ UNISTR2 efs_blob;
+} LSA_DOM_INFO_POLICY_EFS;
+
+typedef struct lsa_dom_info_union {
+ uint16 info_class;
+ LSA_DOM_INFO_POLICY_EFS efs_policy;
+ LSA_DOM_INFO_POLICY_KERBEROS krb_policy;
+} LSA_DOM_INFO_UNION;
+
+/* LSA_Q_QUERY_DOM_INFO_POLICY - LSA query info */
+typedef struct lsa_q_query_dom_info_policy
+{
+ POLICY_HND pol; /* policy handle */
+ uint16 info_class; /* info class */
+} LSA_Q_QUERY_DOM_INFO_POLICY;
+
+typedef struct lsa_r_query_dom_info_policy
+{
+ LSA_DOM_INFO_UNION *info;
+ NTSTATUS status;
+} LSA_R_QUERY_DOM_INFO_POLICY;
+
+
#endif /* _RPC_LSA_H */
diff --git a/source/include/rpc_misc.h b/source/include/rpc_misc.h
index 091ba3395e0..661d436859a 100644
--- a/source/include/rpc_misc.h
+++ b/source/include/rpc_misc.h
@@ -264,13 +264,20 @@ typedef struct {
* Domain SID structures
**********************************************************************/
-/* DOM_RID2 - domain RID structure for ntlsa pipe */
+/* DOM_RID - domain RID structure for ntlsa pipe */
typedef struct {
- uint8 type; /* value is SID_NAME_USE enum */
+ uint16 type; /* value is SID_NAME_USE enum */
uint32 rid;
uint32 rid_idx; /* referenced domain index */
-} DOM_RID2;
+} DOM_RID;
+/* DOM_RID2 - second domain RID structure for ntlsa pipe */
+typedef struct {
+ uint16 type; /* value is SID_NAME_USE enum */
+ uint32 rid;
+ uint32 rid_idx; /* referenced domain index */
+ uint32 unknown;
+} DOM_RID2;
typedef struct { /* DOM_RID3 - domain RID structure for samr pipe */
uint32 rid; /* domain-relative (to a SID) id */
@@ -317,7 +324,7 @@ typedef struct log_info {
/* DOM_CHAL - challenge info */
typedef struct chal_info {
- uchar data[8]; /* credentials */
+ unsigned char data[8]; /* credentials */
} DOM_CHAL;
/* DOM_CREDs - timestamped client or server credentials */
diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h
index c1d85403448..9df7701de41 100644
--- a/source/include/rpc_netlogon.h
+++ b/source/include/rpc_netlogon.h
@@ -41,6 +41,7 @@
#define NET_DSR_GETDCNAME 0x14
#define NET_AUTH3 0x1a
#define NET_DSR_GETSITENAME 0x1c
+#define NET_SAMLOGON_EX 0x27
/* Secure Channel types. used in NetrServerAuthenticate negotiation */
#define SEC_CHAN_WKSTA 2
@@ -86,8 +87,17 @@
#define NL_CTRL_REPL_IN_PROGRESS 0x0002
#define NL_CTRL_FULL_SYNC 0x0004
-#define LOGON_EXTRA_SIDS 0x0020
-#define LOGON_RESOURCE_GROUPS 0x0200
+#define LOGON_GUEST 0x00000001
+#define LOGON_NOENCRYPTION 0x00000002
+#define LOGON_CACHED_ACCOUNT 0x00000004
+#define LOGON_USED_LM_PASSWORD 0x00000008
+#define LOGON_EXTRA_SIDS 0x00000020
+#define LOGON_SUBAUTH_SESSION_KEY 0x00000040
+#define LOGON_SERVER_TRUST_ACCOUNT 0x00000080
+#define LOGON_NTLMV2_ENABLED 0x00000100
+#define LOGON_RESOURCE_GROUPS 0x00000200
+#define LOGON_PROFILE_PATH_RETURNED 0x00000400
+#define LOGON_GRACE_LOGON 0x01000000
#define SE_GROUP_MANDATORY 0x00000001
#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002
@@ -98,8 +108,20 @@
#define SE_GROUP_RESOURCE 0x20000000
/* Flags for controlling the behaviour of a particular logon */
-#define MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT ( 0x020 )
-#define MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT ( 0x800 )
+
+/* sets LOGON_SERVER_TRUST_ACCOUNT user_flag */
+#define MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT 0x00000020
+#define MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 0x00000800
+
+/* updates the "logon time" on network logon */
+#define MSV1_0_UPDATE_LOGON_STATISTICS 0x00000004
+
+/* returns the user parameters in the driveletter */
+#define MSV1_0_RETURN_USER_PARAMETERS 0x00000008
+
+/* returns the profilepath in the driveletter and
+ * sets LOGON_PROFILE_PATH_RETURNED user_flag */
+#define MSV1_0_RETURN_PROFILE_PATH 0x00000200
#if 0
/* I think this is correct - it's what gets parsed on the wire. JRA. */
@@ -160,6 +182,57 @@ typedef struct net_user_info_2 {
} NET_USER_INFO_2;
#endif
+/* NET_USER_INFO_2 */
+typedef struct net_user_info_2 {
+ uint32 ptr_user_info;
+
+ NTTIME logon_time; /* logon time */
+ NTTIME logoff_time; /* logoff time */
+ NTTIME kickoff_time; /* kickoff time */
+ NTTIME pass_last_set_time; /* password last set time */
+ NTTIME pass_can_change_time; /* password can change time */
+ NTTIME pass_must_change_time; /* password must change time */
+
+ UNIHDR hdr_user_name; /* username unicode string header */
+ UNIHDR hdr_full_name; /* user's full name unicode string header */
+ UNIHDR hdr_logon_script; /* logon script unicode string header */
+ UNIHDR hdr_profile_path; /* profile path unicode string header */
+ UNIHDR hdr_home_dir; /* home directory unicode string header */
+ UNIHDR hdr_dir_drive; /* home directory drive unicode string header */
+
+ uint16 logon_count; /* logon count */
+ uint16 bad_pw_count; /* bad password count */
+
+ uint32 user_rid; /* User RID */
+ uint32 group_rid; /* Group RID */
+
+ uint32 num_groups; /* num groups */
+ uint32 buffer_groups; /* undocumented buffer pointer to groups. */
+ uint32 user_flgs; /* user flags */
+
+ uint8 user_sess_key[16]; /* user session key */
+
+ UNIHDR hdr_logon_srv; /* logon server unicode string header */
+ UNIHDR hdr_logon_dom; /* logon domain unicode string header */
+
+ uint32 buffer_dom_id; /* undocumented logon domain id pointer */
+ uint8 lm_sess_key[8]; /* lm session key */
+ uint32 acct_flags; /* account flags */
+ uint32 unknown[7]; /* unknown */
+
+ UNISTR2 uni_user_name; /* username unicode string */
+ UNISTR2 uni_full_name; /* user's full name unicode string */
+ UNISTR2 uni_logon_script; /* logon script unicode string */
+ UNISTR2 uni_profile_path; /* profile path unicode string */
+ UNISTR2 uni_home_dir; /* home directory unicode string */
+ UNISTR2 uni_dir_drive; /* home directory drive unicode string */
+
+ UNISTR2 uni_logon_srv; /* logon server unicode string */
+ UNISTR2 uni_logon_dom; /* logon domain unicode string */
+
+ DOM_SID2 dom_sid; /* domain SID */
+} NET_USER_INFO_2;
+
/* NET_USER_INFO_3 */
typedef struct net_user_info_3 {
uint32 ptr_user_info;
@@ -511,12 +584,26 @@ typedef struct sam_info {
NET_ID_INFO_CTR *ctr;
} DOM_SAM_INFO;
+/* SAM_INFO - sam logon/off id structure - no creds */
+typedef struct sam_info_ex {
+ DOM_CLNT_SRV client;
+ uint16 logon_level;
+ NET_ID_INFO_CTR *ctr;
+} DOM_SAM_INFO_EX;
+
/* NET_Q_SAM_LOGON */
typedef struct net_q_sam_logon_info {
DOM_SAM_INFO sam_id;
uint16 validation_level;
} NET_Q_SAM_LOGON;
+/* NET_Q_SAM_LOGON_EX */
+typedef struct net_q_sam_logon_info_ex {
+ DOM_SAM_INFO_EX sam_id;
+ uint16 validation_level;
+ uint32 flags;
+} NET_Q_SAM_LOGON_EX;
+
/* NET_R_SAM_LOGON */
typedef struct net_r_sam_logon_info {
uint32 buffer_creds; /* undocumented buffer pointer */
@@ -530,6 +617,17 @@ typedef struct net_r_sam_logon_info {
NTSTATUS status; /* return code */
} NET_R_SAM_LOGON;
+/* NET_R_SAM_LOGON_EX */
+typedef struct net_r_sam_logon_info_ex {
+ uint16 switch_value; /* 3 - indicates type of USER INFO */
+ NET_USER_INFO_3 *user;
+
+ uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */
+ uint32 flags;
+
+ NTSTATUS status; /* return code */
+} NET_R_SAM_LOGON_EX;
+
/* NET_Q_SAM_LOGOFF */
typedef struct net_q_sam_logoff_info {
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 342db37ea57..37a0ed9a3f8 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -143,7 +143,7 @@ SamrTestPrivateFunctionsUser
#define SAMR_CONNECT 0x39
#define SAMR_SET_USERINFO 0x3A
#define SAMR_CONNECT4 0x3E
-#define SAMR_CHGPASSWD3 0x3F
+#define SAMR_CHGPASSWD_USER3 0x3F
#define SAMR_CONNECT5 0x40
typedef struct logon_hours_info
@@ -277,6 +277,13 @@ typedef struct sam_user_info_25
UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
} SAM_USER_INFO_25;
+/* SAM_USER_INFO_26 */
+typedef struct sam_user_info_26
+{
+ uint8 pass[532];
+ uint8 pw_len;
+} SAM_USER_INFO_26;
+
/* SAM_USER_INFO_21 */
typedef struct sam_user_info_21
@@ -461,9 +468,9 @@ SAMR_R_GET_USRDOM_PWINFO - a "set user info" occurs just after this
/* SAMR_R_GET_USRDOM_PWINFO */
typedef struct r_samr_usrdom_pwinfo_info
{
- uint16 unknown_0; /* 0000 */
+ uint16 min_pwd_length;
uint16 unknown_1; /* 0x0016 or 0x0015 */
- uint32 unknown_2; /* 0x0000 0000 */
+ uint32 password_properties;
NTSTATUS status;
} SAMR_R_GET_USRDOM_PWINFO;
@@ -736,8 +743,7 @@ typedef struct q_samr_enum_dom_users_info
POLICY_HND pol; /* policy handle */
uint32 start_idx; /* number of values (0 indicates unlimited?) */
- uint16 acb_mask; /* 0x0000 indicates all */
- uint16 unknown_1; /* 0x0000 */
+ uint32 acb_mask; /* 0x0000 indicates all */
uint32 max_size; /* 0x0000 ffff */
@@ -840,7 +846,7 @@ typedef struct samr_entry_info1
uint32 user_idx;
uint32 rid_user;
- uint16 acb_info;
+ uint32 acb_info;
UNIHDR hdr_acct_name;
UNIHDR hdr_user_name;
@@ -871,7 +877,7 @@ typedef struct samr_entry_info2
uint32 user_idx;
uint32 rid_user;
- uint16 acb_info;
+ uint32 acb_info;
UNIHDR hdr_srv_name;
UNIHDR hdr_srv_desc;
@@ -1106,6 +1112,21 @@ typedef struct samr_group_info4
} GROUP_INFO4;
+typedef struct samr_group_info5
+{
+ UNIHDR hdr_acct_name;
+
+ uint32 group_attr; /* 0x0000 0003 - group attribute */
+ uint32 num_members; /* 0x0000 0001 - number of group members? */
+
+ UNIHDR hdr_acct_desc;
+
+ UNISTR2 uni_acct_name;
+ UNISTR2 uni_acct_desc;
+
+} GROUP_INFO5;
+
+
/* GROUP_INFO_CTR */
typedef struct group_info_ctr
{
@@ -1117,7 +1138,7 @@ typedef struct group_info_ctr
GROUP_INFO2 info2;
GROUP_INFO3 info3;
GROUP_INFO4 info4;
-
+ GROUP_INFO5 info5;
} group;
} GROUP_INFO_CTR;
@@ -1198,6 +1219,10 @@ typedef struct {
} ALIAS_INFO1;
typedef struct {
+ UNISTR4 name;
+} ALIAS_INFO2;
+
+typedef struct {
UNISTR4 description;
} ALIAS_INFO3;
@@ -1210,6 +1235,7 @@ typedef struct {
uint16 level;
union {
ALIAS_INFO1 info1;
+ ALIAS_INFO2 info2;
ALIAS_INFO3 info3;
} alias;
} ALIAS_INFO_CTR;
@@ -1272,6 +1298,7 @@ typedef struct sam_userinfo_ctr_info
SAM_USER_INFO_23 *id23;
SAM_USER_INFO_24 *id24;
SAM_USER_INFO_25 *id25;
+ SAM_USER_INFO_26 *id26;
void* id; /* to make typecasting easy */
} info;
@@ -1677,13 +1704,10 @@ typedef struct r_samr_open_alias_info
/* SAMR_Q_CONNECT_ANON - probably an open */
-typedef struct q_samr_connect_anon_info
-{
+typedef struct q_samr_connect_anon_info {
uint32 ptr; /* ptr? */
- uint16 unknown_0; /* 0x005c */
- uint16 unknown_1; /* 0x0001 */
+ uint16 unknown_0; /* Only pushed if ptr is non-zero. */
uint32 access_mask;
-
} SAMR_Q_CONNECT_ANON;
/* SAMR_R_CONNECT_ANON - probably an open */
@@ -1821,7 +1845,7 @@ typedef struct r_samr_chgpasswd_user_info
} SAMR_R_CHGPASSWD_USER;
/* SAMR_Q_CHGPASSWD3 */
-typedef struct q_samr_chgpasswd3
+typedef struct q_samr_chgpasswd_user3
{
uint32 ptr_0;
@@ -1841,7 +1865,12 @@ typedef struct q_samr_chgpasswd3
SAMR_ENC_PASSWD password3;
-} SAMR_Q_CHGPASSWD3;
+} SAMR_Q_CHGPASSWD_USER3;
+
+#define REJECT_REASON_OTHER 0x00000000
+#define REJECT_REASON_TOO_SHORT 0x00000001
+#define REJECT_REASON_IN_HISTORY 0x00000002
+#define REJECT_REASON_NOT_COMPLEX 0x00000005
/* SAMR_CHANGE_REJECT */
typedef struct samr_change_reject
@@ -1853,13 +1882,15 @@ typedef struct samr_change_reject
} SAMR_CHANGE_REJECT;
/* SAMR_R_CHGPASSWD3 */
-typedef struct r_samr_chgpasswd3
+typedef struct r_samr_chgpasswd_user3
{
- SAM_UNK_INFO_1 info;
- SAMR_CHANGE_REJECT reject;
+ uint32 ptr_info;
+ uint32 ptr_reject;
+ SAM_UNK_INFO_1 *info;
+ SAMR_CHANGE_REJECT *reject;
NTSTATUS status; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */
-} SAMR_R_CHGPASSWD3;
+} SAMR_R_CHGPASSWD_USER3;
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index 3b88f76588b..681dcd73d42 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -4,7 +4,7 @@
Copyright (C) Andrew Tridgell 1992-2000,
Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
Copyright (C) Jean Francois Micouleau 1998-2000.
- Copyright (C) Gerald Carter 2001-2005.
+ Copyright (C) Gerald Carter 2001-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
@@ -107,8 +107,19 @@
#define SPOOLSS_DELETEPRINTERDATAEX 0x51
#define SPOOLSS_DELETEPRINTERKEY 0x52
#define SPOOLSS_DELETEPRINTERDRIVEREX 0x54
+#define SPOOLSS_XCVDATAPORT 0x58
#define SPOOLSS_ADDPRINTERDRIVEREX 0x59
+/*
+ * Special strings for the OpenPrinter() call. See the MSDN DDK
+ * docs on the XcvDataPort() for more details.
+ */
+
+#define SPL_LOCAL_PORT "Local Port"
+#define SPL_TCPIP_PORT "Standard TCP/IP Port"
+#define SPL_XCV_MONITOR_LOCALMON ",XcvMonitor Local Port"
+#define SPL_XCV_MONITOR_TCPMON ",XcvMonitor Standard TCP/IP Port"
+
#define PRINTER_CONTROL_UNPAUSE 0x00000000
#define PRINTER_CONTROL_PAUSE 0x00000001
@@ -799,7 +810,7 @@ typedef struct spool_notify_info_data
}
notify_data;
uint32 size;
- BOOL enc_type;
+ uint32 enc_type;
} SPOOL_NOTIFY_INFO_DATA;
typedef struct spool_notify_info
@@ -2161,6 +2172,46 @@ typedef struct spool_r_getprintprocessordirectory
}
SPOOL_R_GETPRINTPROCESSORDIRECTORY;
+/**************************************/
+
+#define MAX_PORTNAME 64
+#define MAX_NETWORK_NAME 49
+#define MAX_SNMP_COMM_NAME 33
+#define MAX_QUEUE_NAME 33
+#define MAX_IPADDR_STRING 17
+
+typedef struct {
+ uint16 portname[MAX_PORTNAME];
+ uint32 version;
+ uint32 protocol;
+ uint32 size;
+ uint32 reserved;
+ uint16 hostaddress[MAX_NETWORK_NAME];
+ uint16 snmpcommunity[MAX_SNMP_COMM_NAME];
+ uint32 dblspool;
+ uint16 queue[MAX_QUEUE_NAME];
+ uint16 ipaddress[MAX_IPADDR_STRING];
+ uint32 port;
+ uint32 snmpenabled;
+ uint32 snmpdevindex;
+} SPOOL_PORT_DATA_1;
+
+typedef struct {
+ POLICY_HND handle;
+ UNISTR2 dataname;
+ RPC_BUFFER indata;
+ uint32 indata_len;
+ uint32 offered;
+ uint32 unknown;
+} SPOOL_Q_XCVDATAPORT;
+
+typedef struct {
+ RPC_BUFFER outdata;
+ uint32 needed;
+ uint32 unknown;
+ WERROR status;
+} SPOOL_R_XCVDATAPORT;
+
#define PRINTER_DRIVER_VERSION 2
#define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86"
diff --git a/source/include/secrets.h b/source/include/secrets.h
index f2d1afd96b3..610a14b52be 100644
--- a/source/include/secrets.h
+++ b/source/include/secrets.h
@@ -75,10 +75,10 @@ typedef struct trusted_dom_pass {
* trusted domain entry/entries returned by secrets_get_trusted_domains
* (used in _lsa_enum_trust_dom call)
*/
-typedef struct trustdom {
- smb_ucs2_t *name;
+struct trustdom_info {
+ char *name;
DOM_SID sid;
-} TRUSTDOM;
+};
/*
* Format of an OpenAFS keyfile
diff --git a/source/include/smb.h b/source/include/smb.h
index d28b9f6cdcf..f6ee4297025 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -224,27 +224,29 @@ typedef struct nttime_info {
/* Allowable account control bits */
-#define ACB_DISABLED 0x0001 /* 1 = User account disabled */
-#define ACB_HOMDIRREQ 0x0002 /* 1 = Home directory required */
-#define ACB_PWNOTREQ 0x0004 /* 1 = User password not required */
-#define ACB_TEMPDUP 0x0008 /* 1 = Temporary duplicate account */
-#define ACB_NORMAL 0x0010 /* 1 = Normal user account */
-#define ACB_MNS 0x0020 /* 1 = MNS logon user account */
-#define ACB_DOMTRUST 0x0040 /* 1 = Interdomain trust account */
-#define ACB_WSTRUST 0x0080 /* 1 = Workstation trust account */
-#define ACB_SVRTRUST 0x0100 /* 1 = Server trust account (BDC) */
-#define ACB_PWNOEXP 0x0200 /* 1 = User password does not expire */
-#define ACB_AUTOLOCK 0x0400 /* 1 = Account auto locked */
-
-#define MAX_HOURS_LEN 32
-
-/*
- * window during which we must talk to the PDC to avoid
- * sam sync delays; expressed in seconds (15 minutes is the
- * default period for SAM replication under Windows NT 4.0
- */
-#define SAM_SYNC_WINDOW 900
+#define ACB_DISABLED 0x00000001 /* 1 = User account disabled */
+#define ACB_HOMDIRREQ 0x00000002 /* 1 = Home directory required */
+#define ACB_PWNOTREQ 0x00000004 /* 1 = User password not required */
+#define ACB_TEMPDUP 0x00000008 /* 1 = Temporary duplicate account */
+#define ACB_NORMAL 0x00000010 /* 1 = Normal user account */
+#define ACB_MNS 0x00000020 /* 1 = MNS logon user account */
+#define ACB_DOMTRUST 0x00000040 /* 1 = Interdomain trust account */
+#define ACB_WSTRUST 0x00000080 /* 1 = Workstation trust account */
+#define ACB_SVRTRUST 0x00000100 /* 1 = Server trust account (BDC) */
+#define ACB_PWNOEXP 0x00000200 /* 1 = User password does not expire */
+#define ACB_AUTOLOCK 0x00000400 /* 1 = Account auto locked */
+
+/* only valid for > Windows 2000 */
+#define ACB_ENC_TXT_PWD_ALLOWED 0x00000800 /* 1 = Text password encryped */
+#define ACB_SMARTCARD_REQUIRED 0x00001000 /* 1 = Smart Card required */
+#define ACB_TRUSTED_FOR_DELEGATION 0x00002000 /* 1 = Trusted for Delegation */
+#define ACB_NOT_DELEGATED 0x00004000 /* 1 = Not delegated */
+#define ACB_USE_DES_KEY_ONLY 0x00008000 /* 1 = Use DES key only */
+#define ACB_DONT_REQUIRE_PREAUTH 0x00010000 /* 1 = Preauth not required */
+#define ACB_PWEXPIRED 0x00020000 /* 1 = Password is expired */
+#define ACB_NO_AUTH_DATA_REQD 0x00080000 /* 1 = No authorization data required */
+#define MAX_HOURS_LEN 32
#ifndef MAXSUBAUTHS
#define MAXSUBAUTHS 15 /* max sub authorities in a SID */
@@ -253,8 +255,7 @@ typedef struct nttime_info {
#define SID_MAX_SIZE ((size_t)(8+(MAXSUBAUTHS*4)))
/* SID Types */
-enum SID_NAME_USE
-{
+enum SID_NAME_USE {
SID_NAME_USE_NONE = 0,
SID_NAME_USER = 1, /* user */
SID_NAME_DOM_GRP, /* domain group */
@@ -267,26 +268,46 @@ enum SID_NAME_USE
SID_NAME_COMPUTER /* sid for a computer */
};
+#define LOOKUP_NAME_ISOLATED 1 /* Look up unqualified names */
+#define LOOKUP_NAME_REMOTE 2 /* Ask others */
+#define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE)
+
+#define LOOKUP_NAME_GROUP 4 /* This is a NASTY hack for valid users = @foo
+ * where foo also exists in as user. */
+
/**
* @brief Security Identifier
*
* @sa http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/accctrl_38yn.asp
**/
-typedef struct sid_info
-{
- uint8 sid_rev_num; /**< SID revision number */
- uint8 num_auths; /**< Number of sub-authorities */
- uint8 id_auth[6]; /**< Identifier Authority */
- /*
- * Pointer to sub-authorities.
- *
- * @note The values in these uint32's are in *native* byteorder, not
- * neccessarily little-endian...... JRA.
- */
- uint32 sub_auths[MAXSUBAUTHS];
-
+typedef struct sid_info {
+ uint8 sid_rev_num; /**< SID revision number */
+ uint8 num_auths; /**< Number of sub-authorities */
+ uint8 id_auth[6]; /**< Identifier Authority */
+ /*
+ * Pointer to sub-authorities.
+ *
+ * @note The values in these uint32's are in *native* byteorder, not
+ * neccessarily little-endian...... JRA.
+ */
+ uint32 sub_auths[MAXSUBAUTHS];
} DOM_SID;
+struct lsa_dom_info {
+ BOOL valid;
+ DOM_SID sid;
+ const char *name;
+ int num_idxs;
+ int *idxs;
+};
+
+struct lsa_name_info {
+ uint32 rid;
+ enum SID_NAME_USE type;
+ const char *name;
+ int dom_idx;
+};
+
/* Some well-known SIDs */
extern const DOM_SID global_sid_World_Domain;
extern const DOM_SID global_sid_World;
@@ -309,6 +330,8 @@ extern const DOM_SID global_sid_Builtin_Server_Operators;
extern const DOM_SID global_sid_Builtin_Print_Operators;
extern const DOM_SID global_sid_Builtin_Backup_Operators;
extern const DOM_SID global_sid_Builtin_Replicator;
+extern const DOM_SID global_sid_Unix_Users;
+extern const DOM_SID global_sid_Unix_Groups;
/*
* The complete list of SIDS belonging to this user.
@@ -323,59 +346,22 @@ extern const DOM_SID global_sid_Builtin_Replicator;
#define PRIMARY_USER_SID_INDEX 0
#define PRIMARY_GROUP_SID_INDEX 1
-typedef struct _nt_user_token {
+typedef struct nt_user_token {
size_t num_sids;
DOM_SID *user_sids;
SE_PRIV privileges;
} NT_USER_TOKEN;
-/*** query a local group, get a list of these: shows who is in that group ***/
-
-/* local group member info */
-typedef struct local_grp_member_info
-{
- DOM_SID sid ; /* matches with name */
- uint8 sid_use; /* usr=1 grp=2 dom=3 alias=4 wkng=5 del=6 inv=7 unk=8 */
- fstring name ; /* matches with sid: must be of the form "DOMAIN\account" */
-
-} LOCAL_GRP_MEMBER;
-
-/* enumerate these to get list of local groups */
-
-/* local group info */
-typedef struct local_grp_info
-{
- fstring name;
- fstring comment;
-
-} LOCAL_GRP;
-
-/*** enumerate these to get list of domain groups ***/
-
-/* domain group member info */
-typedef struct domain_grp_info
-{
- fstring name;
- fstring comment;
- uint32 rid; /* group rid */
- uint8 attr; /* attributes forced to be set to 0x7: SE_GROUP_xxx */
-
-} DOMAIN_GRP;
-
-/*** query a domain group, get a list of these: shows who is in that group ***/
-
-/* domain group info */
-typedef struct domain_grp_member_info
-{
- fstring name;
- uint8 attr; /* attributes forced to be set to 0x7: SE_GROUP_xxx */
-
-} DOMAIN_GRP_MEMBER;
+typedef struct _unix_token {
+ uid_t uid;
+ gid_t gid;
+ int ngroups;
+ gid_t *groups;
+} UNIX_USER_TOKEN;
/* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */
-typedef struct time_info
-{
- uint32 time;
+typedef struct time_info {
+ uint32 time;
} UTIME;
/* Structure used when SMBwritebmpx is active */
@@ -389,17 +375,15 @@ typedef struct {
BOOL wr_discard; /* discard all further data */
} write_bmpx_struct;
-typedef struct write_cache
-{
- SMB_OFF_T file_size;
- SMB_OFF_T offset;
- size_t alloc_size;
- size_t data_size;
- char *data;
+typedef struct write_cache {
+ SMB_OFF_T file_size;
+ SMB_OFF_T offset;
+ size_t alloc_size;
+ size_t data_size;
+ char *data;
} write_cache;
-typedef struct
-{
+typedef struct {
smb_ucs2_t *origname;
smb_ucs2_t *filename;
SMB_STRUCT_STAT *statinfo;
@@ -481,31 +465,57 @@ typedef struct data_blob_ {
* Used in NT change-notify code.
*/
-typedef struct
-{
+typedef struct {
time_t modify_time;
time_t status_time;
} dir_status_struct;
-struct vuid_cache_entry
-{
+struct vuid_cache_entry {
uint16 vuid;
BOOL read_only;
BOOL admin_user;
};
-struct vuid_cache
-{
+struct vuid_cache {
unsigned int entries;
struct vuid_cache_entry array[VUID_CACHE_SIZE];
};
-typedef struct
-{
+typedef struct {
char *name;
BOOL is_wild;
} name_compare_entry;
+struct trans_state {
+ struct trans_state *next, *prev;
+ uint16 vuid;
+ uint16 mid;
+
+ uint32 max_param_return;
+ uint32 max_data_return;
+ uint32 max_setup_return;
+
+ uint8 cmd; /* SMBtrans or SMBtrans2 */
+
+ fstring name; /* for trans requests */
+ uint16 call; /* for trans2 and nttrans requests */
+
+ BOOL close_on_completion;
+ BOOL one_way;
+
+ unsigned int setup_count;
+ uint16 *setup;
+
+ size_t received_data;
+ size_t received_param;
+
+ size_t total_param;
+ char *param;
+
+ size_t total_data;
+ char *data;
+};
+
/* Include VFS stuff */
#include "smb_acls.h"
@@ -521,8 +531,7 @@ struct dfree_cached_info {
struct dptr_struct;
-typedef struct connection_struct
-{
+typedef struct connection_struct {
struct connection_struct *next, *prev;
TALLOC_CTX *mem_ctx;
unsigned cnum; /* an index passed over the wire */
@@ -558,6 +567,7 @@ typedef struct connection_struct
NT_USER_TOKEN *nt_user_token;
time_t lastused;
+ time_t lastused_count;
BOOL used;
int num_files_open;
unsigned int num_smb_operations; /* Count of smb operations on this tree. */
@@ -571,16 +581,13 @@ typedef struct connection_struct
name_compare_entry *veto_oplock_list; /* Per-share list of files to refuse oplocks on. */
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;
} connection_struct;
-struct current_user
-{
+struct current_user {
connection_struct *conn;
uint16 vuid;
- uid_t uid;
- gid_t gid;
- int ngroups;
- gid_t *groups;
+ UNIX_USER_TOKEN ut;
NT_USER_TOKEN *nt_user_token;
};
@@ -601,42 +608,37 @@ typedef struct {
enum {LPQ_QUEUED=0,LPQ_PAUSED,LPQ_SPOOLING,LPQ_PRINTING,LPQ_ERROR,LPQ_DELETING,
LPQ_OFFLINE,LPQ_PAPEROUT,LPQ_PRINTED,LPQ_DELETED,LPQ_BLOCKED,LPQ_USER_INTERVENTION};
-typedef struct _print_queue_struct
-{
- int job; /* normally the UNIX jobid -- see note in
- printing.c:traverse_fn_delete() */
- int size;
- int page_count;
- int status;
- int priority;
- time_t time;
- fstring fs_user;
- fstring fs_file;
+typedef struct _print_queue_struct {
+ int job; /* normally the UNIX jobid -- see note in
+ printing.c:traverse_fn_delete() */
+ int size;
+ int page_count;
+ int status;
+ int priority;
+ time_t time;
+ fstring fs_user;
+ fstring fs_file;
} print_queue_struct;
enum {LPSTAT_OK, LPSTAT_STOPPED, LPSTAT_ERROR};
-typedef struct
-{
- fstring message;
- int qcount;
- int status;
+typedef struct {
+ fstring message;
+ int qcount;
+ int status;
} print_status_struct;
/* used for server information: client, nameserv and ipc */
-struct server_info_struct
-{
- fstring name;
- uint32 type;
- fstring comment;
- fstring domain; /* used ONLY in ipc.c NOT namework.c */
- BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
+struct server_info_struct {
+ fstring name;
+ uint32 type;
+ fstring comment;
+ fstring domain; /* used ONLY in ipc.c NOT namework.c */
+ BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
};
-
/* used for network interfaces */
-struct interface
-{
+struct interface {
struct interface *next, *prev;
struct in_addr ip;
struct in_addr bcast;
@@ -695,11 +697,38 @@ struct share_mode_lock {
SMB_INO_T ino;
int num_share_modes;
struct share_mode_entry *share_modes;
+ UNIX_USER_TOKEN *delete_token;
BOOL delete_on_close;
+ BOOL initial_delete_on_close;
BOOL fresh;
BOOL modified;
};
+/*
+ * Internal structure of locking.tdb share mode db.
+ * Used by locking.c and libsmbsharemodes.c
+ */
+
+struct locking_data {
+ union {
+ 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. */
+ } s;
+ struct share_mode_entry dummy; /* Needed for alignment. */
+ } u;
+ /* The following four entries are implicit
+ struct share_mode_entry modes[num_share_mode_entries];
+ char unix_token[delete_token_size] (divisible by 4).
+ char share_name[];
+ char file_name[];
+ */
+};
+
#define NT_HASH_LEN 16
#define LM_HASH_LEN 16
@@ -768,24 +797,12 @@ typedef enum {
P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
} parm_class;
-/* passed to br lock code */
-enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_LOCK};
-
struct enum_list {
int value;
const char *name;
};
-#define BRLOCK_FN_CAST() \
- void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
- enum brl_type lock_type, \
- 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, \
- br_off start, br_off size)
-struct parm_struct
-{
+struct parm_struct {
const char *label;
parm_type type;
parm_class p_class;
@@ -802,11 +819,6 @@ struct parm_struct
} def;
};
-struct bitmap {
- uint32 *b;
- unsigned int n;
-};
-
/* The following flags are used in SWAT */
#define FLAG_BASIC 0x0001 /* Display only in BASIC view */
#define FLAG_SHARE 0x0002 /* file sharing options */
@@ -819,11 +831,48 @@ struct bitmap {
#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)
+
+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
@@ -1412,8 +1461,7 @@ enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANM
enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER,SEC_DOMAIN,SEC_ADS};
/* server roles */
-enum server_types
-{
+enum server_types {
ROLE_STANDALONE,
ROLE_DOMAIN_MEMBER,
ROLE_DOMAIN_BDC,
@@ -1445,6 +1493,8 @@ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
/* case handling */
enum case_handling {CASE_LOWER,CASE_UPPER};
+/* ACL compatibility */
+enum acl_compatibility {ACL_COMPAT_AUTO, ACL_COMPAT_WINNT, ACL_COMPAT_WIN2K};
/*
* Global value meaing that the smb_uid field should be
* ingored (in share level security and protocol level == CORE)
@@ -1568,7 +1618,10 @@ minimum length == 18.
* Capabilities abstracted for different systems.
*/
-#define KERNEL_OPLOCK_CAPABILITY 0x1
+enum smbd_capability {
+ KERNEL_OPLOCK_CAPABILITY,
+ DMAPI_ACCESS_CAPABILITY
+};
/* if a kernel does support oplocks then a structure of the following
typee is used to describe how to interact with the kernel */
@@ -1588,10 +1641,9 @@ struct cnotify_fns {
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
@@ -1625,7 +1677,6 @@ struct pwd_info {
BOOL cleartext;
fstring password;
-
};
typedef struct user_struct {
@@ -1660,7 +1711,6 @@ typedef struct user_struct {
} user_struct;
-
struct unix_error_map {
int unix_error;
int dos_class;
@@ -1783,4 +1833,23 @@ typedef struct uuid_flat {
/* map readonly options */
enum mapreadonly_options {MAP_READONLY_NO, MAP_READONLY_YES, MAP_READONLY_PERMISSIONS};
+/* usershare error codes. */
+enum usershare_err {
+ USERSHARE_OK=0,
+ USERSHARE_MALFORMED_FILE,
+ USERSHARE_BAD_VERSION,
+ USERSHARE_MALFORMED_PATH,
+ USERSHARE_MALFORMED_COMMENT_DEF,
+ USERSHARE_MALFORMED_ACL_DEF,
+ USERSHARE_ACL_ERR,
+ USERSHARE_PATH_NOT_ABSOLUTE,
+ USERSHARE_PATH_IS_DENIED,
+ USERSHARE_PATH_NOT_ALLOWED,
+ USERSHARE_PATH_NOT_DIRECTORY,
+ USERSHARE_POSIX_ERR
+};
+
+/* Different reasons for closing a file. */
+enum file_close_type {NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE};
+
#endif /* _SMB_H */
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index 35ea792ebea..554dbbc0878 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -24,14 +24,6 @@
#ifndef _SMB_MACROS_H
#define _SMB_MACROS_H
-/* no ops to help reduce the diff between the current 3.0 and release branch */
-
-#define toupper_ascii(x) toupper(x)
-#define tolower_ascii(x) tolower(x)
-#define isupper_ascii(x) isupper(x)
-#define islower_ascii(x) islower(x)
-
-
/* Misc bit macros */
#define BOOLSTR(b) ((b) ? "Yes" : "No")
#define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0)
@@ -84,6 +76,10 @@
(DEBUG(0,("PANIC: assert failed at %s(%d)\n", __FILE__, __LINE__))))
#endif
+#define SMB_WARN(condition, message) \
+ ((condition) ? (void)0 : \
+ DEBUG(0, ("WARNING: %s: %s\n", #condition, message)))
+
#define SMB_ASSERT_ARRAY(a,n) SMB_ASSERT((sizeof(a)/sizeof((a)[0])) >= (n))
/* these are useful macros for checking validity of handles */
@@ -279,8 +275,10 @@ copy an IP address from one buffer to another
*****************************************************************************/
#define SMB_MALLOC_ARRAY(type,count) (type *)malloc_array(sizeof(type),(count))
-#define SMB_REALLOC(p,s) Realloc((p),(s))
-#define SMB_REALLOC_ARRAY(p,type,count) (type *)realloc_array((p),sizeof(type),(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 */
+#define SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(p,type,count) (type *)realloc_array((p),sizeof(type),(count),False) /* Never frees p on error or s == 0 */
#define SMB_CALLOC_ARRAY(type,count) (type *)calloc_array(sizeof(type),(count))
#define SMB_XMALLOC_P(type) (type *)smb_xmalloc_array(sizeof(type),1)
#define SMB_XMALLOC_ARRAY(type,count) (type *)smb_xmalloc_array(sizeof(type),(count))
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index bea1a6d84a3..6cfde13f4a9 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -131,8 +131,7 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx,
struct smbldap_state **smbldap_state);
const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key );
-const char** get_attr_list( ATTRIB_MAP_ENTRY table[] );
-void free_attr_list( const char **list );
+const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] );
void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value);
void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
LDAPMod ***mods,
@@ -196,18 +195,23 @@ struct ldapsam_privates {
};
/* Functions shared between pdb_ldap.c and pdb_nds.c. */
-NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context,
- PDB_METHODS **pdb_method,
- const char *location);
+NTSTATUS pdb_init_ldapsam_compat( struct pdb_methods **pdb_method, const char *location);
void private_data_free_fn(void **result);
int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
const char *user,
LDAPMessage ** result,
const char **attr);
-NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context,
- PDB_METHODS **pdb_method,
- const char *location);
-const char** get_userattr_list( int schema_ver );
+NTSTATUS pdb_init_ldapsam( struct pdb_methods **pdb_method, const char *location);
+const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver );
+
+char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
+ const char *attribute,
+ TALLOC_CTX *mem_ctx);
+void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result);
+void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod);
+const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
+ LDAPMessage *entry);
+
#endif /* HAVE_LDAP */
diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h
index ed6fce9a6d6..f68a1e240f2 100644
--- a/source/include/smbprofile.h
+++ b/source/include/smbprofile.h
@@ -110,6 +110,8 @@ struct profile_stats {
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;
diff --git a/source/include/trans2.h b/source/include/trans2.h
index 1d5dfe3678e..92c5a2e963f 100644
--- a/source/include/trans2.h
+++ b/source/include/trans2.h
@@ -441,7 +441,9 @@ Offset Size Name
#define SMB_QUERY_ATTR_FLAGS 0x206 /* chflags, chattr */
#define SMB_SET_ATTR_FLAGS 0x206
#define SMB_QUERY_POSIX_PERMISSION 0x207
+/* Only valid for qfileinfo */
#define SMB_QUERY_POSIX_LOCK 0x208
+/* Only valid for setfileinfo */
#define SMB_SET_POSIX_LOCK 0x208
/* Transact 2 Find First levels */
@@ -576,4 +578,28 @@ number of entries sent will be zero.
#define SMB_POSIX_ACL_ENTRY_SIZE 10
#define SMB_POSIX_IGNORE_ACE_ENTRIES 0xFFFF
+
+/* Definition 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)
+ [4 bytes] pid = locking context.
+ [8 bytes] start = unsigned 64 bits.
+ [8 bytes] length = unsigned 64 bits.
+*/
+
+#define POSIX_LOCK_TYPE_OFFSET 0
+#define POSIX_LOCK_FLAGS_OFFSET 2
+#define POSIX_LOCK_PID_OFFSET 4
+#define POSIX_LOCK_START_OFFSET 8
+#define POSIX_LOCK_LEN_OFFSET 16
+#define POSIX_LOCK_DATA_SIZE 24
+
+#define POSIX_LOCK_FLAG_NOWAIT 0
+#define POSIX_LOCK_FLAG_WAIT 1
+
+#define POSIX_LOCK_TYPE_READ 0
+#define POSIX_LOCK_TYPE_WRITE 1
+#define POSIX_LOCK_TYPE_UNLOCK 2
+
#endif
diff --git a/source/include/vfs.h b/source/include/vfs.h
index cde2039d1a1..fb99d824125 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -59,9 +59,10 @@
/* Changed to version 12 to add mask and attributes to opendir(). JRA
Also include aio calls. JRA. */
/* Changed to version 13 as the internal structure of files_struct has changed. JRA */
-/* Changed to version 14 as the we had to change DIR to SMB_STRUCT_DIR. JRA */
-/* Changed to version 15 as the we added the statvfs call. JRA */
-#define SMB_VFS_INTERFACE_VERSION 15
+/* 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
/* to bug old modules which are trying to compile with the old functions */
@@ -141,6 +142,7 @@ typedef enum _vfs_op_type {
SMB_VFS_OP_UTIME,
SMB_VFS_OP_FTRUNCATE,
SMB_VFS_OP_LOCK,
+ SMB_VFS_OP_GETLOCK,
SMB_VFS_OP_SYMLINK,
SMB_VFS_OP_READLINK,
SMB_VFS_OP_LINK,
@@ -262,6 +264,7 @@ struct vfs_ops {
int (*utime)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct utimbuf *times);
int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset);
BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
+ 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);
@@ -375,6 +378,7 @@ struct vfs_ops {
struct vfs_handle_struct *utime;
struct vfs_handle_struct *ftruncate;
struct vfs_handle_struct *lock;
+ struct vfs_handle_struct *getlock;
struct vfs_handle_struct *symlink;
struct vfs_handle_struct *readlink;
struct vfs_handle_struct *link;
diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h
index 33810c301f9..e08b386a6ac 100644
--- a/source/include/vfs_macros.h
+++ b/source/include/vfs_macros.h
@@ -70,6 +70,7 @@
#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (conn), (path), (times)))
#define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
+#define SMB_VFS_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)))
@@ -181,6 +182,7 @@
#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (conn), (path), (times)))
#define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
+#define SMB_VFS_OPAQUE_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)))
@@ -293,6 +295,7 @@
#define SMB_VFS_NEXT_UTIME(handle, conn, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (conn), (path), (times)))
#define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset)))
#define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
+#define SMB_VFS_NEXT_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)))
diff --git a/source/iniparser/AUTHORS b/source/iniparser/AUTHORS
new file mode 100644
index 00000000000..86f842c50df
--- /dev/null
+++ b/source/iniparser/AUTHORS
@@ -0,0 +1 @@
+Nicolas Devillard <ndevilla@free.fr>
diff --git a/source/iniparser/INSTALL b/source/iniparser/INSTALL
new file mode 100644
index 00000000000..0d319b2670f
--- /dev/null
+++ b/source/iniparser/INSTALL
@@ -0,0 +1,12 @@
+
+iniParser installation instructions
+-----------------------------------
+
+1. Modify the Makefile to suit your environment.
+2. Type 'make' to make the library.
+3. Type 'make check' to make the test program.
+4. Type 'test/iniexample' to launch the test program.
+
+Enjoy!
+N. Devillard
+Tue Jan 14 11:52:03 CET 2003
diff --git a/source/iniparser/LICENSE b/source/iniparser/LICENSE
new file mode 100644
index 00000000000..2eae4083373
--- /dev/null
+++ b/source/iniparser/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2000 by Nicolas Devillard.
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/source/iniparser/Makefile b/source/iniparser/Makefile
new file mode 100644
index 00000000000..59793dbee19
--- /dev/null
+++ b/source/iniparser/Makefile
@@ -0,0 +1,55 @@
+#
+# iniparser Makefile
+#
+
+# Compiler settings
+CC = gcc
+CFLAGS = -O3
+
+# Ar settings to build the library
+AR = ar
+ARFLAGS = rcv
+
+# Set RANLIB to ranlib on systems that require it (Sun OS < 4, Mac OSX)
+# RANLIB = ranlib
+RANLIB = true
+
+RM = rm -f
+
+
+# Implicit rules
+
+SUFFIXES = .o .c .h .a .so .sl
+
+COMPILE.c=$(CC) $(CFLAGS) -c
+.c.o:
+ @(echo "compiling $< ...")
+ @($(COMPILE.c) -o $@ $<)
+
+
+SRCS = src/iniparser.c \
+ src/dictionary.c \
+ src/strlib.c
+
+OBJS = $(SRCS:.c=.o)
+
+
+default: libiniparser.a
+
+libiniparser.a: $(OBJS)
+ @($(AR) $(ARFLAGS) libiniparser.a $(OBJS))
+ @($(RANLIB) libiniparser.a)
+
+clean:
+ $(RM) $(OBJS)
+
+veryclean:
+ $(RM) $(OBJS) libiniparser.a
+ rm -rf ./html ; mkdir html
+ cd test ; $(MAKE) veryclean
+
+docs:
+ @(cd doc ; $(MAKE))
+
+check:
+ @(cd test ; $(MAKE))
diff --git a/source/iniparser/README b/source/iniparser/README
new file mode 100644
index 00000000000..466d079ba51
--- /dev/null
+++ b/source/iniparser/README
@@ -0,0 +1,11 @@
+
+Welcome to iniParser!
+
+This modules offers parsing of ini files from the C level.
+See a complete documentation in HTML format, from this directory
+open the file html/index.html with any HTML-capable browser.
+
+Enjoy!
+
+N.Devillard
+Thu Nov 17 12:31:42 CET 2005
diff --git a/source/iniparser/html/dir_000000.html b/source/iniparser/html/dir_000000.html
new file mode 100644
index 00000000000..9e4da6fc683
--- /dev/null
+++ b/source/iniparser/html/dir_000000.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+ <meta name="author" content="ndevilla@free.fr">
+ <meta name="keywords" content="ini file, config file, parser, C library">
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
+<title>iniparser 2.x</title>
+</head>
+
+<body text="#000000" bgcolor="#ffffff">
+
+
+
+<!-- Generated by Doxygen 1.4.4 -->
+<div class="nav">
+<a class="el" href="dir_000000.html">src</a></div>
+<h1>src Directory Reference</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Files</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">file &nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html">iniparser.h</a></td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Parser for ini files. <br></td></tr>
+
+<p>
+</table>
+
+</body>
+</html>
diff --git a/source/iniparser/html/dirs.html b/source/iniparser/html/dirs.html
new file mode 100644
index 00000000000..1671bd26b11
--- /dev/null
+++ b/source/iniparser/html/dirs.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <meta name="author" content="ndevilla@free.fr">
+ <meta name="keywords" content="ini file, config file, parser, C library">
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
+<title>iniparser 2.x</title>
+</head>
+
+<body text="#000000" bgcolor="#ffffff">
+
+
+
+<!-- Generated by Doxygen 1.4.4 -->
+<h1>iniparser Directories</h1>This directory hierarchy is sorted roughly, but not completely, alphabetically:<ul>
+<li><a class="el" href="dir_000000.html">src</a>
+</ul>
+
+</body>
+</html>
diff --git a/source/iniparser/html/doxygen.css b/source/iniparser/html/doxygen.css
new file mode 100644
index 00000000000..decae9e3941
--- /dev/null
+++ b/source/iniparser/html/doxygen.css
@@ -0,0 +1,309 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+ font-size: 90%;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
+}
+CAPTION { font-weight: bold }
+DIV.qindex {
+ width: 100%;
+ background-color: #eeeeff;
+ border: 1px solid #b0b0b0;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.nav {
+ width: 100%;
+ background-color: #eeeeff;
+ border: 1px solid #b0b0b0;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #eeeeff;
+ border: 1px solid #b0b0b0;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddff;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { font-weight: normal; color: #0000FF}
+A.codeRef:visited { font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+.fragment {
+ font-family: Fixed, monospace;
+ font-size: 95%;
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+TD.md { background-color: #F4F4FB; font-weight: bold; }
+TD.mdPrefix {
+ background-color: #F4F4FB;
+ color: #606060;
+ font-size: 80%;
+}
+TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
+TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #eeeeff;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #eeeeff;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+.mdTable {
+ border: 1px solid #868686;
+ background-color: #F4F4FB;
+}
+.mdRow {
+ padding: 8px 10px;
+}
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.search { color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #eeeeff;
+}
+TD.tiny { font-size: 75%;
+}
+a {
+ color: #252E78;
+}
+a:visited {
+ color: #3D2185;
+}
+.dirtab { padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #b0b0b0;
+}
+TH.dirtab { background: #eeeeff;
+ font-weight: bold;
+}
+HR { height: 1px;
+ border: none;
+ border-top: 1px solid black;
+}
diff --git a/source/iniparser/html/doxygen.png b/source/iniparser/html/doxygen.png
new file mode 100644
index 00000000000..f0a274bbaff
--- /dev/null
+++ b/source/iniparser/html/doxygen.png
Binary files differ
diff --git a/source/iniparser/html/globals_func.html b/source/iniparser/html/globals_func.html
new file mode 100644
index 00000000000..3e398005f57
--- /dev/null
+++ b/source/iniparser/html/globals_func.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+ <meta name="author" content="ndevilla@free.fr">
+ <meta name="keywords" content="ini file, config file, parser, C library">
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
+<title>iniparser 2.x</title>
+</head>
+
+<body text="#000000" bgcolor="#ffffff">
+
+
+
+<!-- Generated by Doxygen 1.4.4 -->
+<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindexHL" href="globals_func.html">Functions</a></div>
+
+<p>
+<ul>
+<li>iniparser_dump()
+: <a class="el" href="iniparser_8h.html#a3">iniparser.h</a><li>iniparser_dump_ini()
+: <a class="el" href="iniparser_8h.html#a2">iniparser.h</a><li>iniparser_find_entry()
+: <a class="el" href="iniparser_8h.html#a11">iniparser.h</a><li>iniparser_freedict()
+: <a class="el" href="iniparser_8h.html#a13">iniparser.h</a><li>iniparser_getboolean()
+: <a class="el" href="iniparser_8h.html#a8">iniparser.h</a><li>iniparser_getdouble()
+: <a class="el" href="iniparser_8h.html#a7">iniparser.h</a><li>iniparser_getint()
+: <a class="el" href="iniparser_8h.html#a6">iniparser.h</a><li>iniparser_getnsec()
+: <a class="el" href="iniparser_8h.html#a0">iniparser.h</a><li>iniparser_getsecname()
+: <a class="el" href="iniparser_8h.html#a1">iniparser.h</a><li>iniparser_getstr()
+: <a class="el" href="iniparser_8h.html#a4">iniparser.h</a><li>iniparser_getstring()
+: <a class="el" href="iniparser_8h.html#a5">iniparser.h</a><li>iniparser_load()
+: <a class="el" href="iniparser_8h.html#a12">iniparser.h</a><li>iniparser_setstr()
+: <a class="el" href="iniparser_8h.html#a9">iniparser.h</a><li>iniparser_unset()
+: <a class="el" href="iniparser_8h.html#a10">iniparser.h</a></ul>
+
+</body>
+</html>
diff --git a/source/iniparser/html/index.html b/source/iniparser/html/index.html
new file mode 100644
index 00000000000..e0ca48b8723
--- /dev/null
+++ b/source/iniparser/html/index.html
@@ -0,0 +1,148 @@
+<html>
+<head>
+ <meta name="author" content="ndevilla@free.fr">
+ <meta name="keywords" content="ini file, config file, parser, C library">
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
+<title>iniparser 2.x</title>
+</head>
+
+<body text="#000000" bgcolor="#ffffff">
+
+
+
+<!-- Generated by Doxygen 1.4.4 -->
+<h1>iniparser documentation </h1>
+<p>
+<h3 align="center">2.x </h3><hr>
+<h2><a class="anchor" name="welcome">
+Introduction</a></h2>
+iniParser is a simple C library offering ini file parsing services. The library is pretty small (less than 1500 lines of C) and robust, and does not depend on any other external library to compile. It is written in ANSI C and should compile anywhere without difficulty.<p>
+<hr>
+<h2><a class="anchor" name="inidef">
+What is an ini file?</a></h2>
+An ini file is an ASCII file describing simple parameters (character strings, integers, floating-point values or booleans) in an explicit format, easy to use and modify for users.<p>
+An ini file is segmented into Sections, declared by the following syntax:<p>
+<div class="fragment"><pre class="fragment"> [Section Name]
+ </pre></div><p>
+i.e. the section name enclosed in square brackets, alone on a line. Sections names are allowed to contain any character but square brackets or linefeeds. Slashes (/) are also reserved for hierarchical sections (see below).<p>
+In any section are zero or more variables, declared with the following syntax:<p>
+<div class="fragment"><pre class="fragment"> Key = value ; comment
+ </pre></div><p>
+The key is any string (possibly containing blanks). The value is any character on the right side of the equal sign. Values can be given enclosed with quotes. If no quotes are present, the value is understood as containing all characters between the first and the last non-blank characters. The following declarations are identical:<p>
+<div class="fragment"><pre class="fragment"> Hello = "this is a long string value" ; comment
+ Hello = this is a long string value ; comment
+ </pre></div><p>
+The semicolon and comment at the end of the line are optional. If there is a comment, it starts from the first character after the semicolon up to the end of the line.<p>
+Comments in an ini file are:<p>
+<ul>
+<li>Lines starting with a hash sign</li><li>Blank lines (only blanks or tabs)</li><li>Comments given on value lines after the semicolon (if present)</li></ul>
+<p>
+<hr>
+<h2><a class="anchor" name="install">
+Compiling/installing the library</a></h2>
+Edit the Makefile to indicate the C compiler you want to use, the options to provide to compile ANSI C, and possibly the options to pass to the <code>ar</code> program on your machine to build a library (.a) from a set of object (.o) files.<p>
+Defaults are set for the gcc compiler and the standard ar library builder.<p>
+Type 'make', that should do it.<p>
+To use the library in your programs, add the following line on top of your module:<p>
+<div class="fragment"><pre class="fragment"><span class="preprocessor"> #include "<a class="code" href="iniparser_8h.html">iniparser.h</a>"</span>
+</pre></div><p>
+And link your program with the iniparser library by adding <code>-liniparser</code>.a to the compile line.<p>
+See the file test/initest.c for an example.<p>
+<hr>
+<h2><a class="anchor" name="reference">
+Library reference</a></h2>
+The library is completely documented in its header file. On-line documentation has been generated and can be consulted here:<p>
+<ul>
+<li><a class="el" href="iniparser_8h.html">iniparser.h</a></li></ul>
+<p>
+<hr>
+<h2><a class="anchor" name="usage">
+Using the parser</a></h2>
+Comments are discarded by the parser. Then sections are identified, and in each section a new entry is created for every keyword found. The keywords are stored with the following syntax:<p>
+<div class="fragment"><pre class="fragment"> [Section]
+ Keyword = value ; comment
+ </pre></div><p>
+is converted to the following key pair:<p>
+<div class="fragment"><pre class="fragment"> ("section:keyword", "value")
+ </pre></div><p>
+This means that if you want to retrieve the value that was stored in the section called <code>Pizza</code>, in the keyword <code>Cheese</code>, you would make a request to the dictionary for <code>"pizza:cheese"</code>. All section and keyword names are converted to lowercase before storage in the structure. The value side is conserved as it has been parsed, though.<p>
+Section names are also stored in the structure. They are stored using as key the section name, and a NULL associated value. They can be queried through <a class="el" href="iniparser_8h.html#a11">iniparser_find_entry()</a>.<p>
+To launch the parser, simply use the function called <a class="el" href="iniparser_8h.html#a12">iniparser_load()</a>, which takes an input file name and returns a newly allocated <em>dictionary</em> structure. This latter object should remain opaque to the user and only accessed through the following accessor functions:<p>
+<ul>
+<li><a class="el" href="iniparser_8h.html#a4">iniparser_getstr()</a></li><li><a class="el" href="iniparser_8h.html#a6">iniparser_getint()</a></li><li><a class="el" href="iniparser_8h.html#a7">iniparser_getdouble()</a></li><li><a class="el" href="iniparser_8h.html#a8">iniparser_getboolean()</a></li></ul>
+<p>
+Finally, discard this structure using <a class="el" href="iniparser_8h.html#a13">iniparser_freedict()</a>.<p>
+All values parsed from the ini file are stored as strings. The getint, getdouble and getboolean accessors are just converting these strings to the requested type on the fly, but you could basically perform this conversion by yourself after having called the getstr accessor.<p>
+Notice that the <a class="el" href="iniparser_8h.html#a8">iniparser_getboolean()</a> function will return an integer (0 or 1), trying to make sense of what was found in the file. Strings starting with "y", "Y", "t", "T" or "1" are considered true values (return 1), strings starting with "n", "N", "f", "F", "0" are considered false (return 0). This allows flexible handling of boolean answers.<p>
+If you want to add extra information into the structure that was not present in the ini file, you can use <a class="el" href="iniparser_8h.html#a9">iniparser_setstr()</a> to insert a string.<p>
+<hr>
+<h2><a class="anchor" name="implementation">
+A word about the implementation</a></h2>
+The dictionary structure is a pretty simple dictionary implementation which might find some uses in other applications. If you are curious, look into the source.<p>
+<hr>
+<h2><a class="anchor" name="hierarchical">
+Hierarchical ini files</a></h2>
+ini files are nice to present informations to the user in a readable format, but lack a very useful feature: the possibility of organizing data in a hierarchical (tree-like) fashion. The following convention can be used to make ini files obtain this second dimension:<p>
+A section depends on another section if it contains its name as a prefix, separated by slashes (/). For example: we have 2 main sections in the ini file. The first one is called <code>Pizza</code> and has two child subsections called <code>Cheese</code> and <code>Ham</code>. The second main section in the ini file is called <code>Wine</code> and has two child subsections called <code>Year</code> and <code>Grape</code>. As a tree, this could appear as:<p>
+<div class="fragment"><pre class="fragment"> |
+ +-- Pizza
+ | +-- Cheese
+ | +-- Ham
+ +-- Wine
+ +--- Year
+ +--- Grape
+ </pre></div><p>
+In an ini file, that would be converted to:<p>
+<div class="fragment"><pre class="fragment"> [Pizza]
+
+ [Pizza/Cheese]
+ Name = Gorgonzola ;
+ Origin = Italy ;
+
+ [Pizza/Ham]
+ Name = Parma ;
+ Origin = Italy ;
+
+ [Wine]
+
+ [Wine/Year]
+ Value = 1998 ;
+
+ [Wine/Grape]
+ Name = Cabernet Sauvignon ;
+ Origin = Chile ;
+ </pre></div><p>
+This proposal is actually more related to the way people write ini files, more than the parser presented here. But it is certainly a useful way of making tree-like data declarations without going through painful formats like XML.<p>
+Accessing the above tree would give something like (error checking removed for clarity sake):<p>
+<div class="fragment"><pre class="fragment"> dictionary * d ;
+
+ d = <a class="code" href="iniparser_8h.html#a12">iniparser_load</a>(<span class="stringliteral">"example.ini"</span>);
+
+ printf(<span class="stringliteral">"cheese name is %s\n"</span>, <a class="code" href="iniparser_8h.html#a4">iniparser_getstr</a>(d, <span class="stringliteral">"pizza/cheese:name"</span>));
+ printf(<span class="stringliteral">"grape name is %s\n"</span>, <a class="code" href="iniparser_8h.html#a4">iniparser_getstr</a>(d, <span class="stringliteral">"wine/grape:name"</span>));
+
+ <a class="code" href="iniparser_8h.html#a13">iniparser_freedict</a>(d);
+</pre></div><p>
+The whole ini file above is represented in the dictionary as the following list of pairs:<p>
+<div class="fragment"><pre class="fragment"> key value
+
+ "pizza" NULL
+ "pizza/cheese" NULL
+ "pizza/cheese:name" "Gorgonzola"
+ "pizza/cheese:origin" "Italy"
+ "pizza/ham" NULL
+ "pizza/ham:name" "Parma"
+ "pizza/ham:origin" "Italy"
+ "wine" NULL
+ "wine/year" NULL
+ "wine/year:value" "1998"
+ "wine/grape" NULL
+ "wine/grape:name" "Cabernet Sauvignon"
+ "wine/grape:origin" "Chile"
+ </pre></div><p>
+<hr>
+<h2><a class="anchor" name="authors">
+Authors</a></h2>
+Nicolas Devillard (ndevilla AT free DOT fr).
+</body>
+</html>
diff --git a/source/iniparser/html/iniparser_8h.html b/source/iniparser/html/iniparser_8h.html
new file mode 100644
index 00000000000..3f0534f31ec
--- /dev/null
+++ b/source/iniparser/html/iniparser_8h.html
@@ -0,0 +1,737 @@
+<html>
+<head>
+ <meta name="author" content="ndevilla@free.fr">
+ <meta name="keywords" content="ini file, config file, parser, C library">
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
+<title>iniparser 2.x</title>
+</head>
+
+<body text="#000000" bgcolor="#ffffff">
+
+
+
+<!-- Generated by Doxygen 1.4.4 -->
+<div class="nav">
+<a class="el" href="dir_000000.html">src</a></div>
+<h1>iniparser.h File Reference</h1>Parser for ini files. <a href="#_details">More...</a>
+<p>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a0">iniparser_getnsec</a> (dictionary *d)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get number of sections in a dictionary. <a href="#a0"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a1">iniparser_getsecname</a> (dictionary *d, int n)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get name for section n in a dictionary. <a href="#a1"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a2">iniparser_dump_ini</a> (dictionary *d, FILE *f)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Save a dictionary to a loadable ini file. <a href="#a2"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a3">iniparser_dump</a> (dictionary *d, FILE *f)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Dump a dictionary to an opened file pointer. <a href="#a3"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a4">iniparser_getstr</a> (dictionary *d, char *key)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the string associated to a key, return NULL if not found. <a href="#a4"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a5">iniparser_getstring</a> (dictionary *d, char *key, char *def)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the string associated to a key. <a href="#a5"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a6">iniparser_getint</a> (dictionary *d, char *key, int notfound)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the string associated to a key, convert to an int. <a href="#a6"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">double&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a7">iniparser_getdouble</a> (dictionary *d, char *key, double notfound)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the string associated to a key, convert to a double. <a href="#a7"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a8">iniparser_getboolean</a> (dictionary *d, char *key, int notfound)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Get the string associated to a key, convert to a boolean. <a href="#a8"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a9">iniparser_setstr</a> (dictionary *ini, char *entry, char *val)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Set an entry in a dictionary. <a href="#a9"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a10">iniparser_unset</a> (dictionary *ini, char *entry)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Delete an entry in a dictionary. <a href="#a10"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a11">iniparser_find_entry</a> (dictionary *ini, char *entry)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Finds out if a given entry exists in a dictionary. <a href="#a11"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">dictionary *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a12">iniparser_load</a> (char *ininame)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Parse an ini file and return an allocated dictionary object. <a href="#a12"></a><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="iniparser_8h.html#a13">iniparser_freedict</a> (dictionary *d)</td></tr>
+
+<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">Free all memory associated to an ini dictionary. <a href="#a13"></a><br></td></tr>
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Parser for ini files.
+<p>
+<dl compact><dt><b>Author:</b></dt><dd>N. Devillard </dd></dl>
+<dl compact><dt><b>Date:</b></dt><dd>Mar 2000 </dd></dl>
+<dl compact><dt><b>Version:</b></dt><dd><dl compact><dt><b>Revision</b></dt><dd>1.20 </dd></dl>
+</dd></dl>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="a3"></a><!-- doxytag: member="iniparser.h::iniparser_dump" ref="a3" args="(dictionary *d, FILE *f)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">void iniparser_dump </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>FILE *&nbsp;</td>
+ <td class="mdname" nowrap> <em>f</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Dump a dictionary to an opened file pointer.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to dump. </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>f</em>&nbsp;</td><td>Opened file pointer to dump to. </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>void</dd></dl>
+This function prints out the contents of a dictionary, one element by line, onto the provided file pointer. It is OK to specify <code>stderr</code> or <code>stdout</code> as output files. This function is meant for debugging purposes mostly. </td>
+ </tr>
+</table>
+<a class="anchor" name="a2"></a><!-- doxytag: member="iniparser.h::iniparser_dump_ini" ref="a2" args="(dictionary *d, FILE *f)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">void iniparser_dump_ini </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>FILE *&nbsp;</td>
+ <td class="mdname" nowrap> <em>f</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Save a dictionary to a loadable ini file.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to dump </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>f</em>&nbsp;</td><td>Opened file pointer to dump to </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>void</dd></dl>
+This function dumps a given dictionary into a loadable ini file. It is Ok to specify <code>stderr</code> or <code>stdout</code> as output files. </td>
+ </tr>
+</table>
+<a class="anchor" name="a11"></a><!-- doxytag: member="iniparser.h::iniparser_find_entry" ref="a11" args="(dictionary *ini, char *entry)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">int iniparser_find_entry </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>ini</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>entry</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Finds out if a given entry exists in a dictionary.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ini</em>&nbsp;</td><td>Dictionary to search </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>entry</em>&nbsp;</td><td>Name of the entry to look for </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>integer 1 if entry exists, 0 otherwise</dd></dl>
+Finds out if a given entry exists in the dictionary. Since sections are stored as keys with NULL associated values, this is the only way of querying for the presence of sections in a dictionary. </td>
+ </tr>
+</table>
+<a class="anchor" name="a13"></a><!-- doxytag: member="iniparser.h::iniparser_freedict" ref="a13" args="(dictionary *d)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">void iniparser_freedict </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap> <em>d</em> </td>
+ <td class="md" valign="top">&nbsp;)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Free all memory associated to an ini dictionary.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to free </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>void</dd></dl>
+Free all memory associated to an ini dictionary. It is mandatory to call this function before the dictionary object gets out of the current context. </td>
+ </tr>
+</table>
+<a class="anchor" name="a8"></a><!-- doxytag: member="iniparser.h::iniparser_getboolean" ref="a8" args="(dictionary *d, char *key, int notfound)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">int iniparser_getboolean </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap> <em>notfound</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get the string associated to a key, convert to a boolean.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to search </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>key</em>&nbsp;</td><td>Key string to look for </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>notfound</em>&nbsp;</td><td>Value to return in case of error </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>integer</dd></dl>
+This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned.<p>
+A true boolean is found if one of the following is matched:<p>
+<ul>
+<li>A string starting with 'y'</li><li>A string starting with 'Y'</li><li>A string starting with 't'</li><li>A string starting with 'T'</li><li>A string starting with '1'</li></ul>
+<p>
+A false boolean is found if one of the following is matched:<p>
+<ul>
+<li>A string starting with 'n'</li><li>A string starting with 'N'</li><li>A string starting with 'f'</li><li>A string starting with 'F'</li><li>A string starting with '0'</li></ul>
+<p>
+The notfound value returned if no boolean is identified, does not necessarily have to be 0 or 1. </td>
+ </tr>
+</table>
+<a class="anchor" name="a7"></a><!-- doxytag: member="iniparser.h::iniparser_getdouble" ref="a7" args="(dictionary *d, char *key, double notfound)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">double iniparser_getdouble </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>double&nbsp;</td>
+ <td class="mdname" nowrap> <em>notfound</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get the string associated to a key, convert to a double.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to search </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>key</em>&nbsp;</td><td>Key string to look for </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>notfound</em>&nbsp;</td><td>Value to return in case of error </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>double</dd></dl>
+This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. </td>
+ </tr>
+</table>
+<a class="anchor" name="a6"></a><!-- doxytag: member="iniparser.h::iniparser_getint" ref="a6" args="(dictionary *d, char *key, int notfound)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">int iniparser_getint </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap> <em>notfound</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get the string associated to a key, convert to an int.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to search </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>key</em>&nbsp;</td><td>Key string to look for </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>notfound</em>&nbsp;</td><td>Value to return in case of error </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>integer</dd></dl>
+This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the notfound value is returned. </td>
+ </tr>
+</table>
+<a class="anchor" name="a0"></a><!-- doxytag: member="iniparser.h::iniparser_getnsec" ref="a0" args="(dictionary *d)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">int iniparser_getnsec </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap> <em>d</em> </td>
+ <td class="md" valign="top">&nbsp;)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get number of sections in a dictionary.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to examine </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>int Number of sections found in dictionary</dd></dl>
+This function returns the number of sections found in a dictionary. The test to recognize sections is done on the string stored in the dictionary: a section name is given as "section" whereas a key is stored as "section:key", thus the test looks for entries that do not contain a colon.<p>
+This clearly fails in the case a section name contains a colon, but this should simply be avoided.<p>
+This function returns -1 in case of error. </td>
+ </tr>
+</table>
+<a class="anchor" name="a1"></a><!-- doxytag: member="iniparser.h::iniparser_getsecname" ref="a1" args="(dictionary *d, int n)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">char* iniparser_getsecname </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>int&nbsp;</td>
+ <td class="mdname" nowrap> <em>n</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get name for section n in a dictionary.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to examine </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>n</em>&nbsp;</td><td>Section number (from 0 to nsec-1). </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>Pointer to char string</dd></dl>
+This function locates the n-th section in a dictionary and returns its name as a pointer to a string statically allocated inside the dictionary. Do not free or modify the returned string!<p>
+This function returns NULL in case of error. </td>
+ </tr>
+</table>
+<a class="anchor" name="a4"></a><!-- doxytag: member="iniparser.h::iniparser_getstr" ref="a4" args="(dictionary *d, char *key)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">char* iniparser_getstr </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>key</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get the string associated to a key, return NULL if not found.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to search </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>key</em>&nbsp;</td><td>Key string to look for </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>pointer to statically allocated character string, or NULL.</dd></dl>
+This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, NULL is returned. The returned char pointer is pointing to a string allocated in the dictionary, do not free or modify it.<p>
+This function is only provided for backwards compatibility with previous versions of iniparser. It is recommended to use <a class="el" href="iniparser_8h.html#a5">iniparser_getstring()</a> instead. </td>
+ </tr>
+</table>
+<a class="anchor" name="a5"></a><!-- doxytag: member="iniparser.h::iniparser_getstring" ref="a5" args="(dictionary *d, char *key, char *def)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">char* iniparser_getstring </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>d</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>key</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>def</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Get the string associated to a key.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>d</em>&nbsp;</td><td>Dictionary to search </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>key</em>&nbsp;</td><td>Key string to look for </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>def</em>&nbsp;</td><td>Default value to return if key not found. </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>pointer to statically allocated character string</dd></dl>
+This function queries a dictionary for a key. A key as read from an ini file is given as "section:key". If the key cannot be found, the pointer passed as 'def' is returned. The returned char pointer is pointing to a string allocated in the dictionary, do not free or modify it. </td>
+ </tr>
+</table>
+<a class="anchor" name="a12"></a><!-- doxytag: member="iniparser.h::iniparser_load" ref="a12" args="(char *ininame)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">dictionary* iniparser_load </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">char *&nbsp;</td>
+ <td class="mdname1" valign="top" nowrap> <em>ininame</em> </td>
+ <td class="md" valign="top">&nbsp;)&nbsp;</td>
+ <td class="md" nowrap></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Parse an ini file and return an allocated dictionary object.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ininame</em>&nbsp;</td><td>Name of the ini file to read. </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>Pointer to newly allocated dictionary</dd></dl>
+This is the parser for ini files. This function is called, providing the name of the file to be read. It returns a dictionary object that should not be accessed directly, but through accessor functions instead.<p>
+The returned dictionary must be freed using <a class="el" href="iniparser_8h.html#a13">iniparser_freedict()</a>. </td>
+ </tr>
+</table>
+<a class="anchor" name="a9"></a><!-- doxytag: member="iniparser.h::iniparser_setstr" ref="a9" args="(dictionary *ini, char *entry, char *val)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">int iniparser_setstr </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>ini</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>entry</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>val</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Set an entry in a dictionary.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ini</em>&nbsp;</td><td>Dictionary to modify. </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>entry</em>&nbsp;</td><td>Entry to modify (entry name) </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>val</em>&nbsp;</td><td>New value to associate to the entry. </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>int 0 if Ok, -1 otherwise.</dd></dl>
+If the given entry can be found in the dictionary, it is modified to contain the provided value. If it cannot be found, -1 is returned. It is Ok to set val to NULL. </td>
+ </tr>
+</table>
+<a class="anchor" name="a10"></a><!-- doxytag: member="iniparser.h::iniparser_unset" ref="a10" args="(dictionary *ini, char *entry)" --><p>
+<table class="mdTable" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="mdRow">
+ <table cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td class="md" nowrap valign="top">void iniparser_unset </td>
+ <td class="md" valign="top">(&nbsp;</td>
+ <td class="md" nowrap valign="top">dictionary *&nbsp;</td>
+ <td class="mdname" nowrap> <em>ini</em>, </td>
+ </tr>
+ <tr>
+ <td class="md" nowrap align="right"></td>
+ <td class="md"></td>
+ <td class="md" nowrap>char *&nbsp;</td>
+ <td class="mdname" nowrap> <em>entry</em></td>
+ </tr>
+ <tr>
+ <td class="md"></td>
+ <td class="md">)&nbsp;</td>
+ <td class="md" colspan="2"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<table cellspacing="5" cellpadding="0" border="0">
+ <tr>
+ <td>
+ &nbsp;
+ </td>
+ <td>
+
+<p>
+Delete an entry in a dictionary.
+<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ini</em>&nbsp;</td><td>Dictionary to modify </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>entry</em>&nbsp;</td><td>Entry to delete (entry name) </td></tr>
+ </table>
+</dl>
+<dl compact><dt><b>Returns:</b></dt><dd>void</dd></dl>
+If the given entry can be found, it is deleted from the dictionary. </td>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/source/iniparser/html/iniparser_8main.html b/source/iniparser/html/iniparser_8main.html
new file mode 100644
index 00000000000..38a963bbc7f
--- /dev/null
+++ b/source/iniparser/html/iniparser_8main.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <meta name="author" content="ndevilla@free.fr">
+ <meta name="keywords" content="ini file, config file, parser, C library">
+ <link href="doxygen.css" rel="stylesheet" type="text/css">
+<title>iniparser 2.x</title>
+</head>
+
+<body text="#000000" bgcolor="#ffffff">
+
+
+
+<!-- Generated by Doxygen 1.4.4 -->
+<h1>iniparser.main File Reference</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+</table>
+
+</body>
+</html>
diff --git a/source/iniparser/src/dictionary.c b/source/iniparser/src/dictionary.c
new file mode 100644
index 00000000000..4381b9cb780
--- /dev/null
+++ b/source/iniparser/src/dictionary.c
@@ -0,0 +1,508 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file dictionary.c
+ @author N. Devillard
+ @date Aug 2000
+ @version $Revision: 1.23 $
+ @brief Implements a dictionary for string variables.
+
+ This module implements a simple dictionary object, i.e. a list
+ of string/string associations. This object is useful to store e.g.
+ informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ $Id: dictionary.c,v 1.23 2002/06/17 09:30:46 ndevilla Exp $
+ $Author: ndevilla $
+ $Date: 2002/06/17 09:30:46 $
+ $Revision: 1.23 $
+*/
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include "dictionary.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+/** Maximum value size for integers and doubles. */
+#define MAXVALSZ 1024
+
+/** Minimal allocated number of entries in a dictionary */
+#define DICTMINSZ 128
+
+/** Invalid key token */
+#define DICT_INVALID_KEY ((char*)-1)
+
+
+/*---------------------------------------------------------------------------
+ Private functions
+ ---------------------------------------------------------------------------*/
+
+/* Doubles the allocated size associated to a pointer */
+/* 'size' is the current allocated size. */
+static void * mem_double(void * ptr, int size)
+{
+ void * newptr ;
+
+ newptr = calloc(2*size, 1);
+ memcpy(newptr, ptr, size);
+ free(ptr);
+ return newptr ;
+}
+
+
+/*---------------------------------------------------------------------------
+ Function codes
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Compute the hash key for a string.
+ @param key Character string to use for key.
+ @return 1 unsigned int on at least 32 bits.
+
+ This hash function has been taken from an Article in Dr Dobbs Journal.
+ This is normally a collision-free function, distributing keys evenly.
+ The key is stored anyway in the struct so that collision can be avoided
+ by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+
+unsigned dictionary_hash(char * key)
+{
+ int len ;
+ unsigned hash ;
+ int i ;
+
+ len = strlen(key);
+ for (hash=0, i=0 ; i<len ; i++) {
+ hash += (unsigned)key[i] ;
+ hash += (hash<<10);
+ hash ^= (hash>>6) ;
+ }
+ hash += (hash <<3);
+ hash ^= (hash >>11);
+ hash += (hash <<15);
+ return hash ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Create a new dictionary object.
+ @param size Optional initial size of the dictionary.
+ @return 1 newly allocated dictionary objet.
+
+ This function allocates a new dictionary object of given size and returns
+ it. If you do not know in advance (roughly) the number of entries in the
+ dictionary, give size=0.
+ */
+/*--------------------------------------------------------------------------*/
+
+dictionary * dictionary_new(int size)
+{
+ dictionary * d ;
+
+ /* If no size was specified, allocate space for DICTMINSZ */
+ if (size<DICTMINSZ) size=DICTMINSZ ;
+
+ d = calloc(1, sizeof(dictionary));
+ d->size = size ;
+ d->val = calloc(size, sizeof(char*));
+ d->key = calloc(size, sizeof(char*));
+ d->hash = calloc(size, sizeof(unsigned));
+ return d ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete a dictionary object
+ @param d dictionary object to deallocate.
+ @return void
+
+ Deallocate a dictionary object and all memory associated to it.
+ */
+/*--------------------------------------------------------------------------*/
+
+void dictionary_del(dictionary * d)
+{
+ int i ;
+
+ if (d==NULL) return ;
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]!=NULL)
+ free(d->key[i]);
+ if (d->val[i]!=NULL)
+ free(d->val[i]);
+ }
+ free(d->val);
+ free(d->key);
+ free(d->hash);
+ free(d);
+ return ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value to return if key not found.
+ @return 1 pointer to internally allocated character string.
+
+ This function locates a key in a dictionary and returns a pointer to its
+ value, or the passed 'def' pointer if no such key can be found in
+ dictionary. The returned character pointer points to data internal to the
+ dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * dictionary_get(dictionary * d, char * key, char * def)
+{
+ unsigned hash ;
+ int i ;
+
+ hash = dictionary_hash(key);
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key==NULL)
+ continue ;
+ /* Compare hash */
+ if (hash==d->hash[i]) {
+ /* Compare string, to avoid hash collisions */
+ if (!strcmp(key, d->key[i])) {
+ return d->val[i] ;
+ }
+ }
+ }
+ return def ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary, as a char.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value for the key if not found.
+ @return char
+
+ This function locates a key in a dictionary using dictionary_get,
+ and returns the first char of the found string.
+ */
+/*--------------------------------------------------------------------------*/
+char dictionary_getchar(dictionary * d, char * key, char def)
+{
+ char * v ;
+
+ if ((v=dictionary_get(d,key,DICT_INVALID_KEY))==DICT_INVALID_KEY) {
+ return def ;
+ } else {
+ return v[0] ;
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary, as an int.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value for the key if not found.
+ @return int
+
+ This function locates a key in a dictionary using dictionary_get,
+ and applies atoi on it to return an int. If the value cannot be found
+ in the dictionary, the default is returned.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_getint(dictionary * d, char * key, int def)
+{
+ char * v ;
+
+ if ((v=dictionary_get(d,key,DICT_INVALID_KEY))==DICT_INVALID_KEY) {
+ return def ;
+ } else {
+ return atoi(v);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary, as a double.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value for the key if not found.
+ @return double
+
+ This function locates a key in a dictionary using dictionary_get,
+ and applies atof on it to return a double. If the value cannot be found
+ in the dictionary, the default is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double dictionary_getdouble(dictionary * d, char * key, double def)
+{
+ char * v ;
+
+ if ((v=dictionary_get(d,key,DICT_INVALID_KEY))==DICT_INVALID_KEY) {
+ return def ;
+ } else {
+ return atof(v);
+ }
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a value in a dictionary.
+ @param d dictionary object to modify.
+ @param key Key to modify or add.
+ @param val Value to add.
+ @return void
+
+ If the given key is found in the dictionary, the associated value is
+ replaced by the provided one. If the key cannot be found in the
+ dictionary, it is added to it.
+
+ It is Ok to provide a NULL value for val, but NULL values for the dictionary
+ or the key are considered as errors: the function will return immediately
+ in such a case.
+
+ Notice that if you dictionary_set a variable to NULL, a call to
+ dictionary_get will return a NULL value: the variable will be found, and
+ its value (NULL) is returned. In other words, setting the variable
+ content to NULL is equivalent to deleting the variable from the
+ dictionary. It is not possible (in this implementation) to have a key in
+ the dictionary without value.
+ */
+/*--------------------------------------------------------------------------*/
+
+void dictionary_set(dictionary * d, char * key, char * val)
+{
+ int i ;
+ unsigned hash ;
+
+ if (d==NULL || key==NULL) return ;
+
+ /* Compute hash for this key */
+ hash = dictionary_hash(key) ;
+ /* Find if value is already in blackboard */
+ if (d->n>0) {
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (hash==d->hash[i]) { /* Same hash value */
+ if (!strcmp(key, d->key[i])) { /* Same key */
+ /* Found a value: modify and return */
+ if (d->val[i]!=NULL)
+ free(d->val[i]);
+ d->val[i] = val ? strdup(val) : NULL ;
+ /* Value has been modified: return */
+ return ;
+ }
+ }
+ }
+ }
+ /* Add a new value */
+ /* See if dictionary needs to grow */
+ 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)) ;
+
+ /* Double size */
+ d->size *= 2 ;
+ }
+
+ /* Insert key in the first empty slot */
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL) {
+ /* Add key here */
+ break ;
+ }
+ }
+ /* Copy key */
+ d->key[i] = strdup(key);
+ d->val[i] = val ? strdup(val) : NULL ;
+ d->hash[i] = hash;
+ d->n ++ ;
+ return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete a key in a dictionary
+ @param d dictionary object to modify.
+ @param key Key to remove.
+ @return void
+
+ This function deletes a key in a dictionary. Nothing is done if the
+ key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, char * key)
+{
+ unsigned hash ;
+ int i ;
+
+ hash = dictionary_hash(key);
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ /* Compare hash */
+ if (hash==d->hash[i]) {
+ /* Compare string, to avoid hash collisions */
+ if (!strcmp(key, d->key[i])) {
+ /* Found key */
+ break ;
+ }
+ }
+ }
+ if (i>=d->size)
+ /* Key not found */
+ return ;
+
+ free(d->key[i]);
+ d->key[i] = NULL ;
+ if (d->val[i]!=NULL) {
+ free(d->val[i]);
+ d->val[i] = NULL ;
+ }
+ d->hash[i] = 0 ;
+ d->n -- ;
+ return ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a key in a dictionary, providing an int.
+ @param d Dictionary to update.
+ @param key Key to modify or add
+ @param val Integer value to store (will be stored as a string).
+ @return void
+
+ This helper function calls dictionary_set() with the provided integer
+ converted to a string using %d.
+ */
+/*--------------------------------------------------------------------------*/
+
+
+void dictionary_setint(dictionary * d, char * key, int val)
+{
+ char sval[MAXVALSZ];
+ sprintf(sval, "%d", val);
+ dictionary_set(d, key, sval);
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a key in a dictionary, providing a double.
+ @param d Dictionary to update.
+ @param key Key to modify or add
+ @param val Double value to store (will be stored as a string).
+ @return void
+
+ This helper function calls dictionary_set() with the provided double
+ converted to a string using %g.
+ */
+/*--------------------------------------------------------------------------*/
+
+
+void dictionary_setdouble(dictionary * d, char * key, double val)
+{
+ char sval[MAXVALSZ];
+ sprintf(sval, "%g", val);
+ dictionary_set(d, key, sval);
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump
+ @param f Opened file pointer.
+ @return void
+
+ Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+ output file pointers.
+ */
+/*--------------------------------------------------------------------------*/
+
+void dictionary_dump(dictionary * d, FILE * out)
+{
+ int i ;
+
+ if (d==NULL || out==NULL) return ;
+ if (d->n<1) {
+ fprintf(out, "empty dictionary\n");
+ return ;
+ }
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]) {
+ fprintf(out, "%20s\t[%s]\n",
+ d->key[i],
+ d->val[i] ? d->val[i] : "UNDEF");
+ }
+ }
+ return ;
+}
+
+
+
+/* Example code */
+#ifdef TESTDIC
+#define NVALS 20000
+int main(int argc, char *argv[])
+{
+ dictionary * d ;
+ char * val ;
+ int i ;
+ char cval[90] ;
+
+ /* allocate blackboard */
+ printf("allocating...\n");
+ d = dictionary_new(0);
+
+ /* Set values in blackboard */
+ printf("setting %d values...\n", NVALS);
+ for (i=0 ; i<NVALS ; i++) {
+ sprintf(cval, "%04d", i);
+ dictionary_set(d, cval, "salut");
+ }
+ printf("getting %d values...\n", NVALS);
+ for (i=0 ; i<NVALS ; i++) {
+ sprintf(cval, "%04d", i);
+ val = dictionary_get(d, cval, DICT_INVALID_KEY);
+ if (val==DICT_INVALID_KEY) {
+ printf("cannot get value for key [%s]\n", cval);
+ }
+ }
+ printf("unsetting %d values...\n", NVALS);
+ for (i=0 ; i<NVALS ; i++) {
+ sprintf(cval, "%04d", i);
+ dictionary_unset(d, cval);
+ }
+ if (d->n != 0) {
+ printf("error deleting values\n");
+ }
+
+ printf("deallocating...\n");
+ dictionary_del(d);
+ return 0 ;
+}
+#endif
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/source/iniparser/src/dictionary.h b/source/iniparser/src/dictionary.h
new file mode 100644
index 00000000000..dcab6e75117
--- /dev/null
+++ b/source/iniparser/src/dictionary.h
@@ -0,0 +1,244 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file dictionary.h
+ @author N. Devillard
+ @date Aug 2000
+ @version $Revision: 1.11 $
+ @brief Implements a dictionary for string variables.
+
+ This module implements a simple dictionary object, i.e. a list
+ of string/string associations. This object is useful to store e.g.
+ informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ $Id: dictionary.h,v 1.11 2002/06/17 09:30:46 ndevilla Exp $
+ $Author: ndevilla $
+ $Date: 2002/06/17 09:30:46 $
+ $Revision: 1.11 $
+*/
+
+#ifndef _DICTIONARY_H_
+#define _DICTIONARY_H_
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*---------------------------------------------------------------------------
+ New types
+ ---------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dictionary object
+
+ This object contains a list of string/string associations. Each
+ association is identified by a unique string key. Looking up values
+ in the dictionary is speeded up by the use of a (hopefully collision-free)
+ hash function.
+ */
+/*-------------------------------------------------------------------------*/
+typedef struct _dictionary_ {
+ int n ; /** Number of entries in dictionary */
+ int size ; /** Storage size */
+ char ** val ; /** List of string values */
+ char ** key ; /** List of string keys */
+ unsigned * hash ; /** List of hash values for keys */
+} dictionary ;
+
+
+/*---------------------------------------------------------------------------
+ Function prototypes
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Compute the hash key for a string.
+ @param key Character string to use for key.
+ @return 1 unsigned int on at least 32 bits.
+
+ This hash function has been taken from an Article in Dr Dobbs Journal.
+ This is normally a collision-free function, distributing keys evenly.
+ The key is stored anyway in the struct so that collision can be avoided
+ by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(char * key);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Create a new dictionary object.
+ @param size Optional initial size of the dictionary.
+ @return 1 newly allocated dictionary objet.
+
+ This function allocates a new dictionary object of given size and returns
+ it. If you do not know in advance (roughly) the number of entries in the
+ dictionary, give size=0.
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * dictionary_new(int size);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete a dictionary object
+ @param d dictionary object to deallocate.
+ @return void
+
+ Deallocate a dictionary object and all memory associated to it.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_del(dictionary * vd);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value to return if key not found.
+ @return 1 pointer to internally allocated character string.
+
+ This function locates a key in a dictionary and returns a pointer to its
+ value, or the passed 'def' pointer if no such key can be found in
+ dictionary. The returned character pointer points to data internal to the
+ dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * dictionary_get(dictionary * d, char * key, char * def);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary, as a char.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value for the key if not found.
+ @return char
+
+ This function locates a key in a dictionary using dictionary_get,
+ and returns the first char of the found string.
+ */
+/*--------------------------------------------------------------------------*/
+char dictionary_getchar(dictionary * d, char * key, char def) ;
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary, as an int.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value for the key if not found.
+ @return int
+
+ This function locates a key in a dictionary using dictionary_get,
+ and applies atoi on it to return an int. If the value cannot be found
+ in the dictionary, the default is returned.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_getint(dictionary * d, char * key, int def);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get a value from a dictionary, as a double.
+ @param d dictionary object to search.
+ @param key Key to look for in the dictionary.
+ @param def Default value for the key if not found.
+ @return double
+
+ This function locates a key in a dictionary using dictionary_get,
+ and applies atof on it to return a double. If the value cannot be found
+ in the dictionary, the default is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double dictionary_getdouble(dictionary * d, char * key, double def);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a value in a dictionary.
+ @param d dictionary object to modify.
+ @param key Key to modify or add.
+ @param val Value to add.
+ @return void
+
+ If the given key is found in the dictionary, the associated value is
+ replaced by the provided one. If the key cannot be found in the
+ dictionary, it is added to it.
+
+ It is Ok to provide a NULL value for val, but NULL values for the dictionary
+ or the key are considered as errors: the function will return immediately
+ in such a case.
+
+ Notice that if you dictionary_set a variable to NULL, a call to
+ dictionary_get will return a NULL value: the variable will be found, and
+ its value (NULL) is returned. In other words, setting the variable
+ content to NULL is equivalent to deleting the variable from the
+ dictionary. It is not possible (in this implementation) to have a key in
+ the dictionary without value.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_set(dictionary * vd, char * key, char * val);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete a key in a dictionary
+ @param d dictionary object to modify.
+ @param key Key to remove.
+ @return void
+
+ This function deletes a key in a dictionary. Nothing is done if the
+ key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, char * key);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a key in a dictionary, providing an int.
+ @param d Dictionary to update.
+ @param key Key to modify or add
+ @param val Integer value to store (will be stored as a string).
+ @return void
+
+ This helper function calls dictionary_set() with the provided integer
+ converted to a string using %d.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_setint(dictionary * d, char * key, int val);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a key in a dictionary, providing a double.
+ @param d Dictionary to update.
+ @param key Key to modify or add
+ @param val Double value to store (will be stored as a string).
+ @return void
+
+ This helper function calls dictionary_set() with the provided double
+ converted to a string using %g.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_setdouble(dictionary * d, char * key, double val);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump
+ @param f Opened file pointer.
+ @return void
+
+ Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+ output file pointers.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_dump(dictionary * d, FILE * out);
+
+#endif
diff --git a/source/iniparser/src/iniparser.c b/source/iniparser/src/iniparser.c
new file mode 100644
index 00000000000..0c06ab364b1
--- /dev/null
+++ b/source/iniparser/src/iniparser.c
@@ -0,0 +1,517 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file iniparser.c
+ @author N. Devillard
+ @date Mar 2000
+ @version $Revision: 2.14 $
+ @brief Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ $Id: iniparser.c,v 2.14 2002/12/12 10:49:01 ndevilla Exp $
+ $Author: ndevilla $
+ $Date: 2002/12/12 10:49:01 $
+ $Revision: 2.14 $
+*/
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include "iniparser.h"
+#include "strlib.h"
+
+#define ASCIILINESZ 1024
+#define INI_INVALID_KEY ((char*)-1)
+
+/*---------------------------------------------------------------------------
+ Private to this module
+ ---------------------------------------------------------------------------*/
+
+/* Private: add an entry to the dictionary */
+static void iniparser_add_entry(
+ dictionary * d,
+ char * sec,
+ char * key,
+ char * val)
+{
+ char longkey[2*ASCIILINESZ+1];
+
+ /* Make a key as section:keyword */
+ if (key!=NULL) {
+ sprintf(longkey, "%s:%s", sec, key);
+ } else {
+ strcpy(longkey, sec);
+ }
+
+ /* Add (key,val) to dictionary */
+ dictionary_set(d, longkey, val);
+ return ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get number of sections in a dictionary
+ @param d Dictionary to examine
+ @return int Number of sections found in dictionary
+
+ This function returns the number of sections found in a dictionary.
+ The test to recognize sections is done on the string stored in the
+ dictionary: a section name is given as "section" whereas a key is
+ stored as "section:key", thus the test looks for entries that do not
+ contain a colon.
+
+ This clearly fails in the case a section name contains a colon, but
+ this should simply be avoided.
+
+ This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_getnsec(dictionary * d)
+{
+ int i ;
+ int nsec ;
+
+ if (d==NULL) return -1 ;
+ nsec=0 ;
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (strchr(d->key[i], ':')==NULL) {
+ nsec ++ ;
+ }
+ }
+ return nsec ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get name for section n in a dictionary.
+ @param d Dictionary to examine
+ @param n Section number (from 0 to nsec-1).
+ @return Pointer to char string
+
+ This function locates the n-th section in a dictionary and returns
+ its name as a pointer to a string statically allocated inside the
+ dictionary. Do not free or modify the returned string!
+
+ This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+char * iniparser_getsecname(dictionary * d, int n)
+{
+ int i ;
+ int foundsec ;
+
+ if (d==NULL || n<0) return NULL ;
+ foundsec=0 ;
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (strchr(d->key[i], ':')==NULL) {
+ foundsec++ ;
+ if (foundsec>n)
+ break ;
+ }
+ }
+ if (foundsec<=n) {
+ return NULL ;
+ }
+ return d->key[i] ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump.
+ @param f Opened file pointer to dump to.
+ @return void
+
+ This function prints out the contents of a dictionary, one element by
+ line, onto the provided file pointer. It is OK to specify @c stderr
+ or @c stdout as output files. This function is meant for debugging
+ purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump(dictionary * d, FILE * f)
+{
+ int i ;
+
+ if (d==NULL || f==NULL) return ;
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (d->val[i]!=NULL) {
+ fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
+ } else {
+ fprintf(f, "[%s]=UNDEF\n", d->key[i]);
+ }
+ }
+ return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Save a dictionary to a loadable ini file
+ @param d Dictionary to dump
+ @param f Opened file pointer to dump to
+ @return void
+
+ This function dumps a given dictionary into a loadable ini file.
+ It is Ok to specify @c stderr or @c stdout as output files.
+ */
+/*--------------------------------------------------------------------------*/
+
+void iniparser_dump_ini(dictionary * d, FILE * f)
+{
+ int i, j ;
+ char keym[ASCIILINESZ+1];
+ int nsec ;
+ char * secname ;
+ int seclen ;
+
+ if (d==NULL || f==NULL) return ;
+
+ nsec = iniparser_getnsec(d);
+ if (nsec<1) {
+ /* No section in file: dump all keys as they are */
+ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
+ }
+ return ;
+ }
+ for (i=0 ; i<nsec ; i++) {
+ secname = iniparser_getsecname(d, i) ;
+ seclen = (int)strlen(secname);
+ fprintf(f, "\n[%s]\n", secname);
+ sprintf(keym, "%s:", secname);
+ for (j=0 ; j<d->size ; j++) {
+ if (d->key[j]==NULL)
+ continue ;
+ if (!strncmp(d->key[j], keym, seclen+1)) {
+ fprintf(f,
+ "%-30s = %s\n",
+ d->key[j]+seclen+1,
+ d->val[j] ? d->val[j] : "");
+ }
+ }
+ }
+ fprintf(f, "\n");
+ return ;
+}
+
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, return NULL if not found
+ @param d Dictionary to search
+ @param key Key string to look for
+ @return pointer to statically allocated character string, or NULL.
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ NULL is returned.
+ The returned char pointer is pointing to a string allocated in
+ the dictionary, do not free or modify it.
+
+ This function is only provided for backwards compatibility with
+ previous versions of iniparser. It is recommended to use
+ iniparser_getstring() instead.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstr(dictionary * d, char * key)
+{
+ return iniparser_getstring(d, key, NULL);
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param def Default value to return if key not found.
+ @return pointer to statically allocated character string
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the pointer passed as 'def' is returned.
+ The returned char pointer is pointing to a string allocated in
+ the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstring(dictionary * d, char * key, char * def)
+{
+ char * lc_key ;
+ char * sval ;
+
+ if (d==NULL || key==NULL)
+ return def ;
+
+ lc_key = strdup(strlwc(key));
+ sval = dictionary_get(d, lc_key, def);
+ free(lc_key);
+ return sval ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to an int
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return integer
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getint(dictionary * d, char * key, int notfound)
+{
+ char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==INI_INVALID_KEY) return notfound ;
+ return atoi(str);
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a double
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return double
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(dictionary * d, char * key, double notfound)
+{
+ char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==INI_INVALID_KEY) return notfound ;
+ return atof(str);
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a boolean
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return integer
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the notfound value is returned.
+
+ A true boolean is found if one of the following is matched:
+
+ - A string starting with 'y'
+ - A string starting with 'Y'
+ - A string starting with 't'
+ - A string starting with 'T'
+ - A string starting with '1'
+
+ A false boolean is found if one of the following is matched:
+
+ - A string starting with 'n'
+ - A string starting with 'N'
+ - A string starting with 'f'
+ - A string starting with 'F'
+ - A string starting with '0'
+
+ The notfound value returned if no boolean is identified, does not
+ necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(dictionary * d, char * key, int notfound)
+{
+ char * c ;
+ int ret ;
+
+ c = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (c==INI_INVALID_KEY) return notfound ;
+ if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
+ ret = 1 ;
+ } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
+ ret = 0 ;
+ } else {
+ ret = notfound ;
+ }
+ return ret;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Finds out if a given entry exists in a dictionary
+ @param ini Dictionary to search
+ @param entry Name of the entry to look for
+ @return integer 1 if entry exists, 0 otherwise
+
+ Finds out if a given entry exists in the dictionary. Since sections
+ are stored as keys with NULL associated values, this is the only way
+ of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_find_entry(
+ dictionary * ini,
+ char * entry
+)
+{
+ int found=0 ;
+ if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+ found = 1 ;
+ }
+ return found ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set an entry in a dictionary.
+ @param ini Dictionary to modify.
+ @param entry Entry to modify (entry name)
+ @param val New value to associate to the entry.
+ @return int 0 if Ok, -1 otherwise.
+
+ If the given entry can be found in the dictionary, it is modified to
+ contain the provided value. If it cannot be found, -1 is returned.
+ It is Ok to set val to NULL.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_setstr(dictionary * ini, char * entry, char * val)
+{
+ dictionary_set(ini, strlwc(entry), val);
+ return 0 ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete an entry in a dictionary
+ @param ini Dictionary to modify
+ @param entry Entry to delete (entry name)
+ @return void
+
+ If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, char * entry)
+{
+ dictionary_unset(ini, strlwc(entry));
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Parse an ini file and return an allocated dictionary object
+ @param ininame Name of the ini file to read.
+ @return Pointer to newly allocated dictionary
+
+ This is the parser for ini files. This function is called, providing
+ the name of the file to be read. It returns a dictionary object that
+ should not be accessed directly, but through accessor functions
+ instead.
+
+ The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+
+dictionary * iniparser_load(char * ininame)
+{
+ dictionary * d ;
+ char lin[ASCIILINESZ+1];
+ char sec[ASCIILINESZ+1];
+ char key[ASCIILINESZ+1];
+ char val[ASCIILINESZ+1];
+ char * where ;
+ FILE * ini ;
+ int lineno ;
+
+ if ((ini=fopen(ininame, "r"))==NULL) {
+ return NULL ;
+ }
+
+ sec[0]=0;
+
+ /*
+ * Initialize a new dictionary entry
+ */
+ d = dictionary_new(0);
+ lineno = 0 ;
+ while (fgets(lin, ASCIILINESZ, ini)!=NULL) {
+ lineno++ ;
+ where = strskp(lin); /* Skip leading spaces */
+ if (*where==';' || *where=='#' || *where==0)
+ continue ; /* Comment lines */
+ else {
+ if (sscanf(where, "[%[^]]", sec)==1) {
+ /* Valid section name */
+ strcpy(sec, strlwc(sec));
+ iniparser_add_entry(d, sec, NULL, NULL);
+ } else if (sscanf (where, "%[^=] = \"%[^\"]\"", key, val) == 2
+ || sscanf (where, "%[^=] = '%[^\']'", key, val) == 2
+ || sscanf (where, "%[^=] = %[^;#]", key, val) == 2) {
+ strcpy(key, strlwc(strcrop(key)));
+ /*
+ * sscanf cannot handle "" or '' as empty value,
+ * this is done here
+ */
+ if (!strcmp(val, "\"\"") || !strcmp(val, "''")) {
+ val[0] = (char)0;
+ } else {
+ strcpy(val, strcrop(val));
+ }
+ iniparser_add_entry(d, sec, key, val);
+ }
+ }
+ }
+ fclose(ini);
+ return d ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Free all memory associated to an ini dictionary
+ @param d Dictionary to free
+ @return void
+
+ Free all memory associated to an ini dictionary.
+ It is mandatory to call this function before the dictionary object
+ gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+
+void iniparser_freedict(dictionary * d)
+{
+ dictionary_del(d);
+}
+
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/source/iniparser/src/iniparser.h b/source/iniparser/src/iniparser.h
new file mode 100644
index 00000000000..98e8b33b781
--- /dev/null
+++ b/source/iniparser/src/iniparser.h
@@ -0,0 +1,282 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file iniparser.h
+ @author N. Devillard
+ @date Mar 2000
+ @version $Revision: 1.20 $
+ @brief Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ $Id: iniparser.h,v 1.20 2005/08/19 17:23:21 ndevilla Exp $
+ $Author: ndevilla $
+ $Date: 2005/08/19 17:23:21 $
+ $Revision: 1.20 $
+*/
+
+#ifndef _INIPARSER_H_
+#define _INIPARSER_H_
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * The following #include is necessary on many Unixes but not Linux.
+ * It is not needed for Windows platforms.
+ * Uncomment it if needed.
+ */
+/* #include <unistd.h> */
+
+#include "dictionary.h"
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get number of sections in a dictionary
+ @param d Dictionary to examine
+ @return int Number of sections found in dictionary
+
+ This function returns the number of sections found in a dictionary.
+ The test to recognize sections is done on the string stored in the
+ dictionary: a section name is given as "section" whereas a key is
+ stored as "section:key", thus the test looks for entries that do not
+ contain a colon.
+
+ This clearly fails in the case a section name contains a colon, but
+ this should simply be avoided.
+
+ This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_getnsec(dictionary * d);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get name for section n in a dictionary.
+ @param d Dictionary to examine
+ @param n Section number (from 0 to nsec-1).
+ @return Pointer to char string
+
+ This function locates the n-th section in a dictionary and returns
+ its name as a pointer to a string statically allocated inside the
+ dictionary. Do not free or modify the returned string!
+
+ This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+char * iniparser_getsecname(dictionary * d, int n);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Save a dictionary to a loadable ini file
+ @param d Dictionary to dump
+ @param f Opened file pointer to dump to
+ @return void
+
+ This function dumps a given dictionary into a loadable ini file.
+ It is Ok to specify @c stderr or @c stdout as output files.
+ */
+/*--------------------------------------------------------------------------*/
+
+void iniparser_dump_ini(dictionary * d, FILE * f);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump.
+ @param f Opened file pointer to dump to.
+ @return void
+
+ This function prints out the contents of a dictionary, one element by
+ line, onto the provided file pointer. It is OK to specify @c stderr
+ or @c stdout as output files. This function is meant for debugging
+ purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump(dictionary * d, FILE * f);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, return NULL if not found
+ @param d Dictionary to search
+ @param key Key string to look for
+ @return pointer to statically allocated character string, or NULL.
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ NULL is returned.
+ The returned char pointer is pointing to a string allocated in
+ the dictionary, do not free or modify it.
+
+ This function is only provided for backwards compatibility with
+ previous versions of iniparser. It is recommended to use
+ iniparser_getstring() instead.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstr(dictionary * d, char * key);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param def Default value to return if key not found.
+ @return pointer to statically allocated character string
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the pointer passed as 'def' is returned.
+ The returned char pointer is pointing to a string allocated in
+ the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstring(dictionary * d, char * key, char * def);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to an int
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return integer
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getint(dictionary * d, char * key, int notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a double
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return double
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(dictionary * d, char * key, double notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a boolean
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return integer
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+ the notfound value is returned.
+
+ A true boolean is found if one of the following is matched:
+
+ - A string starting with 'y'
+ - A string starting with 'Y'
+ - A string starting with 't'
+ - A string starting with 'T'
+ - A string starting with '1'
+
+ A false boolean is found if one of the following is matched:
+
+ - A string starting with 'n'
+ - A string starting with 'N'
+ - A string starting with 'f'
+ - A string starting with 'F'
+ - A string starting with '0'
+
+ The notfound value returned if no boolean is identified, does not
+ necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(dictionary * d, char * key, int notfound);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set an entry in a dictionary.
+ @param ini Dictionary to modify.
+ @param entry Entry to modify (entry name)
+ @param val New value to associate to the entry.
+ @return int 0 if Ok, -1 otherwise.
+
+ If the given entry can be found in the dictionary, it is modified to
+ contain the provided value. If it cannot be found, -1 is returned.
+ It is Ok to set val to NULL.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_setstr(dictionary * ini, char * entry, char * val);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete an entry in a dictionary
+ @param ini Dictionary to modify
+ @param entry Entry to delete (entry name)
+ @return void
+
+ If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, char * entry);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Finds out if a given entry exists in a dictionary
+ @param ini Dictionary to search
+ @param entry Name of the entry to look for
+ @return integer 1 if entry exists, 0 otherwise
+
+ Finds out if a given entry exists in the dictionary. Since sections
+ are stored as keys with NULL associated values, this is the only way
+ of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_find_entry(dictionary * ini, char * entry) ;
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Parse an ini file and return an allocated dictionary object
+ @param ininame Name of the ini file to read.
+ @return Pointer to newly allocated dictionary
+
+ This is the parser for ini files. This function is called, providing
+ the name of the file to be read. It returns a dictionary object that
+ should not be accessed directly, but through accessor functions
+ instead.
+
+ The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load(char * ininame);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Free all memory associated to an ini dictionary
+ @param d Dictionary to free
+ @return void
+
+ Free all memory associated to an ini dictionary.
+ It is mandatory to call this function before the dictionary object
+ gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_freedict(dictionary * d);
+
+#endif
diff --git a/source/iniparser/src/strlib.c b/source/iniparser/src/strlib.c
new file mode 100644
index 00000000000..3bfddaaebe2
--- /dev/null
+++ b/source/iniparser/src/strlib.c
@@ -0,0 +1,211 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file strlib.c
+ @author N. Devillard
+ @date Jan 2001
+ @version $Revision: 1.8 $
+ @brief Various string handling routines to complement the C lib.
+
+ This modules adds a few complementary string routines usually missing
+ in the standard C library.
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ $Id: strlib.c,v 1.8 2002/12/12 10:29:16 ndevilla Exp $
+ $Author: ndevilla $
+ $Date: 2002/12/12 10:29:16 $
+ $Revision: 1.8 $
+*/
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include <string.h>
+#include <ctype.h>
+
+#include "strlib.h"
+
+/*---------------------------------------------------------------------------
+ Defines
+ ---------------------------------------------------------------------------*/
+#define ASCIILINESZ 1024
+
+/*---------------------------------------------------------------------------
+ Function codes
+ ---------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Convert a string to lowercase.
+ @param s String to convert.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string
+ containing a lowercased version of the input string. Do not free
+ or modify the returned string! Since the returned string is statically
+ allocated, it will be modified at each function call (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+
+char * strlwc(char * s)
+{
+ static char l[ASCIILINESZ+1];
+ int i ;
+
+ if (s==NULL) return NULL ;
+ memset(l, 0, ASCIILINESZ+1);
+ i=0 ;
+ while (s[i] && i<ASCIILINESZ) {
+ l[i] = (char)tolower((int)s[i]);
+ i++ ;
+ }
+ l[ASCIILINESZ]=(char)0;
+ return l ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Convert a string to uppercase.
+ @param s String to convert.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string
+ containing an uppercased version of the input string. Do not free
+ or modify the returned string! Since the returned string is statically
+ allocated, it will be modified at each function call (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+
+char * strupc(char * s)
+{
+ static char l[ASCIILINESZ+1];
+ int i ;
+
+ if (s==NULL) return NULL ;
+ memset(l, 0, ASCIILINESZ+1);
+ i=0 ;
+ while (s[i] && i<ASCIILINESZ) {
+ l[i] = (char)toupper((int)s[i]);
+ i++ ;
+ }
+ l[ASCIILINESZ]=(char)0;
+ return l ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Skip blanks until the first non-blank character.
+ @param s String to parse.
+ @return Pointer to char inside given string.
+
+ This function returns a pointer to the first non-blank character in the
+ given string.
+ */
+/*--------------------------------------------------------------------------*/
+
+char * strskp(char * s)
+{
+ char * skip = s;
+ if (s==NULL) return NULL ;
+ while (isspace((int)*skip) && *skip) skip++;
+ return skip ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Remove blanks at the end of a string.
+ @param s String to parse.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string,
+ which is identical to the input string, except that all blank
+ characters at the end of the string have been removed.
+ Do not free or modify the returned string! Since the returned string
+ is statically allocated, it will be modified at each function call
+ (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+
+char * strcrop(char * s)
+{
+ static char l[ASCIILINESZ+1];
+ char * last ;
+
+ if (s==NULL) return NULL ;
+ memset(l, 0, ASCIILINESZ+1);
+ strcpy(l, s);
+ last = l + strlen(l);
+ while (last > l) {
+ if (!isspace((int)*(last-1)))
+ break ;
+ last -- ;
+ }
+ *last = (char)0;
+ return l ;
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Remove blanks at the beginning and the end of a string.
+ @param s String to parse.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string,
+ which is identical to the input string, except that all blank
+ characters at the end and the beg. of the string have been removed.
+ Do not free or modify the returned string! Since the returned string
+ is statically allocated, it will be modified at each function call
+ (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+char * strstrip(char * s)
+{
+ static char l[ASCIILINESZ+1];
+ char * last ;
+
+ if (s==NULL) return NULL ;
+
+ while (isspace((int)*s) && *s) s++;
+
+ memset(l, 0, ASCIILINESZ+1);
+ strcpy(l, s);
+ last = l + strlen(l);
+ while (last > l) {
+ if (!isspace((int)*(last-1)))
+ break ;
+ last -- ;
+ }
+ *last = (char)0;
+
+ return (char*)l ;
+}
+
+/* Test code */
+#ifdef TEST
+int main(int argc, char * argv[])
+{
+ char * str ;
+
+ str = "\t\tI'm a lumberkack and I'm OK " ;
+ printf("lowercase: [%s]\n", strlwc(str));
+ printf("uppercase: [%s]\n", strupc(str));
+ printf("skipped : [%s]\n", strskp(str));
+ printf("cropped : [%s]\n", strcrop(str));
+ printf("stripped : [%s]\n", strstrip(str));
+
+ return 0 ;
+}
+#endif
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/source/iniparser/src/strlib.h b/source/iniparser/src/strlib.h
new file mode 100644
index 00000000000..8d8f15fcf0a
--- /dev/null
+++ b/source/iniparser/src/strlib.h
@@ -0,0 +1,108 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file strlib.h
+ @author N. Devillard
+ @date Jan 2001
+ @version $Revision: 1.3 $
+ @brief Various string handling routines to complement the C lib.
+
+ This modules adds a few complementary string routines usually missing
+ in the standard C library.
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+ $Id: strlib.h,v 1.3 2001/10/19 08:31:41 ndevilla Exp $
+ $Author: ndevilla $
+ $Date: 2001/10/19 08:31:41 $
+ $Revision: 1.3 $
+*/
+
+#ifndef _STRLIB_H_
+#define _STRLIB_H_
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*---------------------------------------------------------------------------
+ Function codes
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Convert a string to lowercase.
+ @param s String to convert.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string
+ containing a lowercased version of the input string. Do not free
+ or modify the returned string! Since the returned string is statically
+ allocated, it will be modified at each function call (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+char * strlwc(char * s);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Convert a string to uppercase.
+ @param s String to convert.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string
+ containing an uppercased version of the input string. Do not free
+ or modify the returned string! Since the returned string is statically
+ allocated, it will be modified at each function call (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+char * strupc(char * s);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Skip blanks until the first non-blank character.
+ @param s String to parse.
+ @return Pointer to char inside given string.
+
+ This function returns a pointer to the first non-blank character in the
+ given string.
+ */
+/*--------------------------------------------------------------------------*/
+char * strskp(char * s);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Remove blanks at the end of a string.
+ @param s String to parse.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string,
+ which is identical to the input string, except that all blank
+ characters at the end of the string have been removed.
+ Do not free or modify the returned string! Since the returned string
+ is statically allocated, it will be modified at each function call
+ (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+char * strcrop(char * s);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Remove blanks at the beginning and the end of a string.
+ @param s String to parse.
+ @return ptr to statically allocated string.
+
+ This function returns a pointer to a statically allocated string,
+ which is identical to the input string, except that all blank
+ characters at the end and the beg. of the string have been removed.
+ Do not free or modify the returned string! Since the returned string
+ is statically allocated, it will be modified at each function call
+ (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+char * strstrip(char * s) ;
+
+#endif
diff --git a/source/iniparser/test/Makefile b/source/iniparser/test/Makefile
new file mode 100644
index 00000000000..aa8fcb24b57
--- /dev/null
+++ b/source/iniparser/test/Makefile
@@ -0,0 +1,24 @@
+#
+# iniparser tests Makefile
+#
+
+CC = gcc
+CFLAGS = -g -I../src
+LFLAGS = -L.. -liniparser
+AR = ar
+ARFLAGS = rcv
+RM = rm -f
+
+
+default: all
+
+all: iniexample
+
+iniexample: iniexample.c
+ $(CC) $(CFLAGS) -o iniexample iniexample.c -I../src -L.. -liniparser
+
+clean veryclean:
+ $(RM) iniexample example.ini
+
+
+
diff --git a/source/iniparser/test/iniexample.c b/source/iniparser/test/iniexample.c
new file mode 100644
index 00000000000..5e8e71cdf00
--- /dev/null
+++ b/source/iniparser/test/iniexample.c
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "iniparser.h"
+
+void create_example_ini_file(void);
+int parse_ini_file(char * ini_name);
+
+int main(int argc, char * argv[])
+{
+ int status ;
+
+ if (argc<2) {
+ create_example_ini_file();
+ status = parse_ini_file("example.ini");
+ } else {
+ status = parse_ini_file(argv[1]);
+ }
+ return status ;
+}
+
+void create_example_ini_file(void)
+{
+ FILE * ini ;
+
+ ini = fopen("example.ini", "w");
+ fprintf(ini, "\n\
+#\n\
+# This is an example of ini file\n\
+#\n\
+\n\
+[Pizza]\n\
+\n\
+Ham = yes ;\n\
+Mushrooms = TRUE ;\n\
+Capres = 0 ;\n\
+Cheese = NO ;\n\
+\n\
+\n\
+[Wine]\n\
+\n\
+Grape = Cabernet Sauvignon ;\n\
+Year = 1989 ;\n\
+Country = Spain ;\n\
+Alcohol = 12.5 ;\n\
+\n\
+#\n\
+# end of file\n\
+#\n");
+
+ fclose(ini);
+}
+
+
+int parse_ini_file(char * ini_name)
+{
+ dictionary * ini ;
+
+ /* Some temporary variables to hold query results */
+ int b ;
+ int i ;
+ double d ;
+ char * s ;
+
+ ini = iniparser_load(ini_name);
+ if (ini==NULL) {
+ fprintf(stderr, "cannot parse file [%s]", ini_name);
+ return -1 ;
+ }
+ iniparser_dump(ini, stderr);
+
+ /* Get pizza attributes */
+ printf("Pizza:\n");
+
+ b = iniparser_getboolean(ini, "pizza:ham", -1);
+ printf("Ham: [%d]\n", b);
+ b = iniparser_getboolean(ini, "pizza:mushrooms", -1);
+ printf("Mushrooms: [%d]\n", b);
+ b = iniparser_getboolean(ini, "pizza:capres", -1);
+ printf("Capres: [%d]\n", b);
+ b = iniparser_getboolean(ini, "pizza:cheese", -1);
+ printf("Cheese: [%d]\n", b);
+
+ /* Get wine attributes */
+ printf("Wine:\n");
+ s = iniparser_getstr(ini, "wine:grape");
+ if (s) {
+ printf("grape: [%s]\n", s);
+ } else {
+ printf("grape: not found\n");
+ }
+ i = iniparser_getint(ini, "wine:year", -1);
+ if (i>0) {
+ printf("year: [%d]\n", i);
+ } else {
+ printf("year: not found\n");
+ }
+ s = iniparser_getstr(ini, "wine:country");
+ if (s) {
+ printf("country: [%s]\n", s);
+ } else {
+ printf("country: not found\n");
+ }
+ d = iniparser_getdouble(ini, "wine:alcohol", -1.0);
+ if (d>0.0) {
+ printf("alcohol: [%g]\n", d);
+ } else {
+ printf("alcohol: not found\n");
+ }
+
+ iniparser_freedict(ini);
+ return 0 ;
+}
+
+
diff --git a/source/intl/lang_tdb.c b/source/intl/lang_tdb.c
index d3422f0d78a..016f64af52a 100644
--- a/source/intl/lang_tdb.c
+++ b/source/intl/lang_tdb.c
@@ -34,13 +34,16 @@ static BOOL load_msg(const char *msg_file)
char *msgid, *msgstr;
TDB_DATA key, data;
- lines = file_lines_load(msg_file, &num_lines);
+ lines = file_lines_load(msg_file, &num_lines,0);
if (!lines) {
return False;
}
- if (tdb_lockall(tdb) != 0) return False;
+ if (tdb_lockall(tdb) != 0) {
+ file_lines_free(lines);
+ return False;
+ }
/* wipe the db */
tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c
index 75a1d62ee79..6bf7346fe7f 100644
--- a/source/lib/account_pol.c
+++ b/source/lib/account_pol.c
@@ -269,7 +269,7 @@ BOOL init_account_policy(void)
}
/* handle a Samba upgrade */
- tdb_lock_bystring(tdb, vstring,0);
+ tdb_lock_bystring(tdb, vstring);
if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) {
tdb_store_uint32(tdb, vstring, DATABASE_VERSION);
@@ -288,12 +288,17 @@ BOOL init_account_policy(void)
/* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
privilege_create_account( &global_sid_World );
- privilege_create_account( &global_sid_Builtin_Administrators );
privilege_create_account( &global_sid_Builtin_Account_Operators );
privilege_create_account( &global_sid_Builtin_Server_Operators );
privilege_create_account( &global_sid_Builtin_Print_Operators );
privilege_create_account( &global_sid_Builtin_Backup_Operators );
+ /* BUILTIN\Administrators get everything -- *always* */
+
+ if ( !grant_all_privileges( &global_sid_Builtin_Administrators ) ) {
+ DEBUG(0,("init_account_policy: Failed to grant privileges to BUILTIN\\Administrators!\n"));
+ }
+
return True;
}
diff --git a/source/lib/audit.c b/source/lib/audit.c
new file mode 100644
index 00000000000..86bd30bdfff
--- /dev/null
+++ b/source/lib/audit.c
@@ -0,0 +1,149 @@
+/*
+ Unix SMB/CIFS implementation.
+ Auditing helper functions.
+ 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"
+
+static const struct audit_category_tab {
+ uint32 category;
+ const char *category_str;
+ const char *param_str;
+ const char *description;
+} audit_category_tab [] = {
+ { LSA_AUDIT_CATEGORY_LOGON,
+ "LSA_AUDIT_CATEGORY_LOGON",
+ "LOGON", "Logon events" },
+ { LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS,
+ "LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS",
+ "PRIVILEGE", "Privilege Use" },
+ { LSA_AUDIT_CATEGORY_SYSTEM,
+ "LSA_AUDIT_CATEGORY_SYSTEM",
+ "SYSTEM", "System Events" },
+ { LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES,
+ "LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES",
+ "POLICY", "Policy Change" },
+ { LSA_AUDIT_CATEGORY_PROCCESS_TRACKING,
+ "LSA_AUDIT_CATEGORY_PROCCESS_TRACKING",
+ "PROCESS", "Process Tracking" },
+ { LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS,
+ "LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS",
+ "OBJECT", "Object Access" },
+ { LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT,
+ "LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT",
+ "SAM", "Account Management" },
+ { LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS,
+ "LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS",
+ "DIRECTORY", "Directory service access" },
+ { LSA_AUDIT_CATEGORY_ACCOUNT_LOGON,
+ "LSA_AUDIT_CATEGORY_ACCOUNT_LOGON",
+ "ACCOUNT", "Account logon events" },
+ { 0, NULL, NULL }
+};
+
+const char *audit_category_str(uint32 category)
+{
+ int i;
+ for (i=0; audit_category_tab[i].category_str; i++) {
+ if (category == audit_category_tab[i].category) {
+ return audit_category_tab[i].category_str;
+ }
+ }
+ return NULL;
+}
+
+const char *audit_param_str(uint32 category)
+{
+ int i;
+ for (i=0; audit_category_tab[i].param_str; i++) {
+ if (category == audit_category_tab[i].category) {
+ return audit_category_tab[i].param_str;
+ }
+ }
+ return NULL;
+}
+
+const char *audit_description_str(uint32 category)
+{
+ int i;
+ for (i=0; audit_category_tab[i].description; i++) {
+ if (category == audit_category_tab[i].category) {
+ return audit_category_tab[i].description;
+ }
+ }
+ return NULL;
+}
+
+BOOL get_audit_category_from_param(const char *param, uint32 *audit_category)
+{
+ *audit_category = Undefined;
+
+ if (strequal(param, "SYSTEM")) {
+ *audit_category = LSA_AUDIT_CATEGORY_SYSTEM;
+ } else if (strequal(param, "LOGON")) {
+ *audit_category = LSA_AUDIT_CATEGORY_LOGON;
+ } else if (strequal(param, "OBJECT")) {
+ *audit_category = LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS;
+ } else if (strequal(param, "PRIVILEGE")) {
+ *audit_category = LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS;
+ } else if (strequal(param, "PROCESS")) {
+ *audit_category = LSA_AUDIT_CATEGORY_PROCCESS_TRACKING;
+ } else if (strequal(param, "POLICY")) {
+ *audit_category = LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES;
+ } else if (strequal(param, "SAM")) {
+ *audit_category = LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT;
+ } else if (strequal(param, "DIRECTORY")) {
+ *audit_category = LSA_AUDIT_CATEGORY_DIRECTORY_SERVICE_ACCESS;
+ } else if (strequal(param, "ACCOUNT")) {
+ *audit_category = LSA_AUDIT_CATEGORY_ACCOUNT_LOGON;
+ } else {
+ DEBUG(0,("unknown parameter: %s\n", param));
+ return False;
+ }
+
+ return True;
+}
+
+const char *audit_policy_str(TALLOC_CTX *mem_ctx, uint32 policy)
+{
+ const char *ret = NULL;
+
+ if (policy == LSA_AUDIT_POLICY_NONE) {
+ return talloc_strdup(mem_ctx, "None");
+ }
+
+ if (policy & LSA_AUDIT_POLICY_SUCCESS) {
+ ret = talloc_strdup(mem_ctx, "Success");
+ if (ret == NULL) {
+ return NULL;
+ }
+ }
+
+ if (policy & LSA_AUDIT_POLICY_FAILURE) {
+ if (ret) {
+ ret = talloc_asprintf(mem_ctx, "%s, %s", ret, "Failure");
+ if (ret == NULL) {
+ return NULL;
+ }
+ } else {
+ return talloc_strdup(mem_ctx, "Failure");
+ }
+ }
+
+ return ret;
+}
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 26c1a92e69d..097d746a638 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -84,15 +84,6 @@ static const char *charset_name(charset_t ch)
}
ret = ln;
}
-#ifdef HAVE_SETLOCALE
- /* We set back the locale to C to get ASCII-compatible toupper/lower functions.
- For now we do not need any other POSIX localisations anyway. When we should
- really need localized string functions one day we need to write our own
- ascii_tolower etc.
- */
- setlocale(LC_ALL, "C");
- #endif
-
#endif
if (!ret || !*ret) ret = "ASCII";
@@ -111,6 +102,23 @@ void lazy_initialize_conv(void)
}
/**
+ * Destroy global objects allocated by init_iconv()
+ **/
+void gfree_charcnv(void)
+{
+ int c1, c2;
+
+ for (c1=0;c1<NUM_CHARSETS;c1++) {
+ for (c2=0;c2<NUM_CHARSETS;c2++) {
+ if ( conv_handles[c1][c2] ) {
+ smb_iconv_close( conv_handles[c1][c2] );
+ conv_handles[c1][c2] = 0;
+ }
+ }
+ }
+}
+
+/**
* Initialize iconv conversion descriptors.
*
* This is called the first time it is needed, and also called again
@@ -546,19 +554,17 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
destlen = destlen * 2;
}
- if (ctx)
+ if (ctx) {
ob = (char *)TALLOC_REALLOC(ctx, ob, destlen);
- else
+ } else {
ob = (char *)SMB_REALLOC(ob, destlen);
+ }
if (!ob) {
DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
- if (!ctx)
- SAFE_FREE(outbuf);
return (size_t)-1;
- } else {
- outbuf = ob;
}
+ outbuf = ob;
i_len = srclen;
o_len = destlen;
@@ -596,17 +602,18 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
out:
destlen = destlen - o_len;
- if (ctx)
- *dest = (char *)TALLOC_REALLOC(ctx,ob,destlen);
- else
- *dest = (char *)SMB_REALLOC(ob,destlen);
- if (destlen && !*dest) {
+ if (ctx) {
+ ob = (char *)TALLOC_REALLOC(ctx,ob,destlen);
+ } else {
+ ob = (char *)SMB_REALLOC(ob,destlen);
+ }
+
+ if (destlen && !ob) {
DEBUG(0, ("convert_string_allocate: out of memory!\n"));
- if (!ctx)
- SAFE_FREE(ob);
return (size_t)-1;
}
+ *dest = ob;
return destlen;
use_as_is:
diff --git a/source/lib/debug.c b/source/lib/debug.c
index f3676070dcb..b8c42686cdb 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -166,6 +166,7 @@ static const char *default_classname_table[] = {
"acls", /* DBGC_ACLS */
"locking", /* DBGC_LOCKING */
"msdfs", /* DBGC_MSDFS */
+ "dmapi", /* DBGC_DMAPI */
NULL
};
@@ -176,6 +177,27 @@ static char **classname_table = NULL;
* Functions...
*/
+/***************************************************************************
+ Free memory pointed to by global pointers.
+****************************************************************************/
+
+void gfree_debugsyms(void)
+{
+ int i;
+
+ if ( classname_table ) {
+ for ( i = 0; i < debug_num_classes; i++ ) {
+ SAFE_FREE( classname_table[i] );
+ }
+ SAFE_FREE( classname_table );
+ }
+
+ if ( DEBUGLEVEL_CLASS != &debug_all_class_hack )
+ SAFE_FREE( DEBUGLEVEL_CLASS );
+
+ if ( DEBUGLEVEL_CLASS_ISSET != &debug_all_class_isset_hack )
+ SAFE_FREE( DEBUGLEVEL_CLASS_ISSET );
+}
/****************************************************************************
utility lists registered debug class names's
@@ -191,12 +213,14 @@ static char *debug_list_class_names_and_levels(void)
char *b;
BOOL err = False;
- if (DEBUGLEVEL_CLASS == &debug_all_class_hack)
+ if (DEBUGLEVEL_CLASS == &debug_all_class_hack) {
return NULL;
+ }
list = SMB_CALLOC_ARRAY(char *, debug_num_classes + 1);
- if (!list)
+ if (!list) {
return NULL;
+ }
/* prepare strings */
for (i = 0, dim = 0; i < debug_num_classes; i++) {
@@ -227,13 +251,12 @@ static char *debug_list_class_names_and_levels(void)
done:
/* free strings list */
- for (i = 0; i < debug_num_classes; i++)
- if (list[i]) free(list[i]);
- free(list);
+ for (i = 0; i < debug_num_classes; i++) {
+ SAFE_FREE(list[i]);
+ }
+ SAFE_FREE(list);
if (err) {
- if (buf)
- free(buf);
return NULL;
} else {
return buf;
@@ -508,7 +531,7 @@ void debug_init(void)
if (initialised)
return;
-
+
initialised = True;
message_register(MSG_DEBUG, debug_message);
diff --git a/source/rpcclient/display_sec.c b/source/lib/display_sec.c
index 2a93c915f1a..49a86c261ca 100644
--- a/source/rpcclient/display_sec.c
+++ b/source/lib/display_sec.c
@@ -20,7 +20,6 @@
*/
#include "includes.h"
-#include "rpcclient.h"
/****************************************************************************
convert a security permissions into a string
@@ -115,6 +114,41 @@ void display_sec_acl(SEC_ACL *sec_acl)
}
+void display_acl_type(uint16 type)
+{
+ static fstring typestr="";
+
+ typestr[0] = 0;
+
+ if (type & SEC_DESC_OWNER_DEFAULTED) /* 0x0001 */
+ fstrcat(typestr, "SEC_DESC_OWNER_DEFAULTED ");
+ if (type & SEC_DESC_GROUP_DEFAULTED) /* 0x0002 */
+ fstrcat(typestr, "SEC_DESC_GROUP_DEFAULTED ");
+ if (type & SEC_DESC_DACL_PRESENT) /* 0x0004 */
+ fstrcat(typestr, "SEC_DESC_DACL_PRESENT ");
+ if (type & SEC_DESC_DACL_DEFAULTED) /* 0x0008 */
+ fstrcat(typestr, "SEC_DESC_DACL_DEFAULTED ");
+ if (type & SEC_DESC_SACL_PRESENT) /* 0x0010 */
+ fstrcat(typestr, "SEC_DESC_SACL_PRESENT ");
+ if (type & SEC_DESC_SACL_DEFAULTED) /* 0x0020 */
+ fstrcat(typestr, "SEC_DESC_SACL_DEFAULTED ");
+ if (type & SEC_DESC_DACL_TRUSTED) /* 0x0040 */
+ fstrcat(typestr, "SEC_DESC_DACL_TRUSTED ");
+ if (type & SEC_DESC_SERVER_SECURITY) /* 0x0080 */
+ fstrcat(typestr, "SEC_DESC_SERVER_SECURITY ");
+ if (type & 0x0100) fstrcat(typestr, "0x0100 ");
+ if (type & 0x0200) fstrcat(typestr, "0x0200 ");
+ if (type & 0x0400) fstrcat(typestr, "0x0400 ");
+ if (type & 0x0800) fstrcat(typestr, "0x0800 ");
+ if (type & 0x1000) fstrcat(typestr, "0x1000 ");
+ if (type & 0x2000) fstrcat(typestr, "0x2000 ");
+ if (type & 0x4000) fstrcat(typestr, "0x4000 ");
+ if (type & SEC_DESC_SELF_RELATIVE) /* 0x8000 */
+ fstrcat(typestr, "SEC_DESC_SELF_RELATIVE ");
+
+ printf("type: 0x%04x: %s\n", type, typestr);
+}
+
/****************************************************************************
display sec_desc structure
****************************************************************************/
@@ -122,6 +156,14 @@ void display_sec_desc(SEC_DESC *sec)
{
fstring sid_str;
+ if (!sec) {
+ printf("NULL\n");
+ return;
+ }
+
+ printf("revision: %d\n", sec->revision);
+ display_acl_type(sec->type);
+
if (sec->sacl) {
printf("SACL\n");
display_sec_acl(sec->sacl);
diff --git a/source/lib/dummysmbd.c b/source/lib/dummysmbd.c
index 1b31dff4995..9b587224e3e 100644
--- a/source/lib/dummysmbd.c
+++ b/source/lib/dummysmbd.c
@@ -29,3 +29,12 @@ void decrement_smbd_process_count( void )
return;
}
+int find_service(fstring service)
+{
+ return -1;
+}
+
+BOOL conn_snum_used(int snum)
+{
+ return False;
+}
diff --git a/source/lib/events.c b/source/lib/events.c
new file mode 100644
index 00000000000..242c198511e
--- /dev/null
+++ b/source/lib/events.c
@@ -0,0 +1,121 @@
+/*
+ Unix SMB/CIFS implementation.
+ Timed event library.
+ Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Volker Lendecke 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+static struct timed_event *timed_events;
+
+static int timed_event_destructor(void *p)
+{
+ 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);
+ return 0;
+}
+
+/****************************************************************************
+ 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 timeval when,
+ const char *event_name,
+ void (*handler)(struct timed_event *te,
+ const struct timeval *now,
+ void *private_data),
+ void *private_data)
+{
+ struct timed_event *te, *last_te, *cur_te;
+
+ te = TALLOC_P(mem_ctx, struct timed_event);
+ if (te == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ 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;
+ }
+
+ 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,
+ (unsigned long)te));
+ return te;
+}
+
+void run_events(void)
+{
+ struct timeval now;
+
+ if (timed_events == NULL) {
+ /* No syscall if there are no events */
+ DEBUG(11, ("run_events: No events\n"));
+ return;
+ }
+
+ GetTimeOfDay(&now);
+
+ if (timeval_compare(&now, &timed_events->when) < 0) {
+ /* Nothing to do yet */
+ DEBUG(11, ("run_events: Nothing to do\n"));
+ return;
+ }
+
+ DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
+ (unsigned long)timed_events));
+
+ timed_events->handler(timed_events, &now, timed_events->private_data);
+ return;
+}
+
+struct timeval *get_timed_events_timeout(struct timeval *to_ret)
+{
+ struct timeval now;
+
+ if (timed_events == NULL) {
+ return NULL;
+ }
+
+ now = timeval_current();
+ *to_ret = timeval_until(&now, &timed_events->when);
+
+ DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec,
+ (int)to_ret->tv_usec));
+
+ return to_ret;
+}
diff --git a/source/lib/fault.c b/source/lib/fault.c
index 3cb66846393..8ae45f24353 100644
--- a/source/lib/fault.c
+++ b/source/lib/fault.c
@@ -20,7 +20,12 @@
#include "includes.h"
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
static void (*cont_fn)(void *);
+static pstring corepath;
/*******************************************************************
report a fault
@@ -33,11 +38,11 @@ static void fault_report(int sig)
counter++;
- DEBUG(0,("===============================================================\n"));
+ DEBUGSEP(0);
DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),SAMBA_VERSION_STRING));
DEBUG(0,("\nPlease read the Trouble-Shooting section of the Samba3-HOWTO\n"));
DEBUG(0,("\nFrom: http://www.samba.org/samba/docs/Samba3-HOWTO.pdf\n"));
- DEBUG(0,("===============================================================\n"));
+ DEBUGSEP(0);
smb_panic("internal error");
@@ -82,3 +87,91 @@ void fault_setup(void (*fn)(void *))
CatchSignal(SIGABRT,SIGNAL_CAST sig_fault);
#endif
}
+
+/*******************************************************************
+make all the preparations to safely dump a core file
+********************************************************************/
+
+void dump_core_setup(const char *progname)
+{
+ pstring logbase;
+ char * end;
+
+ if (lp_logfile() && *lp_logfile()) {
+ snprintf(logbase, sizeof(logbase), "%s", lp_logfile());
+ if ((end = strrchr_m(logbase, '/'))) {
+ *end = '\0';
+ }
+ } else {
+ /* We will end up here is the log file is given on the command
+ * line by the -l option but the "log file" option is not set
+ * in smb.conf.
+ */
+ snprintf(logbase, sizeof(logbase), "%s", dyn_LOGFILEBASE);
+ }
+
+ SMB_ASSERT(progname != NULL);
+
+ snprintf(corepath, sizeof(corepath), "%s/cores", logbase);
+ mkdir(corepath,0700);
+
+ snprintf(corepath, sizeof(corepath), "%s/cores/%s",
+ logbase, progname);
+ mkdir(corepath,0700);
+
+ sys_chown(corepath,getuid(),getgid());
+ chmod(corepath,0700);
+
+#ifdef HAVE_GETRLIMIT
+#ifdef RLIMIT_CORE
+ {
+ struct rlimit rlp;
+ getrlimit(RLIMIT_CORE, &rlp);
+ rlp.rlim_cur = MAX(16*1024*1024,rlp.rlim_cur);
+ setrlimit(RLIMIT_CORE, &rlp);
+ getrlimit(RLIMIT_CORE, &rlp);
+ DEBUG(3,("Maximum core file size limits now %d(soft) %d(hard)\n",
+ (int)rlp.rlim_cur,(int)rlp.rlim_max));
+ }
+#endif
+#endif
+
+#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
+ /* On Linux we lose the ability to dump core when we change our user
+ * ID. We know how to dump core safely, so let's make sure we have our
+ * dumpable flag set.
+ */
+ prctl(PR_SET_DUMPABLE, 1);
+#endif
+
+ /* FIXME: if we have a core-plus-pid facility, configurably set
+ * this up here.
+ */
+}
+
+ void dump_core(void)
+{
+ 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));
+ DEBUGADD(0, ("refusing to dump core\n"));
+ exit(1);
+ }
+
+ DEBUG(0,("dumping core in %s\n", corepath));
+ }
+
+ umask(~(0700));
+ dbgflush();
+
+ /* Ensure we don't have a signal handler for abort. */
+#ifdef SIGABRT
+ CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
+#endif
+
+ abort();
+}
+
diff --git a/source/lib/gencache.c b/source/lib/gencache.c
index fd44616270c..6725ed4c120 100644
--- a/source/lib/gencache.c
+++ b/source/lib/gencache.c
@@ -268,7 +268,7 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
SAFE_FREE(entry_buf);
DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
- "timeout = %s\n", t > time(NULL) ? "valid" :
+ "timeout = %s", t > time(NULL) ? "valid" :
"expired", keystr, v, ctime(&t)));
if (valstr)
@@ -281,20 +281,18 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
return t > time(NULL);
- } else {
- SAFE_FREE(databuf.dptr);
+ }
- if (valstr)
- *valstr = NULL;
+ SAFE_FREE(databuf.dptr);
- if (timeout)
- timeout = NULL;
+ if (valstr)
+ *valstr = NULL;
+ if (timeout)
+ timeout = NULL;
- DEBUG(10, ("Cache entry with key = %s couldn't be found\n",
- keystr));
+ DEBUG(10, ("Cache entry with key = %s couldn't be found\n", keystr));
- return False;
- }
+ return False;
}
@@ -374,7 +372,7 @@ int gencache_lock_entry( const char *key )
if (!gencache_init())
return -1;
- return tdb_lock_bystring(cache, key, 0);
+ return tdb_lock_bystring(cache, key);
}
/********************************************************************
diff --git a/source/lib/genrand.c b/source/lib/genrand.c
index f37bbc9c2fd..1897b86818b 100644
--- a/source/lib/genrand.c
+++ b/source/lib/genrand.c
@@ -114,14 +114,14 @@ static int do_reseed(BOOL use_fd, int fd)
* seriously this will be secret.
*/
- pw = getpwnam_alloc("root");
+ pw = getpwnam_alloc(NULL, "root");
if (pw && pw->pw_passwd) {
size_t i;
unsigned char md4_tmp[16];
mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd));
for (i=0;i<16;i++)
seed_inbuf[8+i] ^= md4_tmp[i];
- passwd_free(&pw);
+ TALLOC_FREE(pw);
}
/*
diff --git a/source/lib/hmacmd5.c b/source/lib/hmacmd5.c
index f436fd30c0e..a9b7d4d57f9 100644
--- a/source/lib/hmacmd5.c
+++ b/source/lib/hmacmd5.c
@@ -28,14 +28,14 @@
/***********************************************************************
the rfc 2104 version of hmac_md5 initialisation.
***********************************************************************/
-void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx)
+
+void hmac_md5_init_rfc2104(const unsigned char *key, int key_len, HMACMD5Context *ctx)
{
int i;
+ unsigned char tk[16];
/* if key is longer than 64 bytes reset it to key=MD5(key) */
- if (key_len > 64)
- {
- uchar tk[16];
+ if (key_len > 64) {
struct MD5Context tctx;
MD5Init(&tctx);
@@ -53,8 +53,7 @@ void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx)
memcpy( ctx->k_opad, key, key_len);
/* XOR key with ipad and opad values */
- for (i=0; i<64; i++)
- {
+ for (i=0; i<64; i++) {
ctx->k_ipad[i] ^= 0x36;
ctx->k_opad[i] ^= 0x5c;
}
@@ -66,14 +65,14 @@ void hmac_md5_init_rfc2104(uchar* key, int key_len, HMACMD5Context *ctx)
/***********************************************************************
the microsoft version of hmac_md5 initialisation.
***********************************************************************/
-void hmac_md5_init_limK_to_64(const uchar* key, int key_len,
+
+void hmac_md5_init_limK_to_64(const unsigned char* key, int key_len,
HMACMD5Context *ctx)
{
int i;
/* if key is longer than 64 bytes truncate it */
- if (key_len > 64)
- {
+ if (key_len > 64) {
key_len = 64;
}
@@ -96,7 +95,8 @@ void hmac_md5_init_limK_to_64(const uchar* key, int key_len,
/***********************************************************************
update hmac_md5 "inner" buffer
***********************************************************************/
-void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx)
+
+void hmac_md5_update(const unsigned char *text, int text_len, HMACMD5Context *ctx)
{
MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */
}
@@ -104,7 +104,7 @@ void hmac_md5_update(const uchar* text, int text_len, HMACMD5Context *ctx)
/***********************************************************************
finish off hmac_md5 "inner" buffer and generate outer one.
***********************************************************************/
-void hmac_md5_final(uchar *digest, HMACMD5Context *ctx)
+void hmac_md5_final(unsigned char *digest, HMACMD5Context *ctx)
{
struct MD5Context ctx_o;
@@ -121,7 +121,8 @@ void hmac_md5_final(uchar *digest, HMACMD5Context *ctx)
single function to calculate an HMAC MD5 digest from data.
use the microsoft hmacmd5 init method because the key is 16 bytes.
************************************************************/
-void hmac_md5( uchar key[16], uchar* data, int data_len, uchar* digest)
+
+void hmac_md5( unsigned char key[16], unsigned char *data, int data_len, unsigned char *digest)
{
HMACMD5Context ctx;
hmac_md5_init_limK_to_64(key, 16, &ctx);
diff --git a/source/lib/ldap_escape.c b/source/lib/ldap_escape.c
index 6c4e8b8c837..3feb0e0c44e 100644
--- a/source/lib/ldap_escape.c
+++ b/source/lib/ldap_escape.c
@@ -37,7 +37,6 @@ char *escape_ldap_string_alloc(const char *s)
{
size_t len = strlen(s)+1;
char *output = SMB_MALLOC(len);
- char *output_tmp;
const char *sub;
int i = 0;
char *p = output;
@@ -65,12 +64,10 @@ char *escape_ldap_string_alloc(const char *s)
if (sub) {
len = len + 3;
- output_tmp = SMB_REALLOC(output, len);
- if (!output_tmp) {
- SAFE_FREE(output);
+ output = SMB_REALLOC(output, len);
+ if (!output) {
return NULL;
}
- output = output_tmp;
p = &output[i];
strncpy (p, sub, 3);
diff --git a/source/lib/messages.c b/source/lib/messages.c
index 058bbc99b0b..cd2a3b36b6e 100644
--- a/source/lib/messages.c
+++ b/source/lib/messages.c
@@ -70,6 +70,24 @@ static struct dispatch_fns {
} *dispatch_fns;
/****************************************************************************
+ Free global objects.
+****************************************************************************/
+
+void gfree_messsges(void)
+{
+ struct dispatch_fns *dfn, *next;
+
+ /* delete the dispatch_fns list */
+ dfn = dispatch_fns;
+ while( dfn ) {
+ next = dfn->next;
+ DLIST_REMOVE(dispatch_fns, dfn);
+ SAFE_FREE(dfn);
+ dfn = next;
+ }
+}
+
+/****************************************************************************
Notifications come in as signals.
****************************************************************************/
@@ -604,4 +622,19 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
*n_sent = msg_all.n_sent;
return True;
}
+
+/*
+ * Block and unblock receiving of messages. Allows removal of race conditions
+ * when doing a fork and changing message disposition.
+ */
+
+void message_block(void)
+{
+ BlockSignals(True, SIGUSR1);
+}
+
+void message_unblock(void)
+{
+ BlockSignals(False, SIGUSR1);
+}
/** @} **/
diff --git a/source/lib/pam_errors.c b/source/lib/pam_errors.c
index 212d3831fd5..8a4c41d7df5 100644
--- a/source/lib/pam_errors.c
+++ b/source/lib/pam_errors.c
@@ -71,6 +71,7 @@ static const struct {
{NT_STATUS_PASSWORD_MUST_CHANGE, PAM_NEW_AUTHTOK_REQD},
{NT_STATUS_ACCOUNT_LOCKED_OUT, PAM_MAXTRIES},
{NT_STATUS_NO_MEMORY, PAM_BUF_ERR},
+ {NT_STATUS_PASSWORD_RESTRICTION, PAM_PERM_DENIED},
{NT_STATUS_OK, PAM_SUCCESS}
};
diff --git a/source/lib/pidfile.c b/source/lib/pidfile.c
index b041eb7f1b2..08e41083b59 100644
--- a/source/lib/pidfile.c
+++ b/source/lib/pidfile.c
@@ -32,7 +32,8 @@ pid_t pidfile_pid(const char *name)
{
int fd;
char pidstr[20];
- unsigned ret;
+ pid_t pid;
+ unsigned int ret;
pstring pidFile;
slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name);
@@ -57,7 +58,8 @@ pid_t pidfile_pid(const char *name)
goto noproc;
}
- if (!process_exists_by_pid(ret)) {
+ pid = (pid_t)ret;
+ if (!process_exists_by_pid(pid)) {
goto noproc;
}
diff --git a/source/lib/privileges.c b/source/lib/privileges.c
index ee69613df0e..d77d7857d72 100644
--- a/source/lib/privileges.c
+++ b/source/lib/privileges.c
@@ -867,9 +867,27 @@ BOOL privilege_set_to_se_priv( SE_PRIV *mask, PRIVILEGE_SET *privset )
/*******************************************************************
*******************************************************************/
-BOOL is_privileged_sid( DOM_SID *sid )
+BOOL is_privileged_sid( const DOM_SID *sid )
{
SE_PRIV mask;
return get_privileges( sid, &mask );
}
+
+/*******************************************************************
+*******************************************************************/
+
+BOOL grant_all_privileges( const DOM_SID *sid )
+{
+ int i;
+ SE_PRIV mask;
+ uint32 num_privs = count_all_privileges();
+
+ se_priv_copy( &mask, &se_priv_none );
+
+ for ( i=0; i<num_privs; i++ ) {
+ se_priv_add(&mask, &privs[i].se_priv);
+ }
+
+ return grant_privilege( sid, &mask );
+}
diff --git a/source/lib/readline.c b/source/lib/readline.c
index 78b99fd7fb0..c1f1dc7f400 100644
--- a/source/lib/readline.c
+++ b/source/lib/readline.c
@@ -50,7 +50,7 @@
Display the prompt and wait for input. Call callback() regularly
****************************************************************************/
-static char *smb_readline_replacement(char *prompt, void (*callback)(void),
+static char *smb_readline_replacement(const char *prompt, void (*callback)(void),
char **(completion_fn)(const char *text, int start, int end))
{
fd_set fds;
@@ -82,7 +82,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void),
Display the prompt and wait for input. Call callback() regularly.
****************************************************************************/
-char *smb_readline(char *prompt, void (*callback)(void),
+char *smb_readline(const char *prompt, void (*callback)(void),
char **(completion_fn)(const char *text, int start, int end))
{
#if HAVE_LIBREADLINE
diff --git a/source/lib/repdir.c b/source/lib/repdir.c
new file mode 100644
index 00000000000..b920fe4b0cc
--- /dev/null
+++ b/source/lib/repdir.c
@@ -0,0 +1,218 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Tridgell 2005
+ Updated for Samba3 64-bit cleanliness (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.
+*/
+/*
+ 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 <include/includes.h>
+
+ void replace_readdir_dummy(void);
+ void replace_readdir_dummy(void) {}
+
+#if defined(REPLACE_READDIR)
+
+#if defined(PARANOID_MALLOC_CHECKER)
+#ifdef malloc
+#undef malloc
+#endif
+#endif
+
+#define DIR_BUF_BITS 9
+#define DIR_BUF_SIZE (1<<DIR_BUF_BITS)
+
+struct dir_buf {
+ int fd;
+ int nbytes, ofs;
+ SMB_OFF_T seekpos;
+ char buf[DIR_BUF_SIZE];
+};
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
+ SMB_STRUCT_DIR *opendir64(const char *dname)
+#else
+ SMB_STRUCT_DIR *opendir(const char *dname)
+#endif
+{
+ struct dir_buf *d;
+ d = malloc(sizeof(*d));
+ if (d == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
+ d->fd = open64(dname, O_RDONLY);
+#else
+ d->fd = open(dname, O_RDONLY);
+#endif
+
+ if (d->fd == -1) {
+ free(d);
+ return NULL;
+ }
+ d->ofs = 0;
+ d->seekpos = 0;
+ d->nbytes = 0;
+ return (SMB_STRUCT_DIR *)d;
+}
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
+ SMB_STRUCT_DIRENT *readdir64(SMB_STRUCT_DIR *dir)
+#else
+ SMB_STRUCT_DIRENT *readdir(SMB_STRUCT_DIR *dir)
+#endif
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ SMB_STRUCT_DIRENT *de;
+
+ if (d->ofs >= d->nbytes) {
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_LSEEK64)
+ d->seekpos = lseek64(d->fd, 0, SEEK_CUR);
+#else
+ d->seekpos = lseek(d->fd, 0, SEEK_CUR);
+#endif
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_GETDENTS64)
+ d->nbytes = getdents64(d->fd, d->buf, DIR_BUF_SIZE);
+#else
+ d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE);
+#endif
+ d->ofs = 0;
+ }
+ if (d->ofs >= d->nbytes) {
+ return NULL;
+ }
+ de = (SMB_STRUCT_DIRENT *)&d->buf[d->ofs];
+ d->ofs += de->d_reclen;
+ return de;
+}
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
+ long telldir64(SMB_STRUCT_DIR *dir)
+#else
+ long telldir(SMB_STRUCT_DIR *dir)
+#endif
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ if (d->ofs >= d->nbytes) {
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_LSEEK64)
+ d->seekpos = lseek64(d->fd, 0, SEEK_CUR);
+#else
+ d->seekpos = lseek(d->fd, 0, SEEK_CUR);
+#endif
+ 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;
+}
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
+ void seekdir64(SMB_STRUCT_DIR *dir, long ofs)
+#else
+ void seekdir(SMB_STRUCT_DIR *dir, long ofs)
+#endif
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_LSEEK64)
+ d->seekpos = lseek64(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET);
+#else
+ d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET);
+#endif
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_GETDENTS64)
+ d->nbytes = getdents64(d->fd, d->buf, DIR_BUF_SIZE);
+#else
+ d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE);
+#endif
+
+ d->ofs = 0;
+ while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) {
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
+ if (readdir64(dir) == NULL) break;
+#else
+ if (readdir(dir) == NULL) break;
+#endif
+ }
+}
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
+ void rewinddir64(SMB_STRUCT_DIR *dir)
+#else
+ void rewinddir(SMB_STRUCT_DIR *dir)
+#endif
+{
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
+ seekdir64(dir, 0);
+#else
+ seekdir(dir, 0);
+#endif
+}
+
+#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
+ int closedir64(SMB_STRUCT_DIR *dir)
+#else
+ int closedir(SMB_STRUCT_DIR *dir)
+#endif
+{
+ 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(SMB_STRUCT_DIR *dir)
+{
+ struct dir_buf *d = (struct dir_buf *)dir;
+ return d->fd;
+}
+#endif
+#endif /* REPLACE_READDIR */
diff --git a/source/lib/secace.c b/source/lib/secace.c
index b2cf81d0fd0..f1d4d99cc16 100644
--- a/source/lib/secace.c
+++ b/source/lib/secace.c
@@ -149,7 +149,13 @@ BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
{
/* Trivial case */
- if (!s1 && !s2) return True;
+ if (!s1 && !s2) {
+ return True;
+ }
+
+ if (!s1 || !s2) {
+ return False;
+ }
/* Check top level stuff */
diff --git a/source/lib/secdesc.c b/source/lib/secdesc.c
index ace0aee8664..f8873277cf8 100644
--- a/source/lib/secdesc.c
+++ b/source/lib/secdesc.c
@@ -23,6 +23,15 @@
#include "includes.h"
+/* Map generic permissions to file object specific permissions */
+
+struct generic_mapping file_generic_mapping = {
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE,
+ FILE_GENERIC_ALL
+};
+
/*******************************************************************
Works out the linearization size of a SEC_DESC.
********************************************************************/
@@ -64,6 +73,10 @@ BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
goto done;
}
+ if (!s1 || !s2) {
+ return False;
+ }
+
/* Check top level stuff */
if (s1->revision != s2->revision) {
@@ -323,11 +336,11 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32
SEC_ACE *ace = 0;
NTSTATUS status;
- *sd_size = 0;
-
if (!ctx || !psd || !sid || !sd_size)
return NT_STATUS_INVALID_PARAMETER;
+ *sd_size = 0;
+
status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
if (!NT_STATUS_IS_OK(status))
@@ -375,11 +388,11 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t
SEC_ACE *ace = 0;
NTSTATUS status;
- *sd_size = 0;
-
if (!ctx || !psd[0] || !sid || !sd_size)
return NT_STATUS_INVALID_PARAMETER;
+ *sd_size = 0;
+
status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
if (!NT_STATUS_IS_OK(status))
@@ -420,7 +433,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces)))
return NULL;
- for (i = 0; the_acl && i < the_acl->num_aces; i++) {
+ for (i = 0; i < the_acl->num_aces; i++) {
SEC_ACE *ace = &the_acl->ace[i];
SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
uint8 new_flags = 0;
@@ -520,3 +533,4 @@ void init_sec_access(SEC_ACCESS *t, uint32 mask)
t->mask = mask;
}
+
diff --git a/source/lib/sendfile.c b/source/lib/sendfile.c
index f9f33b8f35e..f4f6e16526f 100644
--- a/source/lib/sendfile.c
+++ b/source/lib/sendfile.c
@@ -404,7 +404,6 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of
ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
{
- size_t total=0;
struct sf_parms hdtrl;
/* Set up the header/trailer struct params. */
diff --git a/source/lib/sharesec.c b/source/lib/sharesec.c
new file mode 100644
index 00000000000..8105d5c37a6
--- /dev/null
+++ b/source/lib/sharesec.c
@@ -0,0 +1,308 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * SEC_DESC handling functions
+ * Copyright (C) Jeremy R. Allison 1995-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"
+
+/*******************************************************************
+ Create the share security tdb.
+ ********************************************************************/
+
+static TDB_CONTEXT *share_tdb; /* used for share security descriptors */
+#define SHARE_DATABASE_VERSION_V1 1
+#define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */
+
+/* Map generic permissions to file object specific permissions */
+
+static struct generic_mapping file_generic_mapping = {
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE,
+ FILE_GENERIC_ALL
+};
+
+
+BOOL share_info_db_init(void)
+{
+ const char *vstring = "INFO/version";
+ int32 vers_id;
+
+ if (share_tdb) {
+ return True;
+ }
+
+ share_tdb = tdb_open_log(lock_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+ if (!share_tdb) {
+ DEBUG(0,("Failed to open share info database %s (%s)\n",
+ lock_path("share_info.tdb"), strerror(errno) ));
+ return False;
+ }
+
+ /* handle a Samba upgrade */
+ tdb_lock_bystring(share_tdb, vstring);
+
+ /* Cope with byte-reversed older versions of the db. */
+ vers_id = tdb_fetch_int32(share_tdb, vstring);
+ if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) {
+ /* Written on a bigendian machine with old fetch_int code. Save as le. */
+ tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
+ vers_id = SHARE_DATABASE_VERSION_V2;
+ }
+
+ if (vers_id != SHARE_DATABASE_VERSION_V2) {
+ tdb_traverse(share_tdb, tdb_traverse_delete_fn, NULL);
+ tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
+ }
+ tdb_unlock_bystring(share_tdb, vstring);
+
+ return True;
+}
+
+/*******************************************************************
+ Fake up a Everyone, default access as a default.
+ def_access is a GENERIC_XXX access mode.
+ ********************************************************************/
+
+SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def_access)
+{
+ SEC_ACCESS sa;
+ SEC_ACE ace;
+ SEC_ACL *psa = NULL;
+ SEC_DESC *psd = NULL;
+ uint32 spec_access = def_access;
+
+ se_map_generic(&spec_access, &file_generic_mapping);
+
+ init_sec_access(&sa, def_access | spec_access );
+ init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
+ psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize);
+ }
+
+ if (!psd) {
+ DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
+ return NULL;
+ }
+
+ return psd;
+}
+
+/*******************************************************************
+ Pull a security descriptor from the share tdb.
+ ********************************************************************/
+
+SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
+{
+ prs_struct ps;
+ fstring key;
+ SEC_DESC *psd = NULL;
+
+ if (!share_info_db_init()) {
+ return NULL;
+ }
+
+ *psize = 0;
+
+ /* Fetch security descriptor from tdb */
+
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+
+ 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) ));
+
+ return get_share_security_default(ctx, psize, GENERIC_ALL_ACCESS);
+ }
+
+ if (psd)
+ *psize = sec_desc_size(psd);
+
+ prs_mem_free(&ps);
+ return psd;
+}
+
+/*******************************************************************
+ Store a security descriptor in the share db.
+ ********************************************************************/
+
+BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
+{
+ prs_struct ps;
+ TALLOC_CTX *mem_ctx = NULL;
+ fstring key;
+ BOOL ret = False;
+
+ if (!share_info_db_init()) {
+ return False;
+ }
+
+ mem_ctx = talloc_init("set_share_security");
+ if (mem_ctx == NULL)
+ return False;
+
+ prs_init(&ps, (uint32)sec_desc_size(psd), mem_ctx, MARSHALL);
+
+ if (!sec_io_desc("share_security", &psd, &ps, 1))
+ goto out;
+
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name);
+
+ if (tdb_prs_store(share_tdb, key, &ps)==0) {
+ ret = True;
+ DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name ));
+ } else {
+ DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name ));
+ }
+
+ /* Free malloc'ed memory */
+
+out:
+
+ prs_mem_free(&ps);
+ if (mem_ctx)
+ talloc_destroy(mem_ctx);
+ return ret;
+}
+
+/*******************************************************************
+ Delete a security descriptor.
+********************************************************************/
+
+BOOL delete_share_security(int snum)
+{
+ TDB_DATA kbuf;
+ fstring key;
+
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+ kbuf.dptr = key;
+ kbuf.dsize = strlen(key)+1;
+
+ if (tdb_delete(share_tdb, kbuf) != 0) {
+ DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n",
+ lp_servicename(snum) ));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ Parse the contents of an acl string from a usershare file.
+***************************************************************************/
+
+BOOL parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd)
+{
+ size_t s_size = 0;
+ const char *pacl = acl_str;
+ int num_aces = 0;
+ SEC_ACE *ace_list = NULL;
+ SEC_ACL *psa = NULL;
+ SEC_DESC *psd = NULL;
+ size_t sd_size = 0;
+ int i;
+
+ *ppsd = NULL;
+
+ /* If the acl string is blank return "Everyone:R" */
+ if (!*acl_str) {
+ SEC_DESC *default_psd = get_share_security_default(ctx, &s_size, GENERIC_READ_ACCESS);
+ if (!default_psd) {
+ return False;
+ }
+ *ppsd = default_psd;
+ return True;
+ }
+
+ num_aces = 1;
+
+ /* Add the number of ',' characters to get the number of aces. */
+ num_aces += count_chars(pacl,',');
+
+ ace_list = TALLOC_ARRAY(ctx, SEC_ACE, num_aces);
+ if (!ace_list) {
+ return False;
+ }
+
+ for (i = 0; i < num_aces; i++) {
+ SEC_ACCESS sa;
+ uint32 g_access;
+ uint32 s_access;
+ DOM_SID sid;
+ fstring sidstr;
+ uint8 type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+
+ if (!next_token(&pacl, sidstr, ":", sizeof(sidstr))) {
+ DEBUG(0,("parse_usershare_acl: malformed usershare acl looking "
+ "for ':' in string '%s'\n", pacl));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, sidstr)) {
+ DEBUG(0,("parse_usershare_acl: failed to convert %s to sid.\n",
+ sidstr ));
+ return False;
+ }
+
+ switch (*pacl) {
+ case 'F': /* Full Control, ie. R+W */
+ case 'f': /* Full Control, ie. R+W */
+ s_access = g_access = GENERIC_ALL_ACCESS;
+ break;
+ case 'R': /* Read only. */
+ case 'r': /* Read only. */
+ s_access = g_access = GENERIC_READ_ACCESS;
+ break;
+ case 'D': /* Deny all to this SID. */
+ case 'd': /* Deny all to this SID. */
+ type = SEC_ACE_TYPE_ACCESS_DENIED;
+ s_access = g_access = GENERIC_ALL_ACCESS;
+ break;
+ default:
+ DEBUG(0,("parse_usershare_acl: unknown acl type at %s.\n",
+ pacl ));
+ return False;
+ }
+
+ pacl++;
+ if (*pacl && *pacl != ',') {
+ DEBUG(0,("parse_usershare_acl: bad acl string at %s.\n",
+ pacl ));
+ return False;
+ }
+ pacl++; /* Go past any ',' */
+
+ se_map_generic(&s_access, &file_generic_mapping);
+ init_sec_access(&sa, g_access | s_access );
+ init_sec_ace(&ace_list[i], &sid, type, sa, 0);
+ }
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, num_aces, ace_list)) != NULL) {
+ psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, &sd_size);
+ }
+
+ if (!psd) {
+ DEBUG(0,("parse_usershare_acl: Failed to make SEC_DESC.\n"));
+ return False;
+ }
+
+ *ppsd = psd;
+ return True;
+}
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index 609816b8774..e4cb25104ba 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -230,7 +230,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
Return the list of attribute names from a mapping table
**********************************************************************/
- const char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
+ const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] )
{
const char **names;
int i = 0;
@@ -239,7 +239,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
i++;
i++;
- names = SMB_MALLOC_ARRAY( const char*, i );
+ names = TALLOC_ARRAY( mem_ctx, const char*, i );
if ( !names ) {
DEBUG(0,("get_attr_list: out of memory\n"));
return NULL;
@@ -247,7 +247,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
i = 0;
while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
- names[i] = SMB_STRDUP( table[i].name );
+ names[i] = talloc_strdup( names, table[i].name );
i++;
}
names[i] = NULL;
@@ -255,29 +255,6 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
return names;
}
-/*********************************************************************
- Cleanup
- ********************************************************************/
-
- void free_attr_list( const char **list )
-{
- int i = 0;
-
- if ( !list )
- return;
-
- while ( list[i] ) {
- /* SAFE_FREE generates a warning here that can't be gotten rid
- * of with CONST_DISCARD */
- if (list[i] != NULL) {
- free(CONST_DISCARD(char *, list[i]));
- }
- i+=1;
- }
-
- SAFE_FREE( list );
-}
-
/*******************************************************************
Search an attribute and return the first value found.
******************************************************************/
@@ -321,6 +298,88 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
sizeof(pstring));
}
+ char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
+ const char *attribute,
+ TALLOC_CTX *mem_ctx)
+{
+ char **values;
+ char *result;
+
+ if (attribute == NULL) {
+ return NULL;
+ }
+
+ values = ldap_get_values(ldap_struct, entry, attribute);
+
+ if (values == NULL) {
+ DEBUG(10, ("attribute %s does not exist\n", attribute));
+ return NULL;
+ }
+
+ if (ldap_count_values(values) != 1) {
+ DEBUG(10, ("attribute %s has %d values, expected only one\n",
+ attribute, ldap_count_values(values)));
+ ldap_value_free(values);
+ return NULL;
+ }
+
+ if (pull_utf8_talloc(mem_ctx, &result, values[0]) < 0) {
+ DEBUG(10, ("pull_utf8_talloc failed\n"));
+ ldap_value_free(values);
+ return NULL;
+ }
+
+ ldap_value_free(values);
+
+#ifdef DEBUG_PASSWORDS
+ DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
+ attribute, result));
+#endif
+ return result;
+}
+
+ static int ldapmsg_destructor(void *p) {
+ LDAPMessage **result = talloc_get_type_abort(p, LDAPMessage *);
+ ldap_msgfree(*result);
+ return 0;
+}
+
+ void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
+{
+ LDAPMessage **handle;
+
+ if (result == NULL) {
+ return;
+ }
+
+ handle = TALLOC_P(mem_ctx, LDAPMessage *);
+ SMB_ASSERT(handle != NULL);
+
+ *handle = result;
+ 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);
+ return 0;
+}
+
+ void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
+{
+ LDAPMod ***handle;
+
+ if (mod == NULL) {
+ return;
+ }
+
+ handle = TALLOC_P(mem_ctx, LDAPMod **);
+ SMB_ASSERT(handle != NULL);
+
+ *handle = mod;
+ talloc_set_destructor(handle, ldapmod_destructor);
+}
+
/************************************************************************
Routine to manage the LDAPMod structure array
manage memory used by the array, by each struct, and values
@@ -349,8 +408,9 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
if (mods == NULL) {
mods = SMB_MALLOC_P(LDAPMod *);
if (mods == NULL) {
- DEBUG(0, ("make_a_mod: out of memory!\n"));
- return;
+ smb_panic("smbldap_set_mod: out of memory!\n");
+ /* notreached. */
+ abort();
}
mods[0] = NULL;
}
@@ -363,13 +423,15 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
if (mods[i] == NULL) {
mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
if (mods == NULL) {
- DEBUG(0, ("make_a_mod: out of memory!\n"));
- return;
+ smb_panic("smbldap_set_mod: out of memory!\n");
+ /* notreached. */
+ abort();
}
mods[i] = SMB_MALLOC_P(LDAPMod);
if (mods[i] == NULL) {
- DEBUG(0, ("make_a_mod: out of memory!\n"));
- return;
+ smb_panic("smbldap_set_mod: out of memory!\n");
+ /* notreached. */
+ abort();
}
mods[i]->mod_op = modop;
mods[i]->mod_values = NULL;
@@ -387,13 +449,15 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
if (mods[i]->mod_values == NULL) {
- DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
- return;
+ smb_panic("smbldap_set_mod: out of memory!\n");
+ /* notreached. */
+ abort();
}
if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) {
- DEBUG (0, ("make_a_mod: String conversion failure!\n"));
- return;
+ smb_panic("smbldap_set_mod: String conversion failure!\n");
+ /* notreached. */
+ abort();
}
mods[i]->mod_values[j] = utf8_value;
@@ -794,8 +858,27 @@ static int rebindproc_connect_with_state (LDAP *ldap_struct,
username and password to? */
rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
-
- GetTimeOfDay(&ldap_state->last_rebind);
+
+ /* only set the last rebind timestamp when we did rebind after a
+ * non-read LDAP operation. That way we avoid the replication sleep
+ * after a simple redirected search operation - Guenther */
+
+ switch (request) {
+
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_DELETE:
+ case LDAP_REQ_MODDN:
+ case LDAP_REQ_EXTENDED:
+ DEBUG(10,("rebindproc_connect_with_state: "
+ "setting last_rebind timestamp "
+ "(req: 0x%02x)\n", (unsigned int)request));
+ GetTimeOfDay(&ldap_state->last_rebind);
+ break;
+ default:
+ ZERO_STRUCT(ldap_state->last_rebind);
+ break;
+ }
return rc;
}
@@ -940,7 +1023,7 @@ static int smbldap_open(struct smbldap_state *ldap_state)
#endif
if (reopen) {
/* the other end has died. reopen. */
- ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
+ ldap_unbind(ldap_state->ldap_struct);
ldap_state->ldap_struct = NULL;
ldap_state->last_ping = (time_t)0;
} else {
@@ -958,7 +1041,7 @@ static int smbldap_open(struct smbldap_state *ldap_state)
}
if ((rc = smbldap_connect_system(ldap_state, ldap_state->ldap_struct))) {
- ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
+ ldap_unbind(ldap_state->ldap_struct);
ldap_state->ldap_struct = NULL;
return rc;
}
@@ -980,7 +1063,7 @@ static NTSTATUS smbldap_close(struct smbldap_state *ldap_state)
return NT_STATUS_INVALID_PARAMETER;
if (ldap_state->ldap_struct != NULL) {
- ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
+ ldap_unbind(ldap_state->ldap_struct);
ldap_state->ldap_struct = NULL;
}
@@ -1041,6 +1124,14 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
return True;
}
+ if (open_rc == LDAP_INSUFFICIENT_ACCESS) {
+ /* The fact that we are non-root or any other
+ * access-denied condition will not change in the next
+ * round of trying */
+ *rc = open_rc;
+ break;
+ }
+
if (got_alarm) {
*rc = LDAP_TIMEOUT;
break;
@@ -1123,12 +1214,22 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state,
alarm(lp_ldap_timeout());
/* End setup timeout. */
- while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope,
utf8_filter,
CONST_DISCARD(char **, attrs),
attrsonly, sctrls, cctrls, &timeout,
sizelimit, res);
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ 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"));
+ SAFE_FREE(ld_error);
+ }
+ }
SAFE_FREE(utf8_filter);
@@ -1257,8 +1358,18 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
return LDAP_NO_MEMORY;
}
- while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ 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"));
+ SAFE_FREE(ld_error);
+ }
+ }
SAFE_FREE(utf8_dn);
return rc;
@@ -1279,8 +1390,18 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
return LDAP_NO_MEMORY;
}
- while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ 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"));
+ SAFE_FREE(ld_error);
+ }
+ }
SAFE_FREE(utf8_dn);
return rc;
@@ -1301,8 +1422,18 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
return LDAP_NO_MEMORY;
}
- while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ 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"));
+ SAFE_FREE(ld_error);
+ }
+ }
SAFE_FREE(utf8_dn);
return rc;
@@ -1320,34 +1451,33 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
if (!ldap_state)
return (-1);
- while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
reqdata, serverctrls,
clientctrls, retoidp, retdatap);
+ if (rc != LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ 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"));
+ SAFE_FREE(ld_error);
+ }
+ }
+
return rc;
}
/*******************************************************************
run the search by name.
******************************************************************/
-int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter,
- const char **search_attr, LDAPMessage ** result)
+int smbldap_search_suffix (struct smbldap_state *ldap_state,
+ const char *filter, const char **search_attr,
+ LDAPMessage ** result)
{
- int scope = LDAP_SCOPE_SUBTREE;
- int rc;
-
- rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n",
- ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
- SAFE_FREE(ld_error);
- }
-
- return rc;
+ return smbldap_search(ldap_state, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE,
+ filter, search_attr, 0, result);
}
static void smbldap_idle_fn(void **data, time_t *interval, time_t now)
@@ -1442,6 +1572,25 @@ char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry)
return unix_dn;
}
+ const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
+ LDAPMessage *entry)
+{
+ char *utf8_dn, *unix_dn;
+
+ utf8_dn = ldap_get_dn(ld, entry);
+ if (!utf8_dn) {
+ DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n"));
+ return NULL;
+ }
+ if (pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn) == (size_t)-1) {
+ DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 "
+ "[%s]\n", utf8_dn));
+ return NULL;
+ }
+ ldap_memfree(utf8_dn);
+ return unix_dn;
+}
+
/*******************************************************************
Check if root-dse has a certain Control or Extension
********************************************************************/
diff --git a/source/lib/smbldap_util.c b/source/lib/smbldap_util.c
index 4679b864874..aff4eff6f6d 100644
--- a/source/lib/smbldap_util.c
+++ b/source/lib/smbldap_util.c
@@ -29,6 +29,7 @@
/**********************************************************************
Add the account-policies below the sambaDomain object to LDAP,
*********************************************************************/
+
static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state,
const char *domain_name)
{
@@ -39,7 +40,7 @@ static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state
pstring dn;
LDAPMod **mods = NULL;
- DEBUG(3,("Adding new account policies for domain\n"));
+ DEBUG(3,("add_new_domain_account_policies: Adding new account policies for domain\n"));
pstr_sprintf(dn, "%s=%s,%s",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
@@ -71,7 +72,7 @@ static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state
if (rc!=LDAP_SUCCESS) {
char *ld_error = NULL;
ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(1,("failed to add account policies to dn= %s with: %s\n\t%s\n",
+ DEBUG(1,("add_new_domain_account_policies: failed to add account policies to dn= %s with: %s\n\t%s\n",
dn, ldap_err2string(rc),
ld_error ? ld_error : "unknown"));
SAFE_FREE(ld_error);
@@ -91,6 +92,7 @@ static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state
TODO: Add other attributes, and allow modification.
*********************************************************************/
+
static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
const char *domain_name)
{
@@ -99,21 +101,17 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
pstring filter, dn;
LDAPMod **mods = NULL;
int rc;
- int ldap_op;
LDAPMessage *result = NULL;
int num_result;
const char **attr_list;
- uid_t u_low, u_high;
- gid_t g_low, g_high;
- uint32 rid_low, rid_high;
slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
domain_name, LDAP_OBJ_DOMINFO);
- attr_list = get_attr_list( dominfo_attr_list );
+ attr_list = get_attr_list( NULL, dominfo_attr_list );
rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
@@ -122,87 +120,79 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
num_result = ldap_count_entries(ldap_state->ldap_struct, result);
if (num_result > 1) {
- DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
+ DEBUG (0, ("add_new_domain_info: More than domain with that name exists: bailing "
+ "out!\n"));
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
/* Check if we need to add an entry */
- DEBUG(3,("Adding new domain\n"));
- ldap_op = LDAP_MOD_ADD;
+ DEBUG(3,("add_new_domain_info: Adding new domain\n"));
- pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- domain_name, lp_ldap_suffix());
+ pstr_sprintf(dn, "%s=%s,%s",
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ domain_name, lp_ldap_suffix());
/* Free original search */
ldap_msgfree(result);
- /* make the changes - the entry *must* not already have samba attributes */
- smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
- domain_name);
+ /* make the changes - the entry *must* not already have samba
+ * attributes */
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list,
+ LDAP_ATTR_DOMAIN),
+ domain_name);
- /* If we don't have an entry, then ask secrets.tdb for what it thinks.
+ /* If we don't have an entry, then ask secrets.tdb for what it thinks.
It may choose to make it up */
sid_to_string(sid_string, get_global_sam_sid());
- smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string);
-
- slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base());
- smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list,
+ LDAP_ATTR_DOM_SID),
+ sid_string);
+
+ slprintf(algorithmic_rid_base_string,
+ sizeof(algorithmic_rid_base_string) - 1, "%i",
+ algorithmic_rid_base());
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list,
+ LDAP_ATTR_ALGORITHMIC_RID_BASE),
algorithmic_rid_base_string);
smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
- /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set.
- TODO: fix all the places where the line between idmap and normal operations
- needed by smbd gets fuzzy --jerry 2003-08-11 */
+ /* add the sambaNextUserRid attributes. */
- if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high)
- && get_free_rid_range(&rid_low, &rid_high) )
{
+ uint32 rid = BASE_RID;
fstring rid_str;
- fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE );
- DEBUG(10,("setting next available user rid [%s]\n", rid_str));
- smbldap_set_mod(&mods, LDAP_MOD_ADD,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- rid_str);
-
- fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE );
- DEBUG(10,("setting next available group rid [%s]\n", rid_str));
+ fstr_sprintf( rid_str, "%i", rid );
+ DEBUG(10,("add_new_domain_info: setting next available user rid [%s]\n", rid_str));
smbldap_set_mod(&mods, LDAP_MOD_ADD,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ get_attr_key2string(dominfo_attr_list,
+ LDAP_ATTR_NEXT_USERRID),
rid_str);
-
}
- switch(ldap_op)
- {
- case LDAP_MOD_ADD:
- rc = smbldap_add(ldap_state, dn, mods);
- break;
- case LDAP_MOD_REPLACE:
- rc = smbldap_modify(ldap_state, dn, mods);
- break;
- default:
- DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
+ rc = smbldap_add(ldap_state, dn, mods);
+
if (rc!=LDAP_SUCCESS) {
char *ld_error = NULL;
- ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n",
- ldap_op == LDAP_MOD_ADD ? "add" : "modify",
- dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
+ ldap_get_option(ldap_state->ldap_struct,
+ LDAP_OPT_ERROR_STRING, &ld_error);
+ DEBUG(1,("add_new_domain_info: failed to add domain dn= %s with: %s\n\t%s\n",
+ dn, ldap_err2string(rc),
+ ld_error?ld_error:"unknown"));
SAFE_FREE(ld_error);
ldap_mods_free(mods, True);
return NT_STATUS_UNSUCCESSFUL;
}
- DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name));
+ DEBUG(2,("add_new_domain_info: added: domain = %s in the LDAP database\n", domain_name));
ldap_mods_free(mods, True);
return NT_STATUS_OK;
}
@@ -210,6 +200,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
/**********************************************************************
Search for the domain info entry
*********************************************************************/
+
NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
LDAPMessage ** result, const char *domain_name,
BOOL try_add)
@@ -225,15 +216,15 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
domain_name);
- DEBUG(2, ("Searching for:[%s]\n", filter));
+ DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter));
- attr_list = get_attr_list( dominfo_attr_list );
+ attr_list = get_attr_list( NULL, dominfo_attr_list );
rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
- DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
- DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
+ DEBUG(2,("smbldap_search_domain_info: Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
+ DEBUG(2,("smbldap_search_domain_info: Query was: %s, %s\n", lp_ldap_suffix(), filter));
goto failed;
}
@@ -247,21 +238,21 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
if (count < 1) {
- DEBUG(3, ("Got no domain info entries for domain\n"));
+ DEBUG(3, ("smbldap_search_domain_info: Got no domain info entries for domain\n"));
if (!try_add)
goto failed;
status = add_new_domain_info(ldap_state, domain_name);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Adding domain info for %s failed with %s\n",
+ DEBUG(0, ("smbldap_search_domain_info: Adding domain info for %s failed with %s\n",
domain_name, nt_errstr(status)));
goto failed;
}
status = add_new_domain_account_policies(ldap_state, domain_name);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Adding domain account policies for %s failed with %s\n",
+ DEBUG(0, ("smbldap_search_domain_info: Adding domain account policies for %s failed with %s\n",
domain_name, nt_errstr(status)));
goto failed;
}
@@ -272,13 +263,11 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
if (count > 1 ) {
- DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
+ DEBUG(0, ("smbldap_search_domain_info: Got too many (%d) domain info entries for domain %s\n",
count, domain_name));
goto failed;
}
failed:
return status;
-
}
-
diff --git a/source/lib/smbrun.c b/source/lib/smbrun.c
index 6d6d7817f1a..4400aeb4433 100644
--- a/source/lib/smbrun.c
+++ b/source/lib/smbrun.c
@@ -58,13 +58,14 @@ outfd (or discard it if outfd is NULL).
int smbrun(const char *cmd, int *outfd)
{
pid_t pid;
- uid_t uid = current_user.uid;
- gid_t gid = current_user.gid;
+ uid_t uid = current_user.ut.uid;
+ gid_t gid = current_user.ut.gid;
/*
- * Lose any kernel oplock capabilities we may have.
+ * Lose any elevated privileges.
*/
- oplock_set_capability(False, False);
+ drop_effective_capability(KERNEL_OPLOCK_CAPABILITY);
+ drop_effective_capability(DMAPI_ACCESS_CAPABILITY);
/* point our stdout at the file we want output to go into */
@@ -189,14 +190,15 @@ sends the provided secret to the child stdin.
int smbrunsecret(const char *cmd, const char *secret)
{
pid_t pid;
- uid_t uid = current_user.uid;
- gid_t gid = current_user.gid;
+ uid_t uid = current_user.ut.uid;
+ gid_t gid = current_user.ut.gid;
int ifd[2];
/*
- * Lose any kernel oplock capabilities we may have.
+ * Lose any elevated privileges.
*/
- oplock_set_capability(False, False);
+ drop_effective_capability(KERNEL_OPLOCK_CAPABILITY);
+ drop_effective_capability(DMAPI_ACCESS_CAPABILITY);
/* build up an input pipe */
if(pipe(ifd)) {
diff --git a/source/lib/snprintf.c b/source/lib/snprintf.c
index a3e4b06d47f..5d89aa841fb 100644
--- a/source/lib/snprintf.c
+++ b/source/lib/snprintf.c
@@ -90,11 +90,17 @@
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
* if the C library has some snprintf functions already.
*
- * Darren Tucker (dtucker@zip.com.au)
+ * Darren Tucker (dtucker@zip.com.au) 2005
* Fix bug allowing read overruns of the source string with "%.*s"
* Usually harmless unless the read runs outside the process' allocation
* (eg if your malloc does guard pages) in which case it will segfault.
* From OpenSSH. Also added test for same.
+ *
+ * Simo Sorce (idra@samba.org) Jan 2006
+ *
+ * Add support for position independent parameters
+ * fix fmtstr now it conforms to sprintf wrt min.max
+ *
**************************************************************/
#ifndef NO_CONFIG_H
@@ -186,10 +192,24 @@
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
-#define DP_C_SHORT 1
-#define DP_C_LONG 2
-#define DP_C_LDOUBLE 3
-#define DP_C_LLONG 4
+#define DP_C_CHAR 1
+#define DP_C_SHORT 2
+#define DP_C_LONG 3
+#define DP_C_LDOUBLE 4
+#define DP_C_LLONG 5
+
+/* Chunk types */
+#define CNK_FMT_STR 0
+#define CNK_INT 1
+#define CNK_OCTAL 2
+#define CNK_UINT 3
+#define CNK_HEX 4
+#define CNK_FLOAT 5
+#define CNK_CHAR 6
+#define CNK_STRING 7
+#define CNK_PTR 8
+#define CNK_NUM 9
+#define CNK_PRCNT 10
#define char_to_int(p) ((p)- '0')
#ifndef MAX
@@ -199,6 +219,29 @@
/* 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 */
+ int min;
+ int max;
+ int flags;
+ int cflags;
+ int start;
+ int len;
+ LLONG value;
+ LDOUBLE fvalue;
+ char *strvalue;
+ void *pnum;
+ struct pr_chunk *min_star;
+ struct pr_chunk *max_star;
+ struct pr_chunk *next;
+};
+
+struct pr_chunk_x {
+ struct pr_chunk **chunks;
+ int num;
+};
+
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args_in);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
@@ -208,60 +251,88 @@ static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+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)
{
char ch;
- LLONG value;
- LDOUBLE fvalue;
- char *strvalue;
- int min;
- int max;
int state;
- int flags;
- int cflags;
+ int pflag;
+ int pnum;
+ int pfirst;
size_t currlen;
va_list args;
+ const char *base;
+ struct pr_chunk *chunks = NULL;
+ struct pr_chunk *cnk = NULL;
+ struct pr_chunk_x *clist = NULL;
+ int max_pos;
+ size_t ret = -1;
VA_COPY(args, args_in);
-
+
state = DP_S_DEFAULT;
- currlen = flags = cflags = min = 0;
- max = -1;
+ pfirst = 1;
+ pflag = 0;
+ pnum = 0;
+
+ max_pos = 0;
+ base = format;
ch = *format++;
+ /* retrieve the string structure as chunks */
while (state != DP_S_DONE) {
if (ch == '\0')
state = DP_S_DONE;
switch(state) {
case DP_S_DEFAULT:
- if (ch == '%')
+
+ if (cnk) {
+ cnk->next = new_chunk();
+ cnk = cnk->next;
+ } else {
+ cnk = new_chunk();
+ }
+ if (!cnk) goto done;
+ if (!chunks) chunks = cnk;
+
+ if (ch == '%') {
state = DP_S_FLAGS;
- else
- dopr_outch (buffer, &currlen, maxlen, ch);
- ch = *format++;
+ ch = *format++;
+ } else {
+ cnk->type = CNK_FMT_STR;
+ cnk->start = format - base -1;
+ while ((ch != '\0') && (ch != '%')) ch = *format++;
+ cnk->len = format - base - cnk->start -1;
+ }
break;
case DP_S_FLAGS:
switch (ch) {
case '-':
- flags |= DP_F_MINUS;
+ cnk->flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
- flags |= DP_F_PLUS;
+ cnk->flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
- flags |= DP_F_SPACE;
+ cnk->flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
- flags |= DP_F_NUM;
+ cnk->flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
- flags |= DP_F_ZERO;
+ cnk->flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ case 'I':
+ /* internationalization not supported yet */
ch = *format++;
break;
default:
@@ -271,13 +342,51 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch)) {
- min = 10*min + char_to_int (ch);
+ cnk->min = 10 * cnk->min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '$') {
+ if (!pfirst && !pflag) {
+ /* parameters must be all positioned or none */
+ goto done;
+ }
+ if (pfirst) {
+ pfirst = 0;
+ pflag = 1;
+ }
+ if (cnk->min == 0) /* what ?? */
+ goto done;
+ cnk->num = cnk->min;
+ cnk->min = 0;
ch = *format++;
} else if (ch == '*') {
- min = va_arg (args, int);
+ if (pfirst) pfirst = 0;
+ cnk->min_star = new_chunk();
+ if (!cnk->min_star) /* out of memory :-( */
+ goto done;
+ cnk->min_star->type = CNK_INT;
+ if (pflag) {
+ int num;
+ ch = *format++;
+ if (!isdigit((unsigned char)ch)) {
+ /* parameters must be all positioned or none */
+ goto done;
+ }
+ for (num = 0; isdigit((unsigned char)ch); ch = *format++) {
+ num = 10 * num + char_to_int(ch);
+ }
+ cnk->min_star->num = num;
+ if (ch != '$') /* what ?? */
+ goto done;
+ } else {
+ cnk->min_star->num = ++pnum;
+ }
+ max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star);
+ if (max_pos == 0) /* out of memory :-( */
+ goto done;
ch = *format++;
state = DP_S_DOT;
} else {
+ if (pfirst) pfirst = 0;
state = DP_S_DOT;
}
break;
@@ -291,12 +400,45 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch)) {
- if (max < 0)
- max = 0;
- max = 10*max + char_to_int (ch);
+ if (cnk->max < 0)
+ cnk->max = 0;
+ cnk->max = 10 * cnk->max + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '$') {
+ if (!pfirst && !pflag) {
+ /* parameters must be all positioned or none */
+ goto done;
+ }
+ if (cnk->max <= 0) /* what ?? */
+ goto done;
+ cnk->num = cnk->max;
+ cnk->max = -1;
ch = *format++;
} else if (ch == '*') {
- max = va_arg (args, int);
+ cnk->max_star = new_chunk();
+ if (!cnk->max_star) /* out of memory :-( */
+ goto done;
+ cnk->max_star->type = CNK_INT;
+ if (pflag) {
+ int num;
+ ch = *format++;
+ if (!isdigit((unsigned char)ch)) {
+ /* parameters must be all positioned or none */
+ goto done;
+ }
+ for (num = 0; isdigit((unsigned char)ch); ch = *format++) {
+ num = 10 * num + char_to_int(ch);
+ }
+ cnk->max_star->num = num;
+ if (ch != '$') /* what ?? */
+ goto done;
+ } else {
+ cnk->max_star->num = ++pnum;
+ }
+ max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star);
+ if (max_pos == 0) /* out of memory :-( */
+ goto done;
+
ch = *format++;
state = DP_S_MOD;
} else {
@@ -306,19 +448,23 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
case DP_S_MOD:
switch (ch) {
case 'h':
- cflags = DP_C_SHORT;
+ cnk->cflags = DP_C_SHORT;
ch = *format++;
+ if (ch == 'h') {
+ cnk->cflags = DP_C_CHAR;
+ ch = *format++;
+ }
break;
case 'l':
- cflags = DP_C_LONG;
+ cnk->cflags = DP_C_LONG;
ch = *format++;
if (ch == 'l') { /* It's a long long */
- cflags = DP_C_LLONG;
+ cnk->cflags = DP_C_LLONG;
ch = *format++;
}
break;
case 'L':
- cflags = DP_C_LDOUBLE;
+ cnk->cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
@@ -327,133 +473,64 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
state = DP_S_CONV;
break;
case DP_S_CONV:
+ if (cnk->num == 0) cnk->num = ++pnum;
+ max_pos = add_cnk_list_entry(&clist, max_pos, cnk);
+ if (max_pos == 0) /* out of memory :-( */
+ goto done;
+
switch (ch) {
case 'd':
case 'i':
- if (cflags == DP_C_SHORT)
- value = va_arg (args, int);
- else if (cflags == DP_C_LONG)
- value = va_arg (args, long int);
- else if (cflags == DP_C_LLONG)
- value = va_arg (args, LLONG);
- else
- value = va_arg (args, int);
- fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ cnk->type = CNK_INT;
break;
case 'o':
- flags |= DP_F_UNSIGNED;
- if (cflags == DP_C_SHORT)
- value = va_arg (args, unsigned int);
- else if (cflags == DP_C_LONG)
- value = (long)va_arg (args, unsigned long int);
- else if (cflags == DP_C_LLONG)
- value = (long)va_arg (args, unsigned LLONG);
- else
- value = (long)va_arg (args, unsigned int);
- fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
+ cnk->type = CNK_OCTAL;
+ cnk->flags |= DP_F_UNSIGNED;
break;
case 'u':
- flags |= DP_F_UNSIGNED;
- if (cflags == DP_C_SHORT)
- value = va_arg (args, unsigned int);
- else if (cflags == DP_C_LONG)
- value = (long)va_arg (args, unsigned long int);
- else if (cflags == DP_C_LLONG)
- value = (LLONG)va_arg (args, unsigned LLONG);
- else
- value = (long)va_arg (args, unsigned int);
- fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ cnk->type = CNK_UINT;
+ cnk->flags |= DP_F_UNSIGNED;
break;
case 'X':
- flags |= DP_F_UP;
+ cnk->flags |= DP_F_UP;
case 'x':
- flags |= DP_F_UNSIGNED;
- if (cflags == DP_C_SHORT)
- value = va_arg (args, unsigned int);
- else if (cflags == DP_C_LONG)
- value = (long)va_arg (args, unsigned long int);
- else if (cflags == DP_C_LLONG)
- value = (LLONG)va_arg (args, unsigned LLONG);
- else
- value = (long)va_arg (args, unsigned int);
- fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
- break;
- case 'f':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg (args, LDOUBLE);
- else
- fvalue = va_arg (args, double);
- /* um, floating point? */
- fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+ cnk->type = CNK_HEX;
+ cnk->flags |= DP_F_UNSIGNED;
break;
+ case 'A':
+ /* hex float not supported yet */
case 'E':
- flags |= DP_F_UP;
- case 'e':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg (args, LDOUBLE);
- else
- fvalue = va_arg (args, double);
- fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
- break;
case 'G':
- flags |= DP_F_UP;
+ case 'F':
+ cnk->flags |= DP_F_UP;
+ case 'a':
+ /* hex float not supported yet */
+ case 'e':
+ case 'f':
case 'g':
- if (cflags == DP_C_LDOUBLE)
- fvalue = va_arg (args, LDOUBLE);
- else
- fvalue = va_arg (args, double);
- fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+ cnk->type = CNK_FLOAT;
break;
case 'c':
- dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
+ cnk->type = CNK_CHAR;
break;
case 's':
- strvalue = va_arg (args, char *);
- if (!strvalue) strvalue = "(NULL)";
- if (max == -1) {
- max = strlen(strvalue);
- }
- if (min > 0 && max >= 0 && min > max) max = min;
- fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
+ cnk->type = CNK_STRING;
break;
case 'p':
- strvalue = va_arg (args, void *);
- fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+ cnk->type = CNK_PTR;
break;
case 'n':
- if (cflags == DP_C_SHORT) {
- short int *num;
- num = va_arg (args, short int *);
- *num = currlen;
- } else if (cflags == DP_C_LONG) {
- long int *num;
- num = va_arg (args, long int *);
- *num = (long int)currlen;
- } else if (cflags == DP_C_LLONG) {
- LLONG *num;
- num = va_arg (args, LLONG *);
- *num = (LLONG)currlen;
- } else {
- int *num;
- num = va_arg (args, int *);
- *num = currlen;
- }
+ cnk->type = CNK_NUM;
break;
case '%':
- dopr_outch (buffer, &currlen, maxlen, ch);
- break;
- case 'w':
- /* not supported yet, treat as next char */
- ch = *format++;
+ cnk->type = CNK_PRCNT;
break;
default:
- /* Unknown, skip */
- break;
+ /* Unknown, bail out*/
+ goto done;
}
ch = *format++;
state = DP_S_DEFAULT;
- flags = cflags = min = 0;
- max = -1;
break;
case DP_S_DONE:
break;
@@ -462,14 +539,227 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args
break; /* some picky compilers need this */
}
}
+
+ /* retieve the format arguments */
+ for (pnum = 0; pnum < max_pos; pnum++) {
+ int i;
+
+ if (clist[pnum].num == 0) {
+ /* ignoring a parameter should not be permitted
+ * all parameters must be matched at least once
+ * BUT seem some system ignore this rule ...
+ * at least my glibc based system does --SSS
+ */
+#ifdef DEBUG_SNPRINTF
+ printf("parameter at position %d not used\n", pnum+1);
+#endif
+ /* eat the parameter */
+ va_arg (args, int);
+ continue;
+ }
+ for (i = 1; i < clist[pnum].num; i++) {
+ if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) {
+ /* nooo noo no!
+ * all the references to a parameter
+ * must be of the same type
+ */
+ goto done;
+ }
+ }
+ cnk = clist[pnum].chunks[0];
+ switch (cnk->type) {
+ case CNK_INT:
+ if (cnk->cflags == DP_C_SHORT)
+ cnk->value = va_arg (args, int);
+ else if (cnk->cflags == DP_C_LONG)
+ cnk->value = va_arg (args, long int);
+ else if (cnk->cflags == DP_C_LLONG)
+ cnk->value = va_arg (args, LLONG);
+ else
+ cnk->value = va_arg (args, int);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->value = cnk->value;
+ }
+ break;
+
+ case CNK_OCTAL:
+ case CNK_UINT:
+ case CNK_HEX:
+ if (cnk->cflags == DP_C_SHORT)
+ cnk->value = va_arg (args, unsigned int);
+ else if (cnk->cflags == DP_C_LONG)
+ cnk->value = (long)va_arg (args, unsigned long int);
+ else if (cnk->cflags == DP_C_LLONG)
+ cnk->value = (LLONG)va_arg (args, unsigned LLONG);
+ else
+ cnk->value = (long)va_arg (args, unsigned int);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->value = cnk->value;
+ }
+ break;
+
+ case CNK_FLOAT:
+ if (cnk->cflags == DP_C_LDOUBLE)
+ cnk->fvalue = va_arg (args, LDOUBLE);
+ else
+ cnk->fvalue = va_arg (args, double);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->fvalue = cnk->fvalue;
+ }
+ break;
+
+ case CNK_CHAR:
+ cnk->value = va_arg (args, int);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->value = cnk->value;
+ }
+ break;
+
+ case CNK_STRING:
+ cnk->strvalue = va_arg (args, char *);
+ if (!cnk->strvalue) cnk->strvalue = "(NULL)";
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->strvalue = cnk->strvalue;
+ }
+ break;
+
+ case CNK_PTR:
+ cnk->strvalue = va_arg (args, void *);
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->strvalue = cnk->strvalue;
+ }
+ break;
+
+ case CNK_NUM:
+ if (cnk->cflags == DP_C_CHAR)
+ cnk->pnum = va_arg (args, char *);
+ else if (cnk->cflags == DP_C_SHORT)
+ cnk->pnum = va_arg (args, short int *);
+ else if (cnk->cflags == DP_C_LONG)
+ cnk->pnum = va_arg (args, long int *);
+ else if (cnk->cflags == DP_C_LLONG)
+ cnk->pnum = va_arg (args, LLONG *);
+ else
+ cnk->pnum = va_arg (args, int *);
+
+ for (i = 1; i < clist[pnum].num; i++) {
+ clist[pnum].chunks[i]->pnum = cnk->pnum;
+ }
+ break;
+
+ case CNK_PRCNT:
+ break;
+
+ default:
+ /* what ?? */
+ goto done;
+ }
+ }
+ /* print out the actual string from chunks */
+ currlen = 0;
+ cnk = chunks;
+ while (cnk) {
+ int len, min, max;
+
+ if (cnk->min_star) min = cnk->min_star->value;
+ else min = cnk->min;
+ if (cnk->max_star) max = cnk->max_star->value;
+ else max = cnk->max;
+
+ switch (cnk->type) {
+
+ case CNK_FMT_STR:
+ if (maxlen != 0 && maxlen > currlen) {
+ if (maxlen > (currlen + cnk->len)) len = cnk->len;
+ else len = maxlen - currlen;
+
+ memcpy(&(buffer[currlen]), &(base[cnk->start]), len);
+ }
+ currlen += cnk->len;
+
+ break;
+
+ case CNK_INT:
+ case CNK_UINT:
+ fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags);
+ break;
+
+ case CNK_OCTAL:
+ fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags);
+ break;
+
+ case CNK_HEX:
+ fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags);
+ break;
+
+ case CNK_FLOAT:
+ fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags);
+ break;
+
+ case CNK_CHAR:
+ dopr_outch (buffer, &currlen, maxlen, cnk->value);
+ break;
+
+ case CNK_STRING:
+ if (max == -1) {
+ max = strlen(cnk->strvalue);
+ }
+ fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max);
+ break;
+
+ case CNK_PTR:
+ fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags);
+ break;
+
+ case CNK_NUM:
+ if (cnk->cflags == DP_C_CHAR)
+ *((char *)(cnk->pnum)) = (char)currlen;
+ else if (cnk->cflags == DP_C_SHORT)
+ *((short int *)(cnk->pnum)) = (short int)currlen;
+ else if (cnk->cflags == DP_C_LONG)
+ *((long int *)(cnk->pnum)) = (long int)currlen;
+ else if (cnk->cflags == DP_C_LLONG)
+ *((LLONG *)(cnk->pnum)) = (LLONG)currlen;
+ else
+ *((int *)(cnk->pnum)) = (int)currlen;
+ break;
+
+ case CNK_PRCNT:
+ dopr_outch (buffer, &currlen, maxlen, '%');
+ break;
+
+ default:
+ /* what ?? */
+ goto done;
+ }
+ cnk = cnk->next;
+ }
if (maxlen != 0) {
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else if (maxlen > 0)
buffer[maxlen - 1] = '\0';
}
-
- return currlen;
+ ret = currlen;
+
+done:
+ while (chunks) {
+ cnk = chunks->next;
+ free(chunks);
+ chunks = cnk;
+ }
+ if (clist) {
+ for (pnum = 0; pnum < max_pos; pnum++) {
+ if (clist[pnum].chunks) free(clist[pnum].chunks);
+ }
+ free(clist);
+ }
+ return ret;
}
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
@@ -492,19 +782,17 @@ static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
- while ((padlen > 0) && (cnt < max)) {
+ while (padlen > 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
- ++cnt;
}
while (*value && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
- while ((padlen < 0) && (cnt < max)) {
+ while (padlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
- ++cnt;
}
}
@@ -709,11 +997,11 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
#endif
/*
- * Sorry, we only support 16 digits past the decimal because of our
+ * Sorry, we only support 9 digits past the decimal because of our
* conversion method
*/
- if (max > 16)
- max = 16;
+ if (max > 9)
+ max = 9;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
@@ -823,6 +1111,85 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
(*currlen)++;
}
+static struct pr_chunk *new_chunk(void) {
+ struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk));
+
+ if ( !new_c )
+ return NULL;
+
+ new_c->type = 0;
+ new_c->num = 0;
+ new_c->min = 0;
+ new_c->min_star = NULL;
+ new_c->max = -1;
+ new_c->max_star = NULL;
+ new_c->flags = 0;
+ new_c->cflags = 0;
+ new_c->start = 0;
+ new_c->len = 0;
+ new_c->value = 0;
+ new_c->fvalue = 0;
+ new_c->strvalue = NULL;
+ new_c->pnum = NULL;
+ new_c->next = NULL;
+
+ return new_c;
+}
+
+static int add_cnk_list_entry(struct pr_chunk_x **list,
+ int max_num, struct pr_chunk *chunk) {
+ struct pr_chunk_x *l;
+ struct pr_chunk **c;
+ int max;
+ int cnum;
+ int i, pos;
+
+ if (chunk->num > max_num) {
+ max = chunk->num;
+
+ if (*list == NULL) {
+ l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max);
+ pos = 0;
+ } else {
+ l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max);
+ pos = max_num;
+ }
+ if (l == NULL) {
+ for (i = 0; i < max; i++) {
+ if ((*list)[i].chunks) free((*list)[i].chunks);
+ }
+ return 0;
+ }
+ for (i = pos; i < max; i++) {
+ l[i].chunks = NULL;
+ l[i].num = 0;
+ }
+ } else {
+ l = *list;
+ max = max_num;
+ }
+
+ i = chunk->num - 1;
+ cnum = l[i].num + 1;
+ if (l[i].chunks == NULL) {
+ c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum);
+ } else {
+ c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum);
+ }
+ if (c == NULL) {
+ for (i = 0; i < max; i++) {
+ if (l[i].chunks) free(l[i].chunks);
+ }
+ return 0;
+ }
+ c[l[i].num] = chunk;
+ l[i].chunks = c;
+ l[i].num = cnum;
+
+ *list = l;
+ return max;
+}
+
int smb_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
@@ -914,7 +1281,8 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
"%3.2f",
"%.0f",
"%f",
- "-16.16f",
+ "%-8.8f",
+ "%-9.9f",
NULL
};
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
@@ -933,14 +1301,16 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
"%d",
NULL
};
- long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
+ long int_nums[] = { -1, 134, 91340, 341, 0203, 0, 1234567890};
char *str_fmt[] = {
- "10.5s",
- "5.10s",
- "10.1s",
- "0.10s",
- "10.0s",
- "1.10s",
+ "%10.5s",
+ "%-10.5s",
+ "%5.10s",
+ "%-5.10s",
+ "%10.1s",
+ "%0.10s",
+ "%10.0s",
+ "%1.10s",
"%s",
"%.1s",
"%.10s",
@@ -951,21 +1321,20 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
int x, y;
int fail = 0;
int num = 0;
+ int l1, l2;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] ; x++) {
for (y = 0; fp_nums[y] != 0 ; y++) {
- int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
- int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
+ l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
- if (strcmp (buf1, buf2)) {
- printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
- fp_fmt[x], buf1, buf2);
- fail++;
- }
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
+ buf1[1023] = buf1[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",
+ fp_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
@@ -974,16 +1343,14 @@ 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++) {
- int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
- int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
+ l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
- if (strcmp (buf1, buf2)) {
- printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
- int_fmt[x], buf1, buf2);
- fail++;
- }
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
+ buf1[1023] = buf1[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",
+ int_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
@@ -992,16 +1359,14 @@ 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++) {
- int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
- int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
+ l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
sprintf (buf2, str_fmt[x], str_vals[y]);
- if (strcmp (buf1, buf2)) {
- printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
- str_fmt[x], buf1, buf2);
- fail++;
- }
- if (l1 != l2) {
- printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
+ buf1[1023] = buf1[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",
+ str_fmt[x], l1, buf1, l2, buf2);
fail++;
}
num++;
@@ -1010,18 +1375,60 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
#define BUFSZ 2048
+ buf1[0] = buf2[0] = '\0';
if ((buf3 = malloc(BUFSZ)) == NULL) {
fail++;
} else {
num++;
memset(buf3, 'a', BUFSZ);
snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3);
+ buf1[1023] = '\0';
if (strcmp(buf1, "a") != 0) {
printf("length limit buf1 '%s' expected 'a'\n", buf1);
fail++;
}
}
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9);
+ l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9);
+ buf1[1023] = buf1[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",
+ "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
+ fail++;
+ }
+
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9);
+ l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9);
+ buf1[1023] = buf1[1023] = '\0';
+ if (strcmp(buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
+ fail++;
+ }
+#if 0
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890);
+ l2 = sprintf(buf2, "%lld", (LLONG)1234567890);
+ buf1[1023] = buf1[1023] = '\0';
+ if (strcmp(buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ "%lld", l1, buf1, l2, buf2);
+ fail++;
+ }
+
+ buf1[0] = buf2[0] = '\0';
+ l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123);
+ l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123);
+ buf1[1023] = buf1[1023] = '\0';
+ if (strcmp(buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
+ "%Lf", l1, buf1, l2, buf2);
+ fail++;
+ }
+#endif
printf ("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
diff --git a/source/lib/socket_wrapper.c b/source/lib/socket_wrapper.c
index 9d65aa923af..e9c1404d113 100644
--- a/source/lib/socket_wrapper.c
+++ b/source/lib/socket_wrapper.c
@@ -21,6 +21,11 @@
#include "includes.h"
+#ifdef _PUBLIC_
+#undef _PUBLIC_
+#endif
+#define _PUBLIC_
+
#ifdef SOCKET_WRAPPER_REPLACE
#undef accept
#undef connect
@@ -62,7 +67,9 @@
with this format we have 8 chars left for the directory name
*/
-#define SOCKET_FORMAT "%u_%u"
+#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)
{
@@ -79,6 +86,7 @@ struct socket_info
int type;
int protocol;
int bound;
+ int bcast;
char *path;
char *tmp_path;
@@ -107,45 +115,200 @@ static const char *socket_wrapper_dir(void)
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;
- int type;
+ char type;
if ((*len) < sizeof(struct sockaddr_in)) {
return 0;
}
- in->sin_family = AF_INET;
- in->sin_port = htons(1025); /* Default to 1025 */
p = strrchr(un->sun_path, '/');
if (p) p++; else p = un->sun_path;
- if (sscanf(p, SOCKET_FORMAT, &type, &prt) == 2) {
- in->sin_port = htons(prt);
+ 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;
}
- in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ 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(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un)
+static int convert_in_un_remote(struct socket_info *si, const struct sockaddr_in *in, struct sockaddr_un *un,
+ int *bcast)
{
- int type = si->type;
- uint16_t prt = ntohs(in->sin_port);
+ 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) {
- struct stat st;
/* handle auto-allocation of ephemeral ports */
- prt = 5000;
- do {
+ for (prt = 5001; prt < 10000; prt++) {
snprintf(un->sun_path, sizeof(un->sun_path), "%s/"SOCKET_FORMAT,
- socket_wrapper_dir(), type, ++prt);
- } while (stat(un->sun_path, &st) == 0 && prt < 10000);
- ((struct sockaddr_in *)si->myname)->sin_port = htons(prt);
- }
+ 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, prt);
+ socket_wrapper_dir(), type, iface, prt);
return 0;
}
@@ -161,7 +324,7 @@ static struct socket_info *find_socket_info(int fd)
}
static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len,
- struct sockaddr_un *out_addr)
+ struct sockaddr_un *out_addr, int alloc_sock, int *bcast)
{
if (!out_addr)
return 0;
@@ -170,7 +333,19 @@ static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr
switch (in_addr->sa_family) {
case AF_INET:
- return convert_in_un(si, (const struct sockaddr_in *)in_addr, out_addr);
+ 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;
@@ -187,22 +362,37 @@ static int sockaddr_convert_from_un(const struct socket_info *si,
socklen_t un_addrlen,
int family,
struct sockaddr *out_addr,
- socklen_t *out_len)
+ socklen_t *_out_addrlen)
{
- if (out_addr == NULL || out_len == NULL)
+ socklen_t out_addrlen;
+
+ if (out_addr == NULL || _out_addrlen == NULL)
return 0;
if (un_addrlen == 0) {
- *out_len = 0;
+ *_out_addrlen = 0;
return 0;
}
+ out_addrlen = *_out_addrlen;
+ if (out_addrlen > un_addrlen) {
+ out_addrlen = un_addrlen;
+ }
+
switch (family) {
case AF_INET:
- return convert_un_in(in_addr, (struct sockaddr_in *)out_addr, out_len);
+ 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, sizeof(*in_addr));
- *out_len = sizeof(*in_addr);
+ memcpy(out_addr, in_addr, out_addrlen);
+ *_out_addrlen = out_addrlen;
return 0;
default:
break;
@@ -212,7 +402,7 @@ static int sockaddr_convert_from_un(const struct socket_info *si,
return -1;
}
-int swrap_socket(int domain, int type, int protocol)
+_PUBLIC_ int swrap_socket(int domain, int type, int protocol)
{
struct socket_info *si;
int fd;
@@ -237,12 +427,16 @@ int swrap_socket(int domain, int type, int protocol)
return si->fd;
}
-int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+_PUBLIC_ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
struct socket_info *parent_si, *child_si;
int fd;
- socklen_t un_addrlen = sizeof(struct sockaddr_un);
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);
@@ -251,6 +445,8 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *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;
@@ -265,10 +461,20 @@ int swrap_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
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;
- child_si->myname_len = parent_si->myname_len;
- child_si->myname = sockaddr_dup(parent_si->myname, parent_si->myname_len);
+ 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);
@@ -287,28 +493,46 @@ 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(),
- SOCK_DGRAM, i + 10000);
- if (bind(si->fd, (struct sockaddr *)&un_addr,
- sizeof(un_addr)) == 0) {
- si->tmp_path = strdup(un_addr.sun_path);
- si->bound = 1;
- break;
- }
+ 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(INADDR_LOOPBACK);
+ 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);
@@ -317,7 +541,7 @@ static int swrap_auto_bind(struct socket_info *si)
}
-int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
+_PUBLIC_ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
{
int ret;
struct sockaddr_un un_addr;
@@ -327,25 +551,24 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
return real_connect(s, serv_addr, addrlen);
}
- /* only allow pseudo loopback connections */
- if (serv_addr->sa_family == AF_INET &&
- ((const struct sockaddr_in *)serv_addr)->sin_addr.s_addr !=
- htonl(INADDR_LOOPBACK)) {
- errno = ENETUNREACH;
- return -1;
- }
-
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);
+ 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);
@@ -354,7 +577,7 @@ int swrap_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
return ret;
}
-int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
+_PUBLIC_ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
{
int ret;
struct sockaddr_un un_addr;
@@ -367,12 +590,7 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
si->myname_len = addrlen;
si->myname = sockaddr_dup(myaddr, addrlen);
- if (myaddr->sa_family == AF_INET &&
- ((const struct sockaddr_in *)myaddr)->sin_addr.s_addr == 0) {
- ((struct sockaddr_in *)si->myname)->sin_addr.s_addr =
- htonl(INADDR_LOOPBACK);
- }
- ret = sockaddr_convert_to_un(si, (const struct sockaddr *)myaddr, addrlen, &un_addr);
+ 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);
@@ -387,7 +605,7 @@ int swrap_bind(int s, const struct sockaddr *myaddr, socklen_t addrlen)
return ret;
}
-int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
+_PUBLIC_ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
{
struct socket_info *si = find_socket_info(s);
@@ -407,7 +625,7 @@ int swrap_getpeername(int s, struct sockaddr *name, socklen_t *addrlen)
return 0;
}
-int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
+_PUBLIC_ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
{
struct socket_info *si = find_socket_info(s);
@@ -421,7 +639,7 @@ int swrap_getsockname(int s, struct sockaddr *name, socklen_t *addrlen)
return 0;
}
-int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+_PUBLIC_ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
struct socket_info *si = find_socket_info(s);
@@ -442,7 +660,7 @@ int swrap_getsockopt(int s, int level, int optname, void *optval, socklen_t *opt
}
}
-int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+_PUBLIC_ int swrap_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
struct socket_info *si = find_socket_info(s);
@@ -469,7 +687,7 @@ int swrap_setsockopt(int s, int level, int optname, const void *optval, so
}
}
-ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
+_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);
@@ -495,11 +713,12 @@ ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr
}
-ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
+_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);
@@ -510,15 +729,41 @@ ssize_t swrap_sendto(int s, const void *buf, size_t len, int flags, const str
if (ret == -1) return -1;
}
- ret = sockaddr_convert_to_un(si, to, tolen, &un_addr);
+ 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;
}
-int swrap_close(int fd)
+_PUBLIC_ int swrap_close(int fd)
{
struct socket_info *si = find_socket_info(fd);
diff --git a/source/lib/substitute.c b/source/lib/substitute.c
index 344f6e06fdf..bfe7dc814ca 100644
--- a/source/lib/substitute.c
+++ b/source/lib/substitute.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
string substitution functions
Copyright (C) Andrew Tridgell 1992-2000
+ 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
@@ -171,24 +172,24 @@ const char* get_current_username( void )
}
/*******************************************************************
- Given a pointer to a %$(NAME) expand it as an environment variable.
- Return the number of characters by which the pointer should be advanced.
+ Given a pointer to a %$(NAME) in p and the whole string in str
+ expand it as an environment variable.
+ Return a new allocated and expanded string.
Based on code by Branko Cibej <branko.cibej@hermes.si>
When this is called p points at the '%' character.
+ May substitute multiple occurrencies of the same env var.
********************************************************************/
-static size_t expand_env_var(char *p, int len)
+static char * realloc_expand_env_var(char *str, char *p)
{
- fstring envname;
+ char *envname;
char *envval;
char *q, *r;
int copylen;
- if (p[1] != '$')
- return 1;
-
- if (p[2] != '(')
- return 2;
+ if (p[0] != '%' || p[1] != '$' || p[2] != '(') {
+ return str;
+ }
/*
* Look for the terminating ')'.
@@ -196,21 +197,28 @@ static size_t expand_env_var(char *p, int len)
if ((q = strchr_m(p,')')) == NULL) {
DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
- return 2;
+ return str;
}
/*
* Extract the name from within the %$(NAME) string.
*/
- r = p+3;
- copylen = MIN((q-r),(sizeof(envname)-1));
+ r = p + 3;
+ copylen = q - r;
+
+ /* reserve space for use later add %$() chars */
+ if ( (envname = (char *)SMB_MALLOC(copylen + 1 + 4)) == NULL ) {
+ return NULL;
+ }
+
strncpy(envname,r,copylen);
envname[copylen] = '\0';
if ((envval = getenv(envname)) == NULL) {
DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
- return 2;
+ SAFE_FREE(envname);
+ return str;
}
/*
@@ -218,70 +226,110 @@ static size_t expand_env_var(char *p, int len)
* can be replaced.
*/
- copylen = MIN((q+1-p),(sizeof(envname)-1));
+ copylen = q + 1 - p;
strncpy(envname,p,copylen);
envname[copylen] = '\0';
- string_sub(p,envname,envval,len);
- return 0; /* Allow the environment contents to be parsed. */
+ r = realloc_string_sub(str, envname, envval);
+ SAFE_FREE(envname);
+
+ return r;
}
/*******************************************************************
- Given a pointer to a %$(NAME) in p and the whole string in str
- expand it as an environment variable.
- Return a new allocated and expanded string.
- Based on code by Branko Cibej <branko.cibej@hermes.si>
+*******************************************************************/
+
+static char *longvar_domainsid( void )
+{
+ DOM_SID sid;
+ char *sid_string;
+
+ if ( !secrets_fetch_domain_sid( lp_workgroup(), &sid ) ) {
+ return NULL;
+ }
+
+ sid_string = SMB_STRDUP( sid_string_static( &sid ) );
+
+ if ( !sid_string ) {
+ DEBUG(0,("longvar_domainsid: failed to dup SID string!\n"));
+ }
+
+ return sid_string;
+}
+
+/*******************************************************************
+*******************************************************************/
+
+struct api_longvar {
+ const char *name;
+ char* (*fn)( void );
+};
+
+struct api_longvar longvar_table[] = {
+ { "DomainSID", longvar_domainsid },
+ { NULL, NULL }
+};
+
+static char *get_longvar_val( const char *varname )
+{
+ int i;
+
+ DEBUG(7,("get_longvar_val: expanding variable [%s]\n", varname));
+
+ for ( i=0; longvar_table[i].name; i++ ) {
+ if ( strequal( longvar_table[i].name, varname ) ) {
+ return longvar_table[i].fn();
+ }
+ }
+
+ return NULL;
+}
+
+/*******************************************************************
+ Expand the long smb.conf variable names given a pointer to a %(NAME).
+ Return the number of characters by which the pointer should be advanced.
When this is called p points at the '%' character.
- May substitute multiple occurrencies of the same env var.
********************************************************************/
-
-static char * realloc_expand_env_var(char *str, char *p)
+static char *realloc_expand_longvar(char *str, char *p)
{
- char *envname;
- char *envval;
+ fstring varname;
+ char *value;
char *q, *r;
int copylen;
- if (p[0] != '%' || p[1] != '$' || p[2] != '(')
+ if ( p[0] != '%' || p[1] != '(' ) {
return str;
+ }
- /*
- * Look for the terminating ')'.
- */
+ /* Look for the terminating ')'.*/
if ((q = strchr_m(p,')')) == NULL) {
- DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
+ DEBUG(0,("realloc_expand_longvar: Unterminated environment variable [%s]\n", p));
return str;
}
- /*
- * Extract the name from within the %$(NAME) string.
- */
+ /* Extract the name from within the %(NAME) string.*/
- r = p + 3;
- copylen = q - r;
- envname = (char *)SMB_MALLOC(copylen + 1 + 4); /* reserve space for use later add %$() chars */
- if (envname == NULL) return NULL;
- strncpy(envname,r,copylen);
- envname[copylen] = '\0';
+ r = p+2;
+ copylen = MIN( (q-r), (sizeof(varname)-1) );
+ strncpy(varname, r, copylen);
+ varname[copylen] = '\0';
- if ((envval = getenv(envname)) == NULL) {
- DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
- SAFE_FREE(envname);
+ if ((value = get_longvar_val(varname)) == NULL) {
+ DEBUG(0,("realloc_expand_longvar: Variable [%s] not set. Skipping\n", varname));
return str;
}
- /*
- * Copy the full %$(NAME) into envname so it
- * can be replaced.
- */
+ /* Copy the full %(NAME) into envname so it can be replaced.*/
- copylen = q + 1 - p;
- strncpy(envname,p,copylen);
- envname[copylen] = '\0';
- r = realloc_string_sub(str, envname, envval);
- SAFE_FREE(envname);
- if (r == NULL) return NULL;
+ copylen = MIN( (q+1-p),(sizeof(varname)-1) );
+ strncpy( varname, p, copylen );
+ varname[copylen] = '\0';
+ r = realloc_string_sub(str, varname, value);
+ SAFE_FREE( value );
+
+ /* skip over the %(varname) */
+
return r;
}
@@ -367,160 +415,16 @@ 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, char *str, size_t len)
{
- char *p, *s;
- fstring pidstr;
- struct passwd *pass;
- const char *local_machine_name = get_local_machine_name();
-
- for (s=str; (p=strchr_m(s, '%'));s=p) {
- fstring tmp_str;
-
- int l = (int)len - (int)(p-str);
-
- if (l < 0)
- l = 0;
-
- switch (*(p+1)) {
- case 'U' :
- fstrcpy(tmp_str, smb_name);
- strlower_m(tmp_str);
- string_sub(p,"%U",tmp_str,l);
- break;
- case 'G' :
- fstrcpy(tmp_str, smb_name);
- if ((pass = Get_Pwnam(tmp_str))!=NULL) {
- string_sub(p,"%G",gidtoname(pass->pw_gid),l);
- } else {
- p += 2;
- }
- break;
- case 'D' :
- fstrcpy(tmp_str, current_user_info.domain);
- strupper_m(tmp_str);
- string_sub(p,"%D", tmp_str,l);
- break;
- case 'I' :
- string_sub(p,"%I", client_addr(),l);
- break;
- case 'i' :
- string_sub(p,"%i", client_socket_addr(),l);
- break;
- case 'L' :
- if (!StrnCaseCmp(p, "%LOGONSERVER%", strlen("%LOGONSERVER%"))) {
- p++;
- break;
- }
-
- if (local_machine_name && *local_machine_name) {
- string_sub_once(p, "%L", local_machine_name, l);
- } else {
- pstring temp_name;
-
- pstrcpy(temp_name, global_myname());
- strlower_m(temp_name);
- string_sub_once(p, "%L", temp_name, l);
- }
- break;
- case 'M' :
- string_sub(p,"%M", client_name(),l);
- break;
- case 'R' :
- string_sub(p,"%R", remote_proto,l);
- break;
- case 'T' :
- string_sub(p,"%T", timestring(False),l);
- break;
- case 'a' :
- string_sub(p,"%a", remote_arch,l);
- break;
- case 'd' :
- slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
- string_sub(p,"%d", pidstr,l);
- break;
- case 'h' :
- string_sub(p,"%h", myhostname(),l);
- break;
- case 'm' :
- string_sub(p,"%m", get_remote_machine_name(),l);
- break;
- case 'v' :
- string_sub(p,"%v", SAMBA_VERSION_STRING,l);
- break;
- case 'w' :
- string_sub(p,"%w", lp_winbind_separator(),l);
- break;
- case '$' :
- p += expand_env_var(p,l);
- break; /* Expand environment variables */
- case '\0':
- p++;
- break; /* don't run off the end of the string */
-
- default: p+=2;
- break;
- }
+ char *s;
+
+ if ( (s = alloc_sub_basic( smb_name, str )) != NULL ) {
+ strncpy( str, s, len );
}
-}
-
-static void standard_sub_advanced(int snum, const char *user,
- const char *connectpath, gid_t gid,
- const char *smb_name, char *str, size_t len)
-{
- char *p, *s, *home;
-
- for (s=str; (p=strchr_m(s, '%'));s=p) {
- int l = (int)len - (int)(p-str);
- if (l < 0)
- l = 0;
+ SAFE_FREE( s );
- switch (*(p+1)) {
- case 'N' :
- string_sub(p,"%N", automount_server(user),l);
- break;
- case 'H':
- if ((home = get_user_home_dir(user)))
- string_sub(p,"%H",home, l);
- else
- p += 2;
- break;
- case 'P':
- string_sub(p,"%P", connectpath, l);
- break;
- case 'S':
- if ( snum != -1 )
- string_sub(p,"%S", lp_servicename(snum), l);
- break;
- case 'g':
- string_sub(p,"%g", gidtoname(gid), l);
- break;
- case 'u':
- string_sub(p,"%u", user, l);
- break;
-
- /* Patch from jkf@soton.ac.uk Left the %N (NIS
- * server name) in standard_sub_basic as it is
- * a feature for logon servers, hence uses the
- * username. The %p (NIS server path) code is
- * here as it is used instead of the default
- * "path =" string in [homes] and so needs the
- * service name, not the username. */
- case 'p':
- if ( snum != -1 )
- string_sub(p,"%p", automount_path(lp_servicename(snum)), l);
- break;
- case '\0':
- p++;
- break; /* don't run off the end of the string */
-
- default: p+=2;
- break;
- }
- }
-
- standard_sub_basic(smb_name, str, len);
}
/****************************************************************************
@@ -531,23 +435,28 @@ static void standard_sub_advanced(int snum, const char *user,
char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str)
{
char *a, *t;
- a = alloc_sub_basic(smb_name, str);
- if (!a) return NULL;
+
+ if ( (a = alloc_sub_basic(smb_name, str)) == NULL ) {
+ return NULL;
+ }
t = talloc_strdup(mem_ctx, a);
SAFE_FREE(a);
return t;
}
+/****************************************************************************
+****************************************************************************/
+
char *alloc_sub_basic(const char *smb_name, const char *str)
{
- char *b, *p, *s, *t, *r, *a_string;
+ char *b, *p, *s, *r, *a_string;
fstring pidstr;
struct passwd *pass;
const char *local_machine_name = get_local_machine_name();
- /* workaround to prevent a crash while lookinf at bug #687 */
+ /* workaround to prevent a crash while looking at bug #687 */
- if ( !str ) {
+ if (!str) {
DEBUG(0,("alloc_sub_basic: NULL source string! This should not happen\n"));
return NULL;
}
@@ -561,81 +470,99 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
r = NULL;
- b = t = a_string;
+ b = a_string;
switch (*(p+1)) {
case 'U' :
r = strdup_lower(smb_name);
- if (r == NULL) goto error;
- t = realloc_string_sub(t, "%U", r);
+ if (r == NULL) {
+ goto error;
+ }
+ a_string = realloc_string_sub(a_string, "%U", r);
break;
case 'G' :
r = SMB_STRDUP(smb_name);
- if (r == NULL) goto error;
+ if (r == NULL) {
+ goto error;
+ }
if ((pass = Get_Pwnam(r))!=NULL) {
- t = realloc_string_sub(t, "%G", gidtoname(pass->pw_gid));
+ a_string = realloc_string_sub(a_string, "%G", gidtoname(pass->pw_gid));
}
break;
case 'D' :
r = strdup_upper(current_user_info.domain);
- if (r == NULL) goto error;
- t = realloc_string_sub(t, "%D", r);
+ if (r == NULL) {
+ goto error;
+ }
+ a_string = realloc_string_sub(a_string, "%D", r);
break;
case 'I' :
- t = realloc_string_sub(t, "%I", client_addr());
+ a_string = realloc_string_sub(a_string, "%I", client_addr());
+ break;
+ case 'i':
+ a_string = realloc_string_sub( a_string, "%i", client_socket_addr() );
break;
case 'L' :
- if (local_machine_name && *local_machine_name)
- t = realloc_string_sub(t, "%L", local_machine_name);
- else
- t = realloc_string_sub(t, "%L", global_myname());
+ if ( StrnCaseCmp(p, "%LOGONSERVER%", strlen("%LOGONSERVER%")) == 0 ) {
+ break;
+ }
+ if (local_machine_name && *local_machine_name) {
+ a_string = realloc_string_sub(a_string, "%L", local_machine_name);
+ } else {
+ a_string = realloc_string_sub(a_string, "%L", global_myname());
+ }
break;
case 'N':
- t = realloc_string_sub(t, "%N", automount_server(smb_name));
+ a_string = realloc_string_sub(a_string, "%N", automount_server(smb_name));
break;
case 'M' :
- t = realloc_string_sub(t, "%M", client_name());
+ a_string = realloc_string_sub(a_string, "%M", client_name());
break;
case 'R' :
- t = realloc_string_sub(t, "%R", remote_proto);
+ a_string = realloc_string_sub(a_string, "%R", remote_proto);
break;
case 'T' :
- t = realloc_string_sub(t, "%T", timestring(False));
+ a_string = realloc_string_sub(a_string, "%T", timestring(False));
break;
case 'a' :
- t = realloc_string_sub(t, "%a", remote_arch);
+ a_string = realloc_string_sub(a_string, "%a", remote_arch);
break;
case 'd' :
slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
- t = realloc_string_sub(t, "%d", pidstr);
+ a_string = realloc_string_sub(a_string, "%d", pidstr);
break;
case 'h' :
- t = realloc_string_sub(t, "%h", myhostname());
+ a_string = realloc_string_sub(a_string, "%h", myhostname());
break;
case 'm' :
- t = realloc_string_sub(t, "%m", remote_machine);
+ a_string = realloc_string_sub(a_string, "%m", remote_machine);
break;
case 'v' :
- t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING);
+ a_string = realloc_string_sub(a_string, "%v", SAMBA_VERSION_STRING);
break;
case 'w' :
- t = realloc_string_sub(t, "%w", lp_winbind_separator());
+ a_string = realloc_string_sub(a_string, "%w", lp_winbind_separator());
break;
case '$' :
- t = realloc_expand_env_var(t, p); /* Expand environment variables */
+ a_string = realloc_expand_env_var(a_string, p); /* Expand environment variables */
+ break;
+ case '(':
+ a_string = realloc_expand_longvar( a_string, p );
break;
-
default:
break;
}
p++;
SAFE_FREE(r);
- if (t == NULL) goto error;
- a_string = t;
+
+ if ( !a_string ) {
+ return NULL;
+ }
}
return a_string;
+
error:
SAFE_FREE(a_string);
return NULL;
@@ -655,12 +582,17 @@ char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
{
char *a, *t;
a = alloc_sub_specified(input_string, username, domain, uid, gid);
- if (!a) return NULL;
+ if (!a) {
+ 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,
@@ -668,7 +600,7 @@ char *alloc_sub_specified(const char *input_string,
gid_t gid)
{
char *a_string, *ret_string;
- char *b, *p, *s, *t;
+ char *b, *p, *s;
a_string = SMB_STRDUP(input_string);
if (a_string == NULL) {
@@ -678,45 +610,43 @@ char *alloc_sub_specified(const char *input_string,
for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
- b = t = a_string;
+ b = a_string;
switch (*(p+1)) {
case 'U' :
- t = realloc_string_sub(t, "%U", username);
+ a_string = realloc_string_sub(a_string, "%U", username);
break;
case 'u' :
- t = realloc_string_sub(t, "%u", username);
+ a_string = realloc_string_sub(a_string, "%u", username);
break;
case 'G' :
if (gid != -1) {
- t = realloc_string_sub(t, "%G", gidtoname(gid));
+ a_string = realloc_string_sub(a_string, "%G", gidtoname(gid));
} else {
- t = realloc_string_sub(t, "%G", "NO_GROUP");
+ a_string = realloc_string_sub(a_string, "%G", "NO_GROUP");
}
break;
case 'g' :
if (gid != -1) {
- t = realloc_string_sub(t, "%g", gidtoname(gid));
+ a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
} else {
- t = realloc_string_sub(t, "%g", "NO_GROUP");
+ a_string = realloc_string_sub(a_string, "%g", "NO_GROUP");
}
break;
case 'D' :
- t = realloc_string_sub(t, "%D", domain);
+ a_string = realloc_string_sub(a_string, "%D", domain);
break;
case 'N' :
- t = realloc_string_sub(t, "%N", automount_server(username));
+ a_string = realloc_string_sub(a_string, "%N", automount_server(username));
break;
default:
break;
}
p++;
- if (t == NULL) {
- SAFE_FREE(a_string);
+ if (a_string == NULL) {
return NULL;
}
- a_string = t;
}
ret_string = alloc_sub_basic(username, a_string);
@@ -724,6 +654,9 @@ char *alloc_sub_specified(const char *input_string,
return ret_string;
}
+/****************************************************************************
+****************************************************************************/
+
char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
int snum,
const char *user,
@@ -734,18 +667,23 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
{
char *a, *t;
a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str);
- if (!a) return NULL;
+ if (!a) {
+ return NULL;
+ }
t = talloc_strdup(mem_ctx, a);
SAFE_FREE(a);
return t;
}
+/****************************************************************************
+****************************************************************************/
+
char *alloc_sub_advanced(int snum, const char *user,
const char *connectpath, gid_t gid,
const char *smb_name, const char *str)
{
char *a_string, *ret_string;
- char *b, *p, *s, *t, *h;
+ char *b, *p, *s, *h;
a_string = SMB_STRDUP(str);
if (a_string == NULL) {
@@ -755,27 +693,27 @@ char *alloc_sub_advanced(int snum, const char *user,
for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
- b = t = a_string;
+ b = a_string;
switch (*(p+1)) {
case 'N' :
- t = realloc_string_sub(t, "%N", automount_server(user));
+ a_string = realloc_string_sub(a_string, "%N", automount_server(user));
break;
case 'H':
if ((h = get_user_home_dir(user)))
- t = realloc_string_sub(t, "%H", h);
+ a_string = realloc_string_sub(a_string, "%H", h);
break;
case 'P':
- t = realloc_string_sub(t, "%P", connectpath);
+ a_string = realloc_string_sub(a_string, "%P", connectpath);
break;
case 'S':
- t = realloc_string_sub(t, "%S", lp_servicename(snum));
+ a_string = realloc_string_sub(a_string, "%S", lp_servicename(snum));
break;
case 'g':
- t = realloc_string_sub(t, "%g", gidtoname(gid));
+ a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
break;
case 'u':
- t = realloc_string_sub(t, "%u", user);
+ a_string = realloc_string_sub(a_string, "%u", user);
break;
/* Patch from jkf@soton.ac.uk Left the %N (NIS
@@ -786,7 +724,7 @@ char *alloc_sub_advanced(int snum, const char *user,
* "path =" string in [homes] and so needs the
* service name, not the username. */
case 'p':
- t = realloc_string_sub(t, "%p", automount_path(lp_servicename(snum)));
+ a_string = realloc_string_sub(a_string, "%p", automount_path(lp_servicename(snum)));
break;
default:
@@ -794,11 +732,9 @@ char *alloc_sub_advanced(int snum, const char *user,
}
p++;
- if (t == NULL) {
- SAFE_FREE(a_string);
+ if (a_string == NULL) {
return NULL;
}
- a_string = t;
}
ret_string = alloc_sub_basic(smb_name, a_string);
@@ -812,10 +748,20 @@ char *alloc_sub_advanced(int snum, const char *user,
void standard_sub_conn(connection_struct *conn, char *str, size_t len)
{
- standard_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
- conn->gid, smb_user_name, str, len);
+ char *s;
+
+ s = alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
+ conn->gid, smb_user_name, str);
+
+ if ( s ) {
+ strncpy( str, s, len );
+ SAFE_FREE( s );
+ }
}
+/****************************************************************************
+****************************************************************************/
+
char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str)
{
return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user,
@@ -823,6 +769,9 @@ char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *
smb_user_name, str);
}
+/****************************************************************************
+****************************************************************************/
+
char *alloc_sub_conn(connection_struct *conn, const char *str)
{
return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
@@ -837,14 +786,21 @@ void standard_sub_snum(int snum, 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.uid) {
- fstrcpy(cached_user, uidtoname(current_user.uid));
- cached_uid = current_user.uid;
+ if (cached_uid != current_user.ut.uid) {
+ fstrcpy(cached_user, uidtoname(current_user.ut.uid));
+ cached_uid = current_user.ut.uid;
}
- standard_sub_advanced(snum, cached_user, "", current_user.gid,
- smb_user_name, str, len);
+ s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.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 e7bd288f6e8..61975264fd6 100644
--- a/source/lib/sysacls.c
+++ b/source/lib/sysacls.c
@@ -689,12 +689,8 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
* for each entry still to be processed
*/
if ((len + nbytes) > maxlen) {
- char *oldtext = text;
-
maxlen += nbytes + 20 * (acl_d->count - i);
-
- if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
- SAFE_FREE(oldtext);
+ if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
errno = ENOMEM;
return NULL;
}
@@ -1320,11 +1316,8 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
* for each entry still to be processed
*/
if ((len + nbytes) > maxlen) {
- char *oldtext = text;
-
maxlen += nbytes + 20 * (acl_d->count - i);
-
- if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
+ if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
free(oldtext);
errno = ENOMEM;
return NULL;
diff --git a/source/lib/sysquotas.c b/source/lib/sysquotas.c
index c1ab6ef8cfa..62714cf4d51 100644
--- a/source/lib/sysquotas.c
+++ b/source/lib/sysquotas.c
@@ -184,12 +184,12 @@ static struct {
static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
{
const char *get_quota_command;
+ char **lines = NULL;
get_quota_command = lp_get_quota_command();
if (get_quota_command && *get_quota_command) {
const char *p;
char *p2;
- char **lines;
pstring syscmd;
int _id = -1;
@@ -223,49 +223,79 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10);
p = p2;
- while (p && *p && isspace(*p))
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p);
- else
+ } else {
goto invalid_param;
- while (p && *p && isspace(*p))
+ }
+
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p);
- else
+ } else {
goto invalid_param;
- while (p && *p && isspace(*p))
+ }
+
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p);
- else
+ } else {
goto invalid_param;
- while (p && *p && isspace(*p))
+ }
+
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p);
- else
+ } else {
goto invalid_param;
- while (p && *p && isspace(*p))
+ }
+
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p);
- else
+ } else {
goto invalid_param;
- while (p && *p && isspace(*p))
+ }
+
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p);
- else
+ } else {
goto invalid_param;
- while (p && *p && isspace(*p))
+ }
+
+ while (p && *p && isspace(*p)) {
p++;
- if (p && *p)
+ }
+
+ if (p && *p) {
dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL);
- else
+ } else {
dp->bsize = 1024;
+ }
+
file_lines_free(lines);
+ lines = NULL;
+
DEBUG (3, ("Parsed output of get_quota, ...\n"));
#ifdef LARGE_SMB_OFF_T
@@ -298,6 +328,8 @@ static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t
return -1;
invalid_param:
+
+ file_lines_free(lines);
DEBUG(0,("The output of get_quota_command is invalid!\n"));
return -1;
}
diff --git a/source/lib/system.c b/source/lib/system.c
index e9c13e6d079..2e5f42307bd 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -22,6 +22,10 @@
#include "includes.h"
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
/*
The idea is that this file will eventually have wrappers around all
important system calls in samba. The aims are:
@@ -624,85 +628,125 @@ struct hostent *sys_gethostbyname(const char *name)
}
-#if defined(HAVE_IRIX_SPECIFIC_CAPABILITIES)
-/**************************************************************************
- Try and abstract process capabilities (for systems that have them).
-****************************************************************************/
-static BOOL set_process_capability( uint32 cap_flag, BOOL enable )
-{
- if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
- cap_t cap = cap_get_proc();
+#if defined(HAVE_POSIX_CAPABILITIES)
- if (cap == NULL) {
- DEBUG(0,("set_process_capability: cap_get_proc failed. Error was %s\n",
- strerror(errno)));
- return False;
- }
+#ifdef HAVE_SYS_CAPABILITY_H
- if(enable)
- cap->cap_effective |= CAP_NETWORK_MGT;
- else
- cap->cap_effective &= ~CAP_NETWORK_MGT;
+#if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
+#define _I386_STATFS_H
+#define _PPC_STATFS_H
+#define BROKEN_REDHAT_7_STATFS_WORKAROUND
+#endif
- if (cap_set_proc(cap) == -1) {
- DEBUG(0,("set_process_capability: cap_set_proc failed. Error was %s\n",
- strerror(errno)));
- cap_free(cap);
- return False;
- }
+#include <sys/capability.h>
- cap_free(cap);
+#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
+#undef _I386_STATFS_H
+#undef _PPC_STATFS_H
+#undef BROKEN_REDHAT_7_STATFS_WORKAROUND
+#endif
- DEBUG(10,("set_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
- }
- return True;
-}
+#endif /* HAVE_SYS_CAPABILITY_H */
/**************************************************************************
- Try and abstract inherited process capabilities (for systems that have them).
+ Try and abstract process capabilities (for systems that have them).
****************************************************************************/
-static BOOL set_inherited_process_capability( uint32 cap_flag, BOOL enable )
-{
- if(cap_flag == KERNEL_OPLOCK_CAPABILITY) {
- cap_t cap = cap_get_proc();
+/* Set the POSIX capabilities needed for the given purpose into the effective
+ * capability set of the current process. Make sure they are always removed
+ * from the inheritable set, because there is no circumstance in which our
+ * children should inherit our elevated privileges.
+ */
+static BOOL set_process_capability(enum smbd_capability capability,
+ BOOL enable)
+{
+ cap_value_t cap_vals[2] = {0};
+ int num_cap_vals = 0;
+
+ cap_t cap;
+
+#if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
+ /* On Linux, make sure that any capabilities we grab are sticky
+ * across UID changes. We expect that this would allow us to keep both
+ * the effective and permitted capability sets, but as of circa 2.6.16,
+ * only the permitted set is kept. It is a bug (which we work around)
+ * that the effective set is lost, but we still require the effective
+ * set to be kept.
+ */
+ if (!prctl(PR_GET_KEEPCAPS)) {
+ prctl(PR_SET_KEEPCAPS, 1);
+ }
+#endif
- if (cap == NULL) {
- DEBUG(0,("set_inherited_process_capability: cap_get_proc failed. Error was %s\n",
- strerror(errno)));
- return False;
- }
+ cap = cap_get_proc();
+ if (cap == NULL) {
+ DEBUG(0,("set_process_capability: cap_get_proc failed: %s\n",
+ strerror(errno)));
+ return False;
+ }
- if(enable)
- cap->cap_inheritable |= CAP_NETWORK_MGT;
- else
- cap->cap_inheritable &= ~CAP_NETWORK_MGT;
+ switch (capability) {
+ case KERNEL_OPLOCK_CAPABILITY:
+#ifdef CAP_NETWORK_MGT
+ /* IRIX has CAP_NETWORK_MGT for oplocks. */
+ cap_vals[num_cap_vals++] = CAP_NETWORK_MGT;
+#endif
+ break;
+ case DMAPI_ACCESS_CAPABILITY:
+#ifdef CAP_DEVICE_MGT
+ /* IRIX has CAP_DEVICE_MGT for DMAPI access. */
+ cap_vals[num_cap_vals++] = CAP_DEVICE_MGT;
+#elif CAP_MKNOD
+ /* Linux has CAP_MKNOD for DMAPI access. */
+ cap_vals[num_cap_vals++] = CAP_MKNOD;
+#endif
+ break;
+ }
- if (cap_set_proc(cap) == -1) {
- DEBUG(0,("set_inherited_process_capability: cap_set_proc failed. Error was %s\n",
- strerror(errno)));
- cap_free(cap);
- return False;
- }
+ SMB_ASSERT(num_cap_vals <= ARRAY_SIZE(cap_vals));
+ if (num_cap_vals == 0) {
cap_free(cap);
+ return True;
+ }
+
+ cap_set_flag(cap, CAP_EFFECTIVE, num_cap_vals, cap_vals,
+ enable ? CAP_SET : CAP_CLEAR);
- DEBUG(10,("set_inherited_process_capability: Set KERNEL_OPLOCK_CAPABILITY.\n"));
+ /* We never want to pass capabilities down to our children, so make
+ * sure they are not inherited.
+ */
+ cap_set_flag(cap, CAP_INHERITABLE, num_cap_vals, cap_vals, CAP_CLEAR);
+
+ if (cap_set_proc(cap) == -1) {
+ DEBUG(0, ("set_process_capability: cap_set_proc failed: %s\n",
+ strerror(errno)));
+ cap_free(cap);
+ return False;
}
+
+ cap_free(cap);
return True;
}
-#endif
+
+#endif /* HAVE_POSIX_CAPABILITIES */
/****************************************************************************
Gain the oplock capability from the kernel if possible.
****************************************************************************/
-void oplock_set_capability(BOOL this_process, BOOL inherit)
+void set_effective_capability(enum smbd_capability capability)
{
-#if HAVE_KERNEL_OPLOCKS_IRIX
- set_process_capability(KERNEL_OPLOCK_CAPABILITY,this_process);
- set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY,inherit);
-#endif
+#if defined(HAVE_POSIX_CAPABILITIES)
+ set_process_capability(capability, True);
+#endif /* HAVE_POSIX_CAPABILITIES */
+}
+
+void drop_effective_capability(enum smbd_capability capability)
+{
+#if defined(HAVE_POSIX_CAPABILITIES)
+ set_process_capability(capability, False);
+#endif /* HAVE_POSIX_CAPABILITIES */
}
/**************************************************************************
@@ -1374,6 +1418,8 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si
{
#if defined(HAVE_GETXATTR)
return getxattr(path, name, value, size);
+#elif defined(HAVE_GETEA)
+ return getea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FILE)
char *s;
ssize_t retval;
@@ -1416,6 +1462,8 @@ 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_LGETEA)
+ return lgetea(path, name, value, size);
#elif defined(HAVE_EXTATTR_GET_LINK)
char *s;
ssize_t retval;
@@ -1454,6 +1502,8 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
{
#if defined(HAVE_FGETXATTR)
return fgetxattr(filedes, name, value, size);
+#elif defined(HAVE_FGETEA)
+ return fgetea(filedes, name, value, size);
#elif defined(HAVE_EXTATTR_GET_FD)
char *s;
ssize_t retval;
@@ -1653,6 +1703,8 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size)
{
#if defined(HAVE_LISTXATTR)
return listxattr(path, list, size);
+#elif defined(HAVE_LISTEA)
+ return listea(path, list, size);
#elif defined(HAVE_EXTATTR_LIST_FILE)
extattr_arg arg;
arg.path = path;
@@ -1669,6 +1721,8 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size)
{
#if defined(HAVE_LLISTXATTR)
return llistxattr(path, list, size);
+#elif defined(HAVE_LLISTEA)
+ return llistea(path, list, size);
#elif defined(HAVE_EXTATTR_LIST_LINK)
extattr_arg arg;
arg.path = path;
@@ -1685,6 +1739,8 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size)
{
#if defined(HAVE_FLISTXATTR)
return flistxattr(filedes, list, size);
+#elif defined(HAVE_FLISTEA)
+ return flistea(filedes, list, size);
#elif defined(HAVE_EXTATTR_LIST_FD)
extattr_arg arg;
arg.filedes = filedes;
@@ -1701,6 +1757,8 @@ int sys_removexattr (const char *path, const char *name)
{
#if defined(HAVE_REMOVEXATTR)
return removexattr(path, name);
+#elif defined(HAVE_REMOVEEA)
+ return removeea(path, name);
#elif defined(HAVE_EXTATTR_DELETE_FILE)
char *s;
int attrnamespace = (strncmp(name, "system", 6) == 0) ?
@@ -1725,6 +1783,8 @@ int sys_lremovexattr (const char *path, const char *name)
{
#if defined(HAVE_LREMOVEXATTR)
return lremovexattr(path, name);
+#elif defined(HAVE_LREMOVEEA)
+ return lremoveea(path, name);
#elif defined(HAVE_EXTATTR_DELETE_LINK)
char *s;
int attrnamespace = (strncmp(name, "system", 6) == 0) ?
@@ -1749,6 +1809,8 @@ int sys_fremovexattr (int filedes, const char *name)
{
#if defined(HAVE_FREMOVEXATTR)
return fremovexattr(filedes, name);
+#elif defined(HAVE_FREMOVEEA)
+ return fremoveea(filedes, name);
#elif defined(HAVE_EXTATTR_DELETE_FD)
char *s;
int attrnamespace = (strncmp(name, "system", 6) == 0) ?
@@ -1778,6 +1840,8 @@ int sys_setxattr (const char *path, const char *name, const void *value, size_t
{
#if defined(HAVE_SETXATTR)
return setxattr(path, name, value, size, flags);
+#elif defined(HAVE_SETEA)
+ return setea(path, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FILE)
char *s;
int retval = 0;
@@ -1824,6 +1888,8 @@ 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(LSETEA)
+ return lsetea(path, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_LINK)
char *s;
int retval = 0;
@@ -1871,6 +1937,8 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size
{
#if defined(HAVE_FSETXATTR)
return fsetxattr(filedes, name, value, size, flags);
+#elif defined(HAVE_FSETEA)
+ return fsetea(filedes, name, value, size, flags);
#elif defined(HAVE_EXTATTR_SET_FD)
char *s;
int retval = 0;
diff --git a/source/lib/system_smbd.c b/source/lib/system_smbd.c
index 6c65f61ad7a..afa64489cfd 100644
--- a/source/lib/system_smbd.c
+++ b/source/lib/system_smbd.c
@@ -28,47 +28,6 @@
#ifndef HAVE_GETGROUPLIST
-static int int_compare( int *a, int *b )
-{
- if ( *a == *b )
- return 0;
- else if ( *a < *b )
- return -1;
- else
- return 1;
-}
-
-void remove_duplicate_gids( int *num_groups, gid_t *groups )
-{
- int i;
- int count = *num_groups;
-
- if ( *num_groups <= 0 || !groups )
- return;
-
- DEBUG(8,("remove_duplicate_gids: Enter %d gids\n", *num_groups));
-
- qsort( groups, *num_groups, sizeof(gid_t), QSORT_CAST int_compare );
-
- for ( i=1; i<count; ) {
- if ( groups[i-1] == groups[i] ) {
- memmove( &groups[i-1], &groups[i], (count - i + 1)*sizeof(gid_t) );
-
- /* decrement the total number of groups and do not increment
- the loop counter */
- count--;
- continue;
- }
- i++;
- }
-
- *num_groups = count;
-
- DEBUG(8,("remove_duplicate_gids: Exit %d gids\n", *num_groups));
-
- return;
-}
-
/*
This is a *much* faster way of getting the list of groups for a user
without changing the current supplementary group list. The old
@@ -79,7 +38,8 @@ void remove_duplicate_gids( int *num_groups, gid_t *groups )
NOTE!! this function only works if it is called as root!
*/
-static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
+static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups,
+ int *grpcnt)
{
gid_t *gids_saved;
int ret, ngrp_saved, num_gids;
@@ -140,9 +100,6 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
}
groups[0] = gid;
*grpcnt = ret + 1;
-
- /* remove any duplicates gids in the list */
- remove_duplicate_gids( grpcnt, groups );
}
restore_re_gid();
@@ -163,18 +120,19 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
{
int retval;
+ char *winbindd_env;
DEBUG(10,("sys_getgrouplist: user [%s]\n", user));
+
+ /* Save the winbindd state and not just blindly turn it back on */
+
+ winbindd_env = getenv(WINBINDD_DONT_ENV);
- /* see if we should disable winbindd lookups for local users */
- if (strchr(user, *lp_winbind_separator()) == NULL) {
- if ( !winbind_off() )
- DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n",
- WINBINDD_DONT_ENV));
- else
- DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n",
- user));
- }
+ /* This is only ever called for Unix users, remote memberships are
+ * always determined by the info3 coming back from auth3 or the
+ * PAC. */
+
+ winbind_off() ;
#ifdef HAVE_GETGROUPLIST
retval = getgrouplist(user, gid, groups, grpcnt);
@@ -184,14 +142,18 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp
unbecome_root();
#endif
- /* allow winbindd lookups */
- winbind_on();
-
+ /* allow winbindd lookups , but only if they were not already disabled */
+
+ if ( !(winbindd_env && strequal(winbindd_env, "1")) ) {
+ winbind_on();
+ }
+
return retval;
}
-static BOOL getgroups_user(const char *user, gid_t primary_gid,
- gid_t **ret_groups, size_t *p_ngroups)
+BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
+ gid_t primary_gid,
+ gid_t **ret_groups, size_t *p_ngroups)
{
size_t ngrp;
int max_grp;
@@ -206,15 +168,10 @@ static BOOL getgroups_user(const char *user, gid_t primary_gid,
}
if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
- gid_t *groups_tmp;
-
- groups_tmp = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp);
-
- if (!groups_tmp) {
- SAFE_FREE(temp_groups);
+ temp_groups = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp);
+ if (!temp_groups) {
return False;
}
- temp_groups = groups_tmp;
if (sys_getgrouplist(user, primary_gid,
temp_groups, &max_grp) == -1) {
@@ -229,51 +186,14 @@ static BOOL getgroups_user(const char *user, gid_t primary_gid,
groups = NULL;
/* Add in primary group first */
- add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp);
+ add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp);
for (i=0; i<max_grp; i++)
- add_gid_to_array_unique(NULL, temp_groups[i], &groups, &ngrp);
+ add_gid_to_array_unique(mem_ctx, temp_groups[i],
+ &groups, &ngrp);
*p_ngroups = ngrp;
*ret_groups = groups;
SAFE_FREE(temp_groups);
return True;
}
-
-NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
- const char *username,
- gid_t primary_gid,
- DOM_SID **pp_sids,
- gid_t **pp_gids,
- size_t *p_num_groups)
-{
- size_t i;
-
- if (!getgroups_user(username, primary_gid, pp_gids, p_num_groups)) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- if (*p_num_groups == 0) {
- smb_panic("primary group missing");
- }
-
- *pp_sids = SMB_MALLOC_ARRAY(DOM_SID, *p_num_groups);
-
- if (*pp_sids == NULL) {
- SAFE_FREE(pp_gids);
- return NT_STATUS_NO_MEMORY;
- }
-
- for (i=0; i<*p_num_groups; i++) {
- if (!NT_STATUS_IS_OK(gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]))) {
- DEBUG(1, ("get_user_groups: failed to convert "
- "gid %ld to a sid!\n",
- (long int)(*pp_gids)[i+1]));
- SAFE_FREE(*pp_sids);
- SAFE_FREE(*pp_gids);
- return NT_STATUS_NO_SUCH_USER;
- }
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source/lib/talloc.c b/source/lib/talloc.c
index 00f889d682c..c1116155065 100644
--- a/source/lib/talloc.c
+++ b/source/lib/talloc.c
@@ -289,7 +289,11 @@ static int talloc_unreference(const void *context, const void *ptr)
for (h=tc->refs;h;h=h->next) {
struct talloc_chunk *p = talloc_parent_chunk(h);
- if ((p==NULL && context==NULL) || TC_PTR_FROM_CHUNK(p) == context) break;
+ if (p == NULL) {
+ if (context == NULL) break;
+ } else if (TC_PTR_FROM_CHUNK(p) == context) {
+ break;
+ }
}
if (h == NULL) {
return -1;
@@ -879,6 +883,16 @@ 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)
@@ -1026,11 +1040,13 @@ char *talloc_append_string(const void *t, char *orig, const char *append)
{
char *ret;
size_t olen = strlen(orig);
- size_t alenz = strlen(append) + 1;
+ size_t alenz;
if (!append)
return orig;
+ alenz = strlen(append) + 1;
+
ret = talloc_realloc(t, orig, char, olen + alenz);
if (!ret)
return NULL;
@@ -1074,10 +1090,14 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
int len;
char *ret;
va_list ap2;
+ char c;
VA_COPY(ap2, ap);
- len = vsnprintf(NULL, 0, fmt, ap2);
+ /* this call looks strange, but it makes it work on older solaris boxes */
+ if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
+ return NULL;
+ }
ret = _talloc(t, len+1);
if (ret) {
@@ -1129,7 +1149,15 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
VA_COPY(ap2, ap);
s_len = tc->size - 1;
- len = vsnprintf(NULL, 0, fmt, ap2);
+ if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 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
+ * the original string. Most current callers of this
+ * function expect it to never return NULL.
+ */
+ return s;
+ }
s = talloc_realloc(NULL, s, char, s_len + len+1);
if (!s) return NULL;
diff --git a/source/lib/time.c b/source/lib/time.c
index 989589121b9..a13dcf1646a 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -231,7 +231,7 @@ time_t nt_time_to_unix(NTTIME *nt)
if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
****************************************************************************/
-time_t nt_time_to_unix_abs(NTTIME *nt)
+time_t nt_time_to_unix_abs(const NTTIME *nt)
{
double d;
time_t ret;
@@ -239,6 +239,7 @@ time_t nt_time_to_unix_abs(NTTIME *nt)
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);
@@ -250,11 +251,11 @@ time_t nt_time_to_unix_abs(NTTIME *nt)
/* reverse the time */
/* it's a negative value, turn it to positive */
- nt->high=~nt->high;
- nt->low=~nt->low;
+ neg_nt.high=~nt->high;
+ neg_nt.low=~nt->low;
- d = ((double)nt->high)*4.0*(double)(1<<30);
- d += (nt->low&0xFFF00000);
+ 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)) {
@@ -728,11 +729,24 @@ void init_nt_time(NTTIME *nt)
nt->low = 0xFFFFFFFF;
}
+BOOL nt_time_is_set(const NTTIME *nt)
+{
+ if ((nt->high == 0x7FFFFFFF) && (nt->low == 0xFFFFFFFF)) {
+ return False;
+ }
+
+ if ((nt->high == 0x80000000) && (nt->low == 0)) {
+ return False;
+ }
+
+ return True;
+}
+
/****************************************************************************
Check if NTTIME is 0.
****************************************************************************/
-BOOL nt_time_is_zero(NTTIME *nt)
+BOOL nt_time_is_zero(const NTTIME *nt)
{
if(nt->high==0) {
return True;
@@ -744,7 +758,7 @@ BOOL nt_time_is_zero(NTTIME *nt)
Check if two NTTIMEs are the same.
****************************************************************************/
-BOOL nt_time_equals(NTTIME *nt1, NTTIME *nt2)
+BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
{
return (nt1->high == nt2->high && nt1->low == nt2->low);
}
@@ -941,3 +955,105 @@ time_t generalized_to_unix_time(const char *str)
return timegm(&tm);
}
+
+/****************************************************************************
+ Return all the possible time fields from a stat struct as a timespec.
+****************************************************************************/
+
+struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
+{
+#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
+}
+
+struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
+
+ /* 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
+}
+
+struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
+{
+#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
+}
+
+#if 0
+/****************************************************************************
+ Return the best approximation to a 'create time' under UNIX from a stat
+ structure.
+****************************************************************************/
+
+struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+{
+ 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;
+}
+#endif
diff --git a/source/lib/username.c b/source/lib/username.c
index 7d66b320adf..3dcf9e18cc4 100644
--- a/source/lib/username.c
+++ b/source/lib/username.c
@@ -22,18 +22,12 @@
#include "includes.h"
/* internal functions */
-static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (const char *), int N);
-static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (const char *), int N);
-
-/*****************************************************************
- Check if a user or group name is local (this is a *local* name for
- *local* people, there's nothing for you here...).
-*****************************************************************/
-
-static BOOL name_is_local(const char *name)
-{
- return !(strchr_m(name, *lp_winbind_separator()));
-}
+static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
+ struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
+ int N);
+static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset,
+ struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
+ int N);
/****************************************************************************
Get a users home directory.
@@ -54,160 +48,6 @@ char *get_user_home_dir(const char *user)
return(pass->pw_dir);
}
-/*******************************************************************
- Map a username from a dos name to a unix name by looking in the username
- map. Note that this modifies the name in place.
- This is the main function that should be called *once* on
- any incoming or new username - in order to canonicalize the name.
- This is being done to de-couple the case conversions from the user mapping
- function. Previously, the map_username was being called
- every time Get_Pwnam was called.
- Returns True if username was changed, false otherwise.
-********************************************************************/
-
-BOOL map_username(fstring user)
-{
- static BOOL initialised=False;
- static fstring last_from,last_to;
- XFILE *f;
- char *mapfile = lp_username_map();
- char *s;
- pstring buf;
- BOOL mapped_user = False;
- char *cmd = lp_username_map_script();
-
- if (!*user)
- return False;
-
- if (strequal(user,last_to))
- return False;
-
- if (strequal(user,last_from)) {
- DEBUG(3,("Mapped user %s to %s\n",user,last_to));
- fstrcpy(user,last_to);
- return True;
- }
-
- /* first try the username map script */
-
- if ( *cmd ) {
- char **qlines;
- pstring command;
- int numlines, ret, fd;
-
- pstr_sprintf( command, "%s \"%s\"", cmd, user );
-
- DEBUG(10,("Running [%s]\n", command));
- ret = smbrun(command, &fd);
- DEBUGADD(10,("returned [%d]\n", ret));
-
- if ( ret != 0 ) {
- if (fd != -1)
- close(fd);
- return False;
- }
-
- numlines = 0;
- qlines = fd_lines_load(fd, &numlines);
- DEBUGADD(10,("Lines returned = [%d]\n", numlines));
- close(fd);
-
- /* should be either no lines or a single line with the mapped username */
-
- if (numlines) {
- DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] ));
- fstrcpy( user, qlines[0] );
- }
-
- file_lines_free(qlines);
-
- return numlines != 0;
- }
-
- /* ok. let's try the mapfile */
-
- if (!*mapfile)
- return False;
-
- if (!initialised) {
- *last_from = *last_to = 0;
- initialised = True;
- }
-
- f = x_fopen(mapfile,O_RDONLY, 0);
- if (!f) {
- DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) ));
- return False;
- }
-
- DEBUG(4,("Scanning username map %s\n",mapfile));
-
- while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
- char *unixname = s;
- char *dosname = strchr_m(unixname,'=');
- char **dosuserlist;
- BOOL return_if_mapped = False;
-
- if (!dosname)
- continue;
-
- *dosname++ = 0;
-
- while (isspace((int)*unixname))
- unixname++;
-
- if ('!' == *unixname) {
- return_if_mapped = True;
- unixname++;
- while (*unixname && isspace((int)*unixname))
- unixname++;
- }
-
- if (!*unixname || strchr_m("#;",*unixname))
- continue;
-
- {
- int l = strlen(unixname);
- while (l && isspace((int)unixname[l-1])) {
- unixname[l-1] = 0;
- l--;
- }
- }
-
- dosuserlist = str_list_make(dosname, NULL);
- if (!dosuserlist) {
- DEBUG(0,("Unable to build user list\n"));
- return False;
- }
-
- if (strchr_m(dosname,'*') || user_in_list(user, (const char **)dosuserlist, NULL, 0)) {
- DEBUG(3,("Mapped user %s to %s\n",user,unixname));
- mapped_user = True;
- fstrcpy( last_from,user );
- fstrcpy( user, unixname );
- fstrcpy( last_to,user );
- if ( return_if_mapped ) {
- str_list_free (&dosuserlist);
- x_fclose(f);
- return True;
- }
- }
-
- str_list_free (&dosuserlist);
- }
-
- x_fclose(f);
-
- /*
- * Setup the last_from and last_to as an optimization so
- * that we don't scan the file again for the same user.
- */
- fstrcpy(last_from,user);
- fstrcpy(last_to,user);
-
- return mapped_user;
-}
-
/****************************************************************************
* A wrapper for sys_getpwnam(). The following variations are tried:
* - as transmitted
@@ -218,7 +58,8 @@ BOOL map_username(fstring user)
static struct passwd *Get_Pwnam_ret = NULL;
-static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
+static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx,
+ const char *user, char *user2)
{
struct passwd *ret = NULL;
@@ -232,7 +73,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
common case on UNIX systems */
strlower_m(user2);
DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2));
- ret = getpwnam_alloc(user2);
+ ret = getpwnam_alloc(mem_ctx, user2);
if(ret)
goto done;
@@ -240,7 +81,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
if(strcmp(user, user2) != 0) {
DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n",
user));
- ret = getpwnam_alloc(user);
+ ret = getpwnam_alloc(mem_ctx, user);
if(ret)
goto done;
}
@@ -250,7 +91,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
if(strcmp(user, user2) != 0) {
DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n",
user2));
- ret = getpwnam_alloc(user2);
+ ret = getpwnam_alloc(mem_ctx, user2);
if(ret)
goto done;
}
@@ -259,7 +100,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
strlower_m(user2);
DEBUG(5,("Checking combinations of %d uppercase letters in %s\n",
lp_usernamelevel(), user2));
- ret = uname_string_combinations(user2, getpwnam_alloc,
+ ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc,
lp_usernamelevel());
done:
@@ -275,7 +116,7 @@ done:
This will return an allocated structure
****************************************************************************/
-struct passwd *Get_Pwnam_alloc(const char *user)
+struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user)
{
fstring user2;
struct passwd *ret;
@@ -289,7 +130,7 @@ struct passwd *Get_Pwnam_alloc(const char *user)
DEBUG(5,("Finding user %s\n", user));
- ret = Get_Pwnam_internals(user, user2);
+ ret = Get_Pwnam_internals(mem_ctx, user, user2);
return ret;
}
@@ -303,7 +144,7 @@ struct passwd *Get_Pwnam(const char *user)
{
struct passwd *ret;
- ret = Get_Pwnam_alloc(user);
+ ret = Get_Pwnam_alloc(NULL, user);
/* This call used to just return the 'passwd' static buffer.
This could then have accidental reuse implications, so
@@ -320,7 +161,7 @@ struct passwd *Get_Pwnam(const char *user)
*/
if (Get_Pwnam_ret) {
- passwd_free(&Get_Pwnam_ret);
+ TALLOC_FREE(Get_Pwnam_ret);
}
Get_Pwnam_ret = ret;
@@ -328,374 +169,6 @@ struct passwd *Get_Pwnam(const char *user)
return ret;
}
-/****************************************************************************
- Check if a user is in a netgroup user list. If at first we don't succeed,
- try lower case.
-****************************************************************************/
-
-static BOOL user_in_netgroup_list(const char *user, const char *ngname)
-{
-#ifdef HAVE_NETGROUP
- static char *mydomain = NULL;
- fstring lowercase_user;
-
- if (mydomain == NULL)
- yp_get_default_domain(&mydomain);
-
- if(mydomain == NULL) {
- DEBUG(5,("Unable to get default yp domain\n"));
- return False;
- }
-
- DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
- user, mydomain, ngname));
-
- if (innetgr(ngname, NULL, user, mydomain)) {
- DEBUG(5,("user_in_netgroup_list: Found\n"));
- return (True);
- } else {
-
- /*
- * Ok, innetgr is case sensitive. Try once more with lowercase
- * just in case. Attempt to fix #703. JRA.
- */
-
- fstrcpy(lowercase_user, user);
- strlower_m(lowercase_user);
-
- DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
- lowercase_user, mydomain, ngname));
-
- if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
- DEBUG(5,("user_in_netgroup_list: Found\n"));
- return (True);
- }
- }
-#endif /* HAVE_NETGROUP */
- return False;
-}
-
-/****************************************************************************
- Check if a user is in a winbind group.
-****************************************************************************/
-
-static BOOL user_in_winbind_group_list(const char *user, const char *gname,
- BOOL *winbind_answered)
-{
- int i;
- gid_t gid, gid_low, gid_high;
- BOOL ret = False;
- static gid_t *groups = NULL;
- static int num_groups = 0;
- static fstring last_user = "";
-
- *winbind_answered = False;
-
- if ((gid = nametogid(gname)) == (gid_t)-1) {
- DEBUG(0,("user_in_winbind_group_list: nametogid for group %s "
- "failed.\n", gname ));
- goto err;
- }
-
- if (!lp_idmap_gid(&gid_low, &gid_high)) {
- DEBUG(4, ("winbind gid range not configured, therefore %s "
- "cannot be a winbind group\n", gname));
- goto err;
- }
-
- if (gid < gid_low || gid > gid_high) {
- DEBUG(4, ("group %s is not a winbind group\n", gname));
- goto err;
- }
-
- /* try to user the last user we looked up */
- /* otherwise fall back to lookups */
-
- if ( !strequal( last_user, user ) || !groups )
- {
- /* clear any cached information */
-
- SAFE_FREE(groups);
- fstrcpy( last_user, "" );
-
- /*
- * Get the gid's that this user belongs to.
- */
-
- if ((num_groups = winbind_getgroups(user, &groups)) == -1)
- return False;
-
- if ( num_groups == -1 )
- return False;
-
- if ( num_groups == 0 ) {
- *winbind_answered = True;
- return False;
- }
-
- /* save the last username */
-
- fstrcpy( last_user, user );
-
- }
- else
- DEBUG(10,("user_in_winbind_group_list: using cached user "
- "groups for [%s]\n", user));
-
- if ( DEBUGLEVEL >= 10 ) {
- DEBUG(10,("user_in_winbind_group_list: using groups -- "));
- for ( i=0; i<num_groups; i++ )
- DEBUGADD(10,("%lu ", (unsigned long)groups[i]));
- DEBUGADD(10,("\n"));
- }
-
- /*
- * Now we have the gid list for this user - convert the gname to a
- * gid_t via either winbind or the local UNIX lookup and do the
- * comparison.
- */
-
- for (i = 0; i < num_groups; i++) {
- if (gid == groups[i]) {
- ret = True;
- break;
- }
- }
-
- *winbind_answered = True;
- SAFE_FREE(groups);
- return ret;
-
- err:
-
- *winbind_answered = False;
- SAFE_FREE(groups);
- return False;
-}
-
-/****************************************************************************
- Check if a user is in a UNIX group.
-****************************************************************************/
-
-BOOL user_in_unix_group_list(const char *user,const char *gname)
-{
- struct passwd *pass = Get_Pwnam(user);
- struct sys_userlist *user_list;
- struct sys_userlist *member;
-
- DEBUG(10,("user_in_unix_group_list: checking user %s in group %s\n",
- user, gname));
-
- /*
- * We need to check the users primary group as this
- * group is implicit and often not listed in the group database.
- */
-
- if (pass) {
- if (strequal(gname,gidtoname(pass->pw_gid))) {
- DEBUG(10,("user_in_unix_group_list: group %s is "
- "primary group.\n", gname ));
- return True;
- }
- }
-
- user_list = get_users_in_group(gname);
- if (user_list == NULL) {
- DEBUG(10,("user_in_unix_group_list: no such group %s\n",
- gname ));
- return False;
- }
-
- for (member = user_list; member; member = member->next) {
- DEBUG(10,("user_in_unix_group_list: checking user %s against "
- "member %s\n", user, member->unix_name ));
- if (strequal(member->unix_name,user)) {
- free_userlist(user_list);
- return(True);
- }
- }
-
- free_userlist(user_list);
- return False;
-}
-
-/****************************************************************************
- Check if a user is in a group list. Ask winbind first, then use UNIX.
-****************************************************************************/
-
-BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups,
- size_t n_groups)
-{
- BOOL winbind_answered = False;
- BOOL ret;
- gid_t gid;
- unsigned i;
-
- gid = nametogid(gname);
- if (gid == (gid_t)-1)
- return False;
-
- if (groups && n_groups > 0) {
- for (i=0; i < n_groups; i++) {
- if (groups[i] == gid) {
- return True;
- }
- }
- return False;
- }
-
- /* fallback if we don't yet have the group list */
-
- ret = user_in_winbind_group_list(user, gname, &winbind_answered);
- if (!winbind_answered)
- ret = user_in_unix_group_list(user, gname);
-
- if (ret)
- DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n",
- user, gname));
- return ret;
-}
-
-/****************************************************************************
- Check if a user is in a user list - can check combinations of UNIX
- and netgroup lists.
-****************************************************************************/
-
-BOOL user_in_list(const char *user,const char **list, gid_t *groups,
- size_t n_groups)
-{
- if (!list || !*list)
- return False;
-
- DEBUG(10,("user_in_list: checking user %s in list\n", user));
-
- while (*list) {
-
- DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
- user, *list));
-
- /*
- * Check raw username.
- */
- if (strequal(user, *list))
- return(True);
-
- /*
- * Now check to see if any combination
- * of UNIX and netgroups has been specified.
- */
-
- if(**list == '@') {
- /*
- * Old behaviour. Check netgroup list
- * followed by UNIX list.
- */
- if(user_in_netgroup_list(user, *list +1))
- return True;
- if(user_in_group_list(user, *list +1, groups,
- n_groups))
- return True;
- } else if (**list == '+') {
-
- if((*(*list +1)) == '&') {
- /*
- * Search UNIX list followed by netgroup.
- */
- if(user_in_group_list(user, *list +2, groups,
- n_groups))
- return True;
- if(user_in_netgroup_list(user, *list +2))
- return True;
-
- } else {
-
- /*
- * Just search UNIX list.
- */
-
- if(user_in_group_list(user, *list +1, groups,
- n_groups))
- return True;
- }
-
- } else if (**list == '&') {
-
- if(*(*list +1) == '+') {
- /*
- * Search netgroup list followed by UNIX list.
- */
- if(user_in_netgroup_list(user, *list +2))
- return True;
- if(user_in_group_list(user, *list +2, groups,
- n_groups))
- return True;
- } else {
- /*
- * Just search netgroup list.
- */
- if(user_in_netgroup_list(user, *list +1))
- return True;
- }
- } else if (!name_is_local(*list)) {
- /*
- * If user name did not match and token is not a unix
- * group and the token has a winbind separator in the
- * name then see if it is a Windows group.
- */
-
- DOM_SID g_sid;
- enum SID_NAME_USE name_type;
- BOOL winbind_answered = False;
- BOOL ret;
- fstring groupname, domain;
-
- /* Parse a string of the form DOMAIN/user into a
- * domain and a user */
-
- char *p = strchr(*list,*lp_winbind_separator());
-
- DEBUG(10,("user_in_list: checking if user |%s| is in "
- "winbind group |%s|\n", user, *list));
-
- if (p) {
- fstrcpy(groupname, p+1);
- fstrcpy(domain, *list);
- domain[PTR_DIFF(p, *list)] = 0;
-
- /* Check to see if name is a Windows group;
- Win2k native mode DCs will return domain
- local groups; while NT4 or mixed mode 2k
- DCs will not */
-
- if ( winbind_lookup_name(domain, groupname,
- &g_sid, &name_type)
- && ( name_type==SID_NAME_DOM_GRP ||
- (strequal(lp_workgroup(), domain) &&
- name_type==SID_NAME_ALIAS) ) )
- {
-
- /* Check if user name is in the
- * Windows group */
- ret = user_in_winbind_group_list(
- user, *list,
- &winbind_answered);
-
- if (winbind_answered && ret == True) {
- DEBUG(10,("user_in_list: user "
- "|%s| is in winbind "
- "group |%s|\n",
- user, *list));
- return ret;
- }
- }
- }
- }
-
- list++;
- }
- return(False);
-}
-
/* The functions below have been taken from password.c and slightly modified */
/****************************************************************************
Apply a function to upper/lower case combinations
@@ -705,21 +178,24 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
it assumes the string starts lowercased
****************************************************************************/
-static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(const char *),int N)
+static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx,
+ int offset,
+ struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *),
+ int N)
{
ssize_t len = (ssize_t)strlen(s);
int i;
struct passwd *ret;
if (N <= 0 || offset >= len)
- return(fn(s));
+ return(fn(mem_ctx, s));
for (i=offset;i<(len-(N-1));i++) {
char c = s[i];
if (!islower_ascii((int)c))
continue;
s[i] = toupper_ascii(c);
- ret = uname_string_combinations2(s,i+1,fn,N-1);
+ ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1);
if(ret)
return(ret);
s[i] = c;
@@ -735,13 +211,15 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw
it assumes the string starts lowercased
****************************************************************************/
-static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(const char *),int N)
+static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
+ struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *),
+ int N)
{
int n;
struct passwd *ret;
for (n=1;n<=N;n++) {
- ret = uname_string_combinations2(s,0,fn,n);
+ ret = uname_string_combinations2(s,mem_ctx,0,fn,n);
if(ret)
return(ret);
}
diff --git a/source/lib/util.c b/source/lib/util.c
index 38878befc77..c023df0b017 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -5,7 +5,8 @@
Copyright (C) Jeremy Allison 2001-2002
Copyright (C) Simo Sorce 2001
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 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
the Free Software Foundation; either version 2 of the License, or
@@ -179,6 +180,31 @@ static BOOL set_my_netbios_names(const char *name, int i)
return True;
}
+/***********************************************************************
+ Free memory allocated to global objects
+***********************************************************************/
+
+void gfree_names(void)
+{
+ SAFE_FREE( smb_myname );
+ SAFE_FREE( smb_myworkgroup );
+ SAFE_FREE( smb_scope );
+ free_netbios_names_array();
+}
+
+void gfree_all( void )
+{
+ gfree_names();
+ gfree_loadparm();
+ gfree_case_tables();
+ gfree_debugsyms();
+ gfree_charcnv();
+ gfree_messsges();
+
+ /* release the talloc null_context memory last */
+ talloc_nc_free();
+}
+
const char *my_netbios_names(int i)
{
return smb_my_netbios_names[i];
@@ -291,13 +317,15 @@ void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
return;
}
- if (mem_ctx != NULL)
+ if (mem_ctx != NULL) {
*gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
- else
+ } else {
*gids = SMB_REALLOC_ARRAY(*gids, gid_t, *num_gids+1);
+ }
- if (*gids == NULL)
+ if (*gids == NULL) {
return;
+ }
(*gids)[*num_gids] = gid;
*num_gids += 1;
@@ -342,14 +370,10 @@ const char *get_numlist(const char *p, uint32 **num, int *count)
(*num ) = NULL;
while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
- uint32 *tn;
-
- tn = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1);
- if (tn == NULL) {
- SAFE_FREE(*num);
+ *num = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1);
+ if (!(*num)) {
return NULL;
- } else
- (*num) = tn;
+ }
(*num)[(*count)] = val;
(*count)++;
p++;
@@ -506,8 +530,9 @@ void smb_setlen(char *buf,int len)
int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
{
- if (zero)
+ if (zero && (num_words || num_bytes)) {
memset(buf + smb_size,'\0',num_words*2 + num_bytes);
+ }
SCVAL(buf,smb_wct,num_words);
SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
@@ -825,7 +850,7 @@ void smb_msleep(unsigned int t)
Become a daemon, discarding the controlling terminal.
****************************************************************************/
-void become_daemon(BOOL Fork)
+void become_daemon(BOOL Fork, BOOL no_process_group)
{
if (Fork) {
if (sys_fork()) {
@@ -835,9 +860,9 @@ void become_daemon(BOOL Fork)
/* detach from the terminal */
#ifdef HAVE_SETSID
- setsid();
+ if (!no_process_group) setsid();
#elif defined(TIOCNOTTY)
- {
+ if (!no_process_group) {
int i = sys_open("/dev/tty", O_RDWR, 0);
if (i != -1) {
ioctl(i, (int) TIOCNOTTY, (char *)0);
@@ -941,32 +966,68 @@ void *calloc_array(size_t size, size_t nmemb)
/****************************************************************************
Expand a pointer to be a particular size.
+ Note that this version of Realloc has an extra parameter that decides
+ whether to free the passed in storage on allocation failure or if the
+ new size is zero.
+
+ This is designed for use in the typical idiom of :
+
+ p = SMB_REALLOC(p, size)
+ if (!p) {
+ return error;
+ }
+
+ and not to have to keep track of the old 'p' contents to free later, nor
+ to worry if the size parameter was zero. In the case where NULL is returned
+ we guarentee that p has been freed.
+
+ If free later semantics are desired, then pass 'free_old_on_error' as False which
+ guarentees that the old contents are not freed on error, even if size == 0. To use
+ this idiom use :
+
+ tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
+ if (!tmp) {
+ SAFE_FREE(p);
+ return error;
+ } else {
+ p = tmp;
+ }
+
+ Changes were instigated by Coverity error checking. JRA.
****************************************************************************/
-void *Realloc(void *p,size_t size)
+void *Realloc(void *p, size_t size, BOOL free_old_on_error)
{
void *ret=NULL;
if (size == 0) {
- SAFE_FREE(p);
- DEBUG(5,("Realloc asked for 0 bytes\n"));
+ if (free_old_on_error) {
+ SAFE_FREE(p);
+ }
+ DEBUG(2,("Realloc asked for 0 bytes\n"));
return NULL;
}
#if defined(PARANOID_MALLOC_CHECKER)
- if (!p)
+ if (!p) {
ret = (void *)malloc_(size);
- else
+ } else {
ret = (void *)realloc_(p,size);
+ }
#else
- if (!p)
+ if (!p) {
ret = (void *)malloc(size);
- else
+ } else {
ret = (void *)realloc(p,size);
+ }
#endif
- if (!ret)
+ if (!ret) {
+ if (free_old_on_error && p) {
+ SAFE_FREE(p);
+ }
DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
+ }
return(ret);
}
@@ -975,23 +1036,28 @@ void *Realloc(void *p,size_t size)
Type-safe realloc.
****************************************************************************/
-void *realloc_array(void *p,size_t el_size, unsigned int count)
+void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_on_error)
{
if (count >= MAX_ALLOC_SIZE/el_size) {
+ if (free_old_on_error) {
+ SAFE_FREE(p);
+ }
return NULL;
}
- return Realloc(p,el_size*count);
+ return Realloc(p, el_size*count, free_old_on_error);
}
/****************************************************************************
- (Hopefully) efficient array append
+ (Hopefully) efficient array append.
****************************************************************************/
+
void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
void *element, void **array, uint32 *num_elements,
ssize_t *array_size)
{
- if (*array_size < 0)
+ if (*array_size < 0) {
return;
+ }
if (*array == NULL) {
if (*array_size == 0) {
@@ -1002,13 +1068,15 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
goto error;
}
- if (mem_ctx != NULL)
+ if (mem_ctx != NULL) {
*array = TALLOC(mem_ctx, element_size * (*array_size));
- else
+ } else {
*array = SMB_MALLOC(element_size * (*array_size));
+ }
- if (*array == NULL)
+ if (*array == NULL) {
goto error;
+ }
}
if (*num_elements == *array_size) {
@@ -1018,15 +1086,17 @@ void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
goto error;
}
- if (mem_ctx != NULL)
+ if (mem_ctx != NULL) {
*array = TALLOC_REALLOC(mem_ctx, *array,
element_size * (*array_size));
- else
+ } else {
*array = SMB_REALLOC(*array,
element_size * (*array_size));
+ }
- if (*array == NULL)
+ if (*array == NULL) {
goto error;
+ }
}
memcpy((char *)(*array) + element_size*(*num_elements),
@@ -1427,10 +1497,10 @@ const char *uidtoname(uid_t uid)
static fstring name;
struct passwd *pass;
- pass = getpwuid_alloc(uid);
+ pass = getpwuid_alloc(NULL, uid);
if (pass) {
fstrcpy(name, pass->pw_name);
- passwd_free(&pass);
+ TALLOC_FREE(pass);
} else {
slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
}
@@ -1464,10 +1534,10 @@ uid_t nametouid(const char *name)
char *p;
uid_t u;
- pass = getpwnam_alloc(name);
+ pass = getpwnam_alloc(NULL, name);
if (pass) {
u = pass->pw_uid;
- passwd_free(&pass);
+ TALLOC_FREE(pass);
return u;
}
@@ -1499,30 +1569,13 @@ gid_t nametogid(const char *name)
}
/*******************************************************************
- legacy wrapper for smb_panic2()
-********************************************************************/
-void smb_panic( const char *why )
-{
- smb_panic2( why, True );
-}
-
-/*******************************************************************
Something really nasty happened - panic !
********************************************************************/
-#ifdef HAVE_LIBEXC_H
-#include <libexc.h>
-#endif
-
-void smb_panic2(const char *why, BOOL decrement_pid_count )
+void smb_panic(const char *const why)
{
char *cmd;
int result;
-#ifdef HAVE_BACKTRACE_SYMBOLS
- void *backtrace_stack[BACKTRACE_STACK_SIZE];
- size_t backtrace_size;
- char **backtrace_strings;
-#endif
#ifdef DEVELOPER
{
@@ -1535,9 +1588,12 @@ void smb_panic2(const char *why, BOOL decrement_pid_count )
}
#endif
+ DEBUG(0,("PANIC (pid %llu): %s\n",
+ (unsigned long long)sys_getpid(), why));
+ log_stack_trace();
+
/* only smbd needs to decrement the smbd counter in connections.tdb */
- if ( decrement_pid_count )
- decrement_smbd_process_count();
+ decrement_smbd_process_count();
cmd = lp_panic_action();
if (cmd && *cmd) {
@@ -1551,9 +1607,90 @@ void smb_panic2(const char *why, BOOL decrement_pid_count )
DEBUG(0, ("smb_panic(): action returned status %d\n",
WEXITSTATUS(result)));
}
- DEBUG(0,("PANIC: %s\n", why));
-#ifdef HAVE_BACKTRACE_SYMBOLS
+ dump_core();
+}
+
+/*******************************************************************
+ Print a backtrace of the stack to the debug log. This function
+ DELIBERATELY LEAKS MEMORY. The expectation is that you should
+ exit shortly after calling it.
+********************************************************************/
+
+#ifdef HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+#ifdef HAVE_LIBEXC_H
+#include <libexc.h>
+#endif
+
+void log_stack_trace(void)
+{
+#ifdef HAVE_LIBUNWIND
+ /* Try to use libunwind before any other technique since on ia64
+ * libunwind correctly walks the stack in more circumstances than
+ * backtrace.
+ */
+ unw_cursor_t cursor;
+ unw_context_t uc;
+ unsigned i = 0;
+
+ char procname[256];
+ unw_word_t ip, sp, off;
+
+ procname[sizeof(procname) - 1] = '\0';
+
+ if (unw_getcontext(&uc) != 0) {
+ goto libunwind_failed;
+ }
+
+ if (unw_init_local(&cursor, &uc) != 0) {
+ goto libunwind_failed;
+ }
+
+ DEBUG(0, ("BACKTRACE:\n"));
+
+ do {
+ ip = sp = 0;
+ unw_get_reg(&cursor, UNW_REG_IP, &ip);
+ unw_get_reg(&cursor, UNW_REG_SP, &sp);
+
+ switch (unw_get_proc_name(&cursor,
+ procname, sizeof(procname) - 1, &off) ) {
+ case 0:
+ /* Name found. */
+ case -UNW_ENOMEM:
+ /* Name truncated. */
+ DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
+ i, procname, (long long)off,
+ (long long)ip, (long long) sp));
+ break;
+ default:
+ /* case -UNW_ENOINFO: */
+ /* case -UNW_EUNSPEC: */
+ /* No symbol name found. */
+ DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
+ i, "<unknown symbol>",
+ (long long)ip, (long long) sp));
+ }
+ ++i;
+ } while (unw_step(&cursor) > 0);
+
+ return;
+
+libunwind_failed:
+ DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
+
+#elif HAVE_BACKTRACE_SYMBOLS
+ void *backtrace_stack[BACKTRACE_STACK_SIZE];
+ size_t backtrace_size;
+ char **backtrace_strings;
+
/* get the backtrace (stack frames) */
backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
@@ -1572,52 +1709,45 @@ void smb_panic2(const char *why, BOOL decrement_pid_count )
#elif HAVE_LIBEXC
-#define NAMESIZE 32 /* Arbitrary */
-
/* The IRIX libexc library provides an API for unwinding the stack. See
* libexc(3) for details. Apparantly trace_back_stack leaks memory, but
* since we are about to abort anyway, it hardly matters.
- *
- * Note that if we paniced due to a SIGSEGV or SIGBUS (or similar) this
- * will fail with a nasty message upon failing to open the /proc entry.
*/
- {
- __uint64_t addrs[BACKTRACE_STACK_SIZE];
- char * names[BACKTRACE_STACK_SIZE];
- char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
- int i;
- int levels;
+#define NAMESIZE 32 /* Arbitrary */
+
+ __uint64_t addrs[BACKTRACE_STACK_SIZE];
+ char * names[BACKTRACE_STACK_SIZE];
+ char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
- ZERO_ARRAY(addrs);
- ZERO_ARRAY(names);
- ZERO_ARRAY(namebuf);
+ int i;
+ int levels;
- /* We need to be root so we can open our /proc entry to walk
- * our stack. It also helps when we want to dump core.
- */
- become_root();
+ ZERO_ARRAY(addrs);
+ ZERO_ARRAY(names);
+ ZERO_ARRAY(namebuf);
- for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
- names[i] = namebuf + (i * NAMESIZE);
- }
+ /* We need to be root so we can open our /proc entry to walk
+ * our stack. It also helps when we want to dump core.
+ */
+ become_root();
+
+ for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
+ names[i] = namebuf + (i * NAMESIZE);
+ }
- levels = trace_back_stack(0, addrs, names,
- BACKTRACE_STACK_SIZE, NAMESIZE - 1);
+ levels = trace_back_stack(0, addrs, names,
+ BACKTRACE_STACK_SIZE, NAMESIZE - 1);
- DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
- for (i = 0; i < levels; i++) {
- DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
- }
- }
+ DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
+ for (i = 0; i < levels; i++) {
+ DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
+ }
#undef NAMESIZE
-#endif
- dbgflush();
-#ifdef SIGABRT
- CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
+#else
+ DEBUG(0, ("unable to produce a stack trace on this platform\n"));
#endif
- abort();
}
/*******************************************************************
@@ -1643,7 +1773,7 @@ const char *readdirname(SMB_STRUCT_DIR *p)
return(NULL);
#endif
-#ifdef HAVE_BROKEN_READDIR
+#ifdef HAVE_BROKEN_READDIR_NAME
/* using /usr/ucb/cc is BAD */
dname = dname - 2;
#endif
@@ -1810,6 +1940,7 @@ void free_namearray(name_compare_entry *name_array)
/****************************************************************************
Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
is dealt with in posix.c
+ Returns True if the lock was granted, False otherwise.
****************************************************************************/
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
@@ -1827,34 +1958,54 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
ret = sys_fcntl_ptr(fd,op,&lock);
- if (ret == -1 && errno != 0)
- DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
-
- /* a lock query */
- if (op == SMB_F_GETLK) {
- if ((ret != -1) &&
- (lock.l_type != F_UNLCK) &&
- (lock.l_pid != 0) &&
- (lock.l_pid != sys_getpid())) {
- DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
- return(True);
- }
-
- /* it must be not locked or locked by me */
- return(False);
- }
-
- /* a lock set or unset */
if (ret == -1) {
DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
(double)offset,(double)count,op,type,strerror(errno)));
- return(False);
+ return False;
}
/* everything went OK */
DEBUG(8,("fcntl_lock: Lock call successful\n"));
- return(True);
+ return True;
+}
+
+/****************************************************************************
+ Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
+ is dealt with in posix.c
+ Returns True if we have information regarding this lock region (and returns
+ F_UNLCK in *ptype if the region is unlocked). False if the call failed.
+****************************************************************************/
+
+BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
+{
+ SMB_STRUCT_FLOCK lock;
+ int ret;
+
+ DEBUG(8,("fcntl_getlock %d %.0f %.0f %d\n",fd,(double)*poffset,(double)*pcount,*ptype));
+
+ lock.l_type = *ptype;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = *poffset;
+ lock.l_len = *pcount;
+ lock.l_pid = 0;
+
+ ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
+
+ if (ret == -1) {
+ DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
+ (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
+ return False;
+ }
+
+ *ptype = lock.l_type;
+ *poffset = lock.l_start;
+ *pcount = lock.l_len;
+ *ppid = lock.l_pid;
+
+ DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
+ fd, (int)lock.l_type, (unsigned int)lock.l_pid));
+ return True;
}
#undef DBGC_CLASS
diff --git a/source/lib/util_file.c b/source/lib/util_file.c
index 407a8b24fc9..ed7be3f6c1d 100644
--- a/source/lib/util_file.c
+++ b/source/lib/util_file.c
@@ -322,16 +322,11 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f)
}
if (!s2 && len > maxlen-3) {
- char *t;
-
maxlen *= 2;
- t = (char *)SMB_REALLOC(s,maxlen);
- if (!t) {
+ s = (char *)SMB_REALLOC(s,maxlen);
+ if (!s) {
DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
- SAFE_FREE(s);
return(NULL);
- } else {
- s = t;
}
}
}
@@ -345,7 +340,7 @@ char *fgets_slash(char *s2,int maxlen,XFILE *f)
char *file_pload(char *syscmd, size_t *size)
{
int fd, n;
- char *p, *tp;
+ char *p;
pstring buf;
size_t total;
@@ -358,19 +353,19 @@ char *file_pload(char *syscmd, size_t *size)
total = 0;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
- tp = SMB_REALLOC(p, total + n + 1);
- if (!tp) {
+ p = SMB_REALLOC(p, total + n + 1);
+ if (!p) {
DEBUG(0,("file_pload: failed to expand buffer!\n"));
close(fd);
- SAFE_FREE(p);
return NULL;
- } else {
- p = tp;
}
memcpy(p+total, buf, n);
total += n;
}
- if (p) p[total] = 0;
+
+ if (p) {
+ p[total] = 0;
+ }
/* FIXME: Perhaps ought to check that the command completed
* successfully (returned 0); if not the data may be
@@ -386,30 +381,37 @@ char *file_pload(char *syscmd, size_t *size)
/****************************************************************************
Load a file into memory from a fd.
+ Truncate at maxsize. If maxsize == 0 - no limit.
****************************************************************************/
-char *fd_load(int fd, size_t *size)
+char *fd_load(int fd, size_t *psize, size_t maxsize)
{
SMB_STRUCT_STAT sbuf;
+ size_t size;
char *p;
if (sys_fstat(fd, &sbuf) != 0) {
return NULL;
}
- p = (char *)SMB_MALLOC(sbuf.st_size+1);
+ size = sbuf.st_size;
+ if (maxsize) {
+ size = MIN(size, maxsize);
+ }
+
+ p = (char *)SMB_MALLOC(size+1);
if (!p) {
return NULL;
}
- if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
+ if (read(fd, p, size) != size) {
SAFE_FREE(p);
return NULL;
}
- p[sbuf.st_size] = 0;
+ p[size] = 0;
- if (size) {
- *size = sbuf.st_size;
+ if (psize) {
+ *psize = size;
}
return p;
@@ -419,7 +421,7 @@ char *fd_load(int fd, size_t *size)
Load a file into memory.
****************************************************************************/
-char *file_load(const char *fname, size_t *size)
+char *file_load(const char *fname, size_t *size, size_t maxsize)
{
int fd;
char *p;
@@ -433,12 +435,32 @@ char *file_load(const char *fname, size_t *size)
return NULL;
}
- p = fd_load(fd, size);
+ p = fd_load(fd, size, maxsize);
close(fd);
return p;
}
/*******************************************************************
+ unmap or free memory
+*******************************************************************/
+
+BOOL unmap_file(void* start, size_t size)
+{
+#ifdef HAVE_MMAP
+ if ( munmap( start, size ) != 0 ) {
+ DEBUG( 1, ("map_file: Failed to unmap address %p "
+ "of size %u - %s\n",
+ start, (unsigned int)size, strerror(errno) ));
+ return False;
+ }
+ return True;
+#else
+ SAFE_FREE( start );
+ return True;
+#endif
+}
+
+/*******************************************************************
mmap (if possible) or read a file.
********************************************************************/
@@ -461,7 +483,7 @@ void *map_file(char *fname, size_t size)
}
#endif
if (!p) {
- p = file_load(fname, &s2);
+ p = file_load(fname, &s2, 0);
if (!p) {
return NULL;
}
@@ -522,12 +544,12 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
must be freed with file_lines_free().
****************************************************************************/
-char **file_lines_load(const char *fname, int *numlines)
+char **file_lines_load(const char *fname, int *numlines, size_t maxsize)
{
char *p;
size_t size = 0;
- p = file_load(fname, &size);
+ p = file_load(fname, &size, maxsize);
if (!p) {
return NULL;
}
@@ -541,12 +563,12 @@ char **file_lines_load(const char *fname, int *numlines)
the list.
****************************************************************************/
-char **fd_lines_load(int fd, int *numlines)
+char **fd_lines_load(int fd, int *numlines, size_t maxsize)
{
char *p;
size_t size;
- p = fd_load(fd, &size);
+ p = fd_load(fd, &size, maxsize);
if (!p) {
return NULL;
}
diff --git a/source/lib/util_getent.c b/source/lib/util_getent.c
deleted file mode 100644
index 7c045fccb22..00000000000
--- a/source/lib/util_getent.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Samba utility functions
- Copyright (C) Simo Sorce 2001
- Copyright (C) Jeremy Allison 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"
-
-
-/****************************************************************
- Returns a single linked list of group entries.
- Use grent_free() to free it after use.
-****************************************************************/
-
-struct sys_grent * getgrent_list(void)
-{
- struct sys_grent *glist;
- struct sys_grent *gent;
- struct group *grp;
-
- gent = SMB_MALLOC_P(struct sys_grent);
- if (gent == NULL) {
- DEBUG (0, ("Out of memory in getgrent_list!\n"));
- return NULL;
- }
- memset(gent, '\0', sizeof(struct sys_grent));
- glist = gent;
-
- setgrent();
- grp = getgrent();
- if (grp == NULL) {
- endgrent();
- SAFE_FREE(glist);
- return NULL;
- }
-
- while (grp != NULL) {
- int i,num;
-
- if (grp->gr_name) {
- if ((gent->gr_name = SMB_STRDUP(grp->gr_name)) == NULL)
- goto err;
- }
- if (grp->gr_passwd) {
- if ((gent->gr_passwd = SMB_STRDUP(grp->gr_passwd)) == NULL)
- goto err;
- }
- gent->gr_gid = grp->gr_gid;
-
- /* number of strings in gr_mem */
- for (num = 0; grp->gr_mem[num]; num++)
- ;
-
- /* alloc space for gr_mem string pointers */
- if ((gent->gr_mem = SMB_MALLOC_ARRAY(char *, num+1)) == NULL)
- goto err;
-
- memset(gent->gr_mem, '\0', (num+1) * sizeof(char *));
-
- for (i=0; i < num; i++) {
- if ((gent->gr_mem[i] = SMB_STRDUP(grp->gr_mem[i])) == NULL)
- goto err;
- }
- gent->gr_mem[num] = NULL;
-
- grp = getgrent();
- if (grp) {
- gent->next = SMB_MALLOC_P(struct sys_grent);
- if (gent->next == NULL)
- goto err;
- gent = gent->next;
- memset(gent, '\0', sizeof(struct sys_grent));
- }
- }
-
- endgrent();
- return glist;
-
- err:
-
- endgrent();
- DEBUG(0, ("Out of memory in getgrent_list!\n"));
- grent_free(glist);
- return NULL;
-}
-
-/****************************************************************
- Free the single linked list of group entries made by
- getgrent_list()
-****************************************************************/
-
-void grent_free (struct sys_grent *glist)
-{
- while (glist) {
- struct sys_grent *prev;
-
- SAFE_FREE(glist->gr_name);
- SAFE_FREE(glist->gr_passwd);
- if (glist->gr_mem) {
- int i;
- for (i = 0; glist->gr_mem[i]; i++)
- SAFE_FREE(glist->gr_mem[i]);
- SAFE_FREE(glist->gr_mem);
- }
- prev = glist;
- glist = glist->next;
- SAFE_FREE(prev);
- }
-}
-
-/****************************************************************
- Returns a single linked list of passwd entries.
- Use pwent_free() to free it after use.
-****************************************************************/
-
-struct sys_pwent * getpwent_list(void)
-{
- struct sys_pwent *plist;
- struct sys_pwent *pent;
- struct passwd *pwd;
-
- pent = SMB_MALLOC_P(struct sys_pwent);
- if (pent == NULL) {
- DEBUG (0, ("Out of memory in getpwent_list!\n"));
- return NULL;
- }
- plist = pent;
-
- setpwent();
- pwd = getpwent();
- while (pwd != NULL) {
- memset(pent, '\0', sizeof(struct sys_pwent));
- if (pwd->pw_name) {
- if ((pent->pw_name = SMB_STRDUP(pwd->pw_name)) == NULL)
- goto err;
- }
- if (pwd->pw_passwd) {
- if ((pent->pw_passwd = SMB_STRDUP(pwd->pw_passwd)) == NULL)
- goto err;
- }
- pent->pw_uid = pwd->pw_uid;
- pent->pw_gid = pwd->pw_gid;
- if (pwd->pw_gecos) {
- if ((pent->pw_gecos = SMB_STRDUP(pwd->pw_gecos)) == NULL)
- goto err;
- }
- if (pwd->pw_dir) {
- if ((pent->pw_dir = SMB_STRDUP(pwd->pw_dir)) == NULL)
- goto err;
- }
- if (pwd->pw_shell) {
- if ((pent->pw_shell = SMB_STRDUP(pwd->pw_shell)) == NULL)
- goto err;
- }
-
- pwd = getpwent();
- if (pwd) {
- pent->next = SMB_MALLOC_P(struct sys_pwent);
- if (pent->next == NULL)
- goto err;
- pent = pent->next;
- }
- }
-
- endpwent();
- return plist;
-
- err:
-
- endpwent();
- DEBUG(0, ("Out of memory in getpwent_list!\n"));
- pwent_free(plist);
- return NULL;
-}
-
-/****************************************************************
- Free the single linked list of passwd entries made by
- getpwent_list()
-****************************************************************/
-
-void pwent_free (struct sys_pwent *plist)
-{
- while (plist) {
- struct sys_pwent *prev;
-
- SAFE_FREE(plist->pw_name);
- SAFE_FREE(plist->pw_passwd);
- SAFE_FREE(plist->pw_gecos);
- SAFE_FREE(plist->pw_dir);
- SAFE_FREE(plist->pw_shell);
-
- prev = plist;
- plist = plist->next;
- SAFE_FREE(prev);
- }
-}
-
-/****************************************************************
- Add the individual group users onto the list.
-****************************************************************/
-
-static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_head, const struct group *grp)
-{
- size_t num_users, i;
-
- /* Count the number of users. */
- for (num_users = 0; grp->gr_mem[num_users]; num_users++)
- ;
-
- for (i = 0; i < num_users; i++) {
- struct sys_userlist *entry = SMB_MALLOC_P(struct sys_userlist);
- if (entry == NULL) {
- free_userlist(list_head);
- return NULL;
- }
- entry->unix_name = (char *)SMB_STRDUP(grp->gr_mem[i]);
- if (entry->unix_name == NULL) {
- SAFE_FREE(entry);
- free_userlist(list_head);
- return NULL;
- }
- DLIST_ADD(list_head, entry);
- }
- return list_head;
-}
-
-/*****************************************************************
- Splits passed user or group name to domain and user/group name parts
- Returns True if name was splitted and False otherwise.
-*****************************************************************/
-
-static BOOL split_domain_and_name(const char *name, char *domain,
- char* username)
-{
- char *p = strchr(name,*lp_winbind_separator());
-
-
- /* Parse a string of the form DOMAIN/user into a domain and a user */
- DEBUG(10,("split_domain_and_name: checking whether name |%s| local or "
- "not\n", name));
-
- if (p) {
- fstrcpy(username, p+1);
- fstrcpy(domain, name);
- domain[PTR_DIFF(p, name)] = 0;
- } else if (lp_winbind_use_default_domain()) {
- fstrcpy(username, name);
- fstrcpy(domain, lp_workgroup());
- } else {
- return False;
- }
-
- DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and "
- "name is |%s|\n", domain, username));
- return True;
-}
-
-/****************************************************************
- Get the list of UNIX users in a group.
- We have to enumerate the /etc/group file as some UNIX getgrnam()
- calls won't do that for us (notably Tru64 UNIX).
-****************************************************************/
-
-struct sys_userlist *get_users_in_group(const char *gname)
-{
- struct sys_userlist *list_head = NULL;
- struct group *gptr;
- fstring domain;
- fstring groupname;
- DOM_SID sid;
- enum SID_NAME_USE name_type;
-
- /* No point using winbind if we can't split it in the
- first place */
- if (split_domain_and_name(gname, domain, groupname)) {
-
- /*
- * If we're doing this via winbindd, don't do the
- * entire group list enumeration as we know this is
- * pointless (and slow).
- */
-
- if (winbind_lookup_name(domain, groupname, &sid, &name_type)
- && name_type == SID_NAME_DOM_GRP) {
- if ((gptr = (struct group *)getgrnam(gname)) == NULL)
- return NULL;
- return add_members_to_userlist(list_head, gptr);
- }
- }
-
-#if !defined(BROKEN_GETGRNAM)
- if ((gptr = (struct group *)getgrnam(gname)) == NULL)
- return NULL;
- return add_members_to_userlist(list_head, gptr);
-#else
- /* BROKEN_GETGRNAM - True64 */
- setgrent();
- while((gptr = getgrent()) != NULL) {
- if (strequal(gname, gptr->gr_name)) {
- list_head = add_members_to_userlist(list_head, gptr);
- if (list_head == NULL)
- return NULL;
- }
- }
- endgrent();
- return list_head;
-#endif
-}
-
-/****************************************************************
- Free list allocated above.
-****************************************************************/
-
-void free_userlist(struct sys_userlist *list_head)
-{
- while (list_head) {
- struct sys_userlist *old_head = list_head;
- DLIST_REMOVE(list_head, list_head);
- SAFE_FREE(old_head->unix_name);
- SAFE_FREE(old_head);
- }
-}
diff --git a/source/lib/util_pw.c b/source/lib/util_pw.c
index 13349bad34e..754899f420e 100644
--- a/source/lib/util_pw.c
+++ b/source/lib/util_pw.c
@@ -22,69 +22,47 @@
#include "includes.h"
-static struct passwd *alloc_copy_passwd(const struct passwd *from)
+struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx, const struct passwd *from)
{
- struct passwd *ret = SMB_XMALLOC_P(struct passwd);
- ZERO_STRUCTP(ret);
- ret->pw_name = smb_xstrdup(from->pw_name);
- ret->pw_passwd = smb_xstrdup(from->pw_passwd);
+ struct passwd *ret = TALLOC_P(mem_ctx, struct passwd);
+ if (!ret) {
+ return NULL;
+ }
+ ret->pw_name = talloc_strdup(ret, from->pw_name);
+ ret->pw_passwd = talloc_strdup(ret, from->pw_passwd);
ret->pw_uid = from->pw_uid;
ret->pw_gid = from->pw_gid;
- ret->pw_gecos = smb_xstrdup(from->pw_gecos);
- ret->pw_dir = smb_xstrdup(from->pw_dir);
- ret->pw_shell = smb_xstrdup(from->pw_shell);
+ ret->pw_gecos = talloc_strdup(ret, from->pw_gecos);
+ ret->pw_dir = talloc_strdup(ret, from->pw_dir);
+ ret->pw_shell = talloc_strdup(ret, from->pw_shell);
return ret;
}
-void passwd_free (struct passwd **buf)
-{
- if (!*buf) {
- DEBUG(0, ("attempted double-free of allocated passwd\n"));
- return;
- }
-
- SAFE_FREE((*buf)->pw_name);
- SAFE_FREE((*buf)->pw_passwd);
- SAFE_FREE((*buf)->pw_gecos);
- SAFE_FREE((*buf)->pw_dir);
- SAFE_FREE((*buf)->pw_shell);
-
- SAFE_FREE(*buf);
-}
-
#define PWNAMCACHE_SIZE 4
-static struct passwd *pwnam_cache[PWNAMCACHE_SIZE];
-static BOOL pwnam_cache_initialized = False;
+static struct passwd **pwnam_cache = NULL;
static void init_pwnam_cache(void)
{
- int i;
-
- if (pwnam_cache_initialized)
+ if (pwnam_cache != NULL)
return;
- for (i=0; i<PWNAMCACHE_SIZE; i++)
- pwnam_cache[i] = NULL;
+ pwnam_cache = TALLOC_ZERO_ARRAY(NULL, struct passwd *,
+ PWNAMCACHE_SIZE);
+ if (pwnam_cache == NULL) {
+ smb_panic("Could not init pwnam_cache\n");
+ }
- pwnam_cache_initialized = True;
return;
}
void flush_pwnam_cache(void)
{
- int i;
-
+ TALLOC_FREE(pwnam_cache);
+ pwnam_cache = NULL;
init_pwnam_cache();
-
- for (i=0; i<PWNAMCACHE_SIZE; i++) {
- if (pwnam_cache[i] == NULL)
- continue;
-
- passwd_free(&pwnam_cache[i]);
- }
}
-struct passwd *getpwnam_alloc(const char *name)
+struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name)
{
int i;
@@ -96,7 +74,7 @@ struct passwd *getpwnam_alloc(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 alloc_copy_passwd(pwnam_cache[i]);
+ return talloc_reference(mem_ctx, pwnam_cache[i]);
}
}
@@ -119,15 +97,19 @@ struct passwd *getpwnam_alloc(const char *name)
if (i == PWNAMCACHE_SIZE)
i = rand() % PWNAMCACHE_SIZE;
- if (pwnam_cache[i] != NULL)
- passwd_free(&pwnam_cache[i]);
+ if (pwnam_cache[i] != NULL) {
+ TALLOC_FREE(pwnam_cache[i]);
+ }
- pwnam_cache[i] = alloc_copy_passwd(temp);
+ 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 alloc_copy_passwd(temp);
+ return tcopy_passwd(NULL, pwnam_cache[i]);
}
-struct passwd *getpwuid_alloc(uid_t uid)
+struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid)
{
struct passwd *temp;
@@ -142,5 +124,5 @@ struct passwd *getpwuid_alloc(uid_t uid)
return NULL;
}
- return alloc_copy_passwd(temp);
+ return tcopy_passwd(mem_ctx, temp);
}
diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c
index 0e209e1700d..3be52dd9f79 100644
--- a/source/lib/util_sid.c
+++ b/source/lib/util_sid.c
@@ -75,11 +75,19 @@ const DOM_SID global_sid_Builtin_Backup_Operators = /* Builtin backup operators
const DOM_SID global_sid_Builtin_Replicator = /* Builtin replicator */
{ 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+const DOM_SID global_sid_Unix_Users = /* Unmapped Unix users */
+{ 1, 1, {0,0,0,0,0,22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+const DOM_SID global_sid_Unix_Groups = /* Unmapped Unix groups */
+{ 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+
+/* Unused, left here for documentary purposes */
+#if 0
#define SECURITY_NULL_SID_AUTHORITY 0
#define SECURITY_WORLD_SID_AUTHORITY 1
#define SECURITY_LOCAL_SID_AUTHORITY 2
#define SECURITY_CREATOR_SID_AUTHORITY 3
#define SECURITY_NT_AUTHORITY 5
+#endif
/*
* An NT compatible anonymous token.
@@ -153,59 +161,6 @@ const char *get_global_sam_name(void)
return global_myname();
}
-/**************************************************************************
- Splits a name of format \DOMAIN\name or name into its two components.
- Sets the DOMAIN name to global_myname() if it has not been specified.
-***************************************************************************/
-
-void split_domain_name(const char *fullname, char *domain, char *name)
-{
- pstring full_name;
- const char *sep;
- char *p;
-
- sep = lp_winbind_separator();
-
- *domain = *name = '\0';
-
- if (fullname[0] == sep[0] || fullname[0] == '\\')
- fullname++;
-
- pstrcpy(full_name, fullname);
- p = strchr_m(full_name+1, '\\');
- if (!p) p = strchr_m(full_name+1, sep[0]);
-
- if (p != NULL) {
- *p = 0;
- fstrcpy(domain, full_name);
- fstrcpy(name, p+1);
- } else {
- fstrcpy(domain, get_global_sam_name());
- fstrcpy(name, full_name);
- }
-
- DEBUG(10,("split_domain_name:name '%s' split into domain :'%s' and user :'%s'\n",
- fullname, domain, name));
-}
-
-/****************************************************************************
- Test if a SID is wellknown and resolvable.
-****************************************************************************/
-
-BOOL resolvable_wellknown_sid(DOM_SID *sid)
-{
- uint32 ia = (sid->id_auth[5]) +
- (sid->id_auth[4] << 8 ) +
- (sid->id_auth[3] << 16) +
- (sid->id_auth[2] << 24);
-
- if (sid->sid_rev_num != SEC_DESC_REVISION || sid->num_auths < 1)
- return False;
-
- return (ia == SECURITY_WORLD_SID_AUTHORITY ||
- ia == SECURITY_CREATOR_SID_AUTHORITY);
-}
-
/*****************************************************************
Convert a SID to an ascii string.
*****************************************************************/
@@ -533,30 +488,6 @@ BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
}
/*****************************************************************
- Check if the SID is the builtin SID (S-1-5-32).
-*****************************************************************/
-
-BOOL sid_check_is_builtin(const DOM_SID *sid)
-{
- return sid_equal(sid, &global_sid_Builtin);
-}
-
-/*****************************************************************
- Check if the SID is one of the builtin SIDs (S-1-5-32-a).
-*****************************************************************/
-
-BOOL sid_check_is_in_builtin(const DOM_SID *sid)
-{
- DOM_SID dom_sid;
- uint32 rid;
-
- sid_copy(&dom_sid, sid);
- sid_split_rid(&dom_sid, &rid);
-
- return sid_equal(&dom_sid, &global_sid_Builtin);
-}
-
-/*****************************************************************
Calculates size of a sid.
*****************************************************************/
@@ -632,14 +563,16 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src)
void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
DOM_SID **sids, size_t *num)
{
- if (mem_ctx != NULL)
+ if (mem_ctx != NULL) {
*sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID,
(*num)+1);
- else
+ } else {
*sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1);
+ }
- if (*sids == NULL)
+ if (*sids == NULL) {
return;
+ }
sid_copy(&((*sids)[*num]), sid);
*num += 1;
diff --git a/source/lib/util_smbd.c b/source/lib/util_smbd.c
deleted file mode 100644
index c6f6bc0a32a..00000000000
--- a/source/lib/util_smbd.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Samba utility functions, used in smbd only
- Copyright (C) Andrew Tridgell 2002
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-/*
- This function requires sys_getgrouplist - which is only
- available in smbd due to it's use of become_root() in a
- legacy systems hack.
-*/
-
-/*
- return a full list of groups for a user
-
- returns the number of groups the user is a member of. The return will include the
- users primary group.
-
- remember to free the resulting gid_t array
-
- NOTE! uses become_root() to gain correct priviages on systems
- that lack a native getgroups() call (uses initgroups and getgroups)
-*/
-BOOL getgroups_user(const char *user, gid_t primary_gid, gid_t **ret_groups, int *ngroups)
-{
- int ngrp, max_grp;
- gid_t *temp_groups;
- gid_t *groups;
- int i;
-
- max_grp = groups_max();
- temp_groups = SMB_MALLOC_ARRAY(gid_t, max_grp);
- if (! temp_groups) {
- return False;
- }
-
- if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
-
- gid_t *groups_tmp;
-
- groups_tmp = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp);
-
- if (!groups_tmp) {
- SAFE_FREE(temp_groups);
- return False;
- }
- temp_groups = groups_tmp;
-
- if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
- DEBUG(0, ("get_user_groups: failed to get the unix group list\n"));
- SAFE_FREE(temp_groups);
- return False;
- }
- }
-
- ngrp = 0;
- groups = NULL;
-
- /* Add in primary group first */
- add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp);
-
- for (i=0; i<max_grp; i++)
- add_gid_to_array_unique(NULL, temp_groups[i], &groups, &ngrp);
-
- *ngroups = ngrp;
- *ret_groups = groups;
- SAFE_FREE(temp_groups);
- return True;
-}
-
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 91c3305996e..12fc2ead95c 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -662,8 +662,6 @@ BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
smb_read_error = 0;
- memset(buffer,'\0',smb_size + 100);
-
len = read_smb_length_return_keepalive(fd,buffer,timeout);
if (len < 0) {
DEBUG(10,("receive_smb_raw: length < 0!\n"));
@@ -708,8 +706,9 @@ BOOL receive_smb_raw(int fd, char *buffer, unsigned int timeout)
}
if (ret != len) {
- if (smb_read_error == 0)
+ if (smb_read_error == 0) {
smb_read_error = READ_ERROR;
+ }
return False;
}
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 07626a3feca..439cbea6d93 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -853,7 +853,7 @@ BOOL in_list(const char *s, const char *list, BOOL casesensitive)
}
/* this is used to prevent lots of mallocs of size 1 */
-static char *null_string = NULL;
+static const char *null_string = "";
/**
Set a string value, allocing the space for the string
@@ -862,20 +862,14 @@ static char *null_string = NULL;
static BOOL string_init(char **dest,const char *src)
{
size_t l;
+
if (!src)
src = "";
l = strlen(src);
if (l == 0) {
- if (!null_string) {
- if((null_string = (char *)SMB_MALLOC(1)) == NULL) {
- DEBUG(0,("string_init: malloc fail for null_string.\n"));
- return False;
- }
- *null_string = 0;
- }
- *dest = null_string;
+ *dest = CONST_DISCARD(char*, null_string);
} else {
(*dest) = SMB_STRDUP(src);
if ((*dest) == NULL) {
@@ -923,7 +917,7 @@ BOOL string_set(char **dest,const char *src)
**/
void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
- BOOL remove_unsafe_characters, BOOL replace_once)
+ BOOL remove_unsafe_characters, BOOL replace_once, BOOL allow_trailing_dollar)
{
char *p;
ssize_t ls,lp,li, i;
@@ -955,6 +949,11 @@ void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
case '\'':
case ';':
case '$':
+ /* allow a trailing $ (as in machine accounts) */
+ if (allow_trailing_dollar && (i == li - 1 )) {
+ p[i] = insert[i];
+ break;
+ }
case '%':
case '\r':
case '\n':
@@ -978,12 +977,12 @@ void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
void string_sub_once(char *s, const char *pattern, const char *insert, size_t len)
{
- string_sub2( s, pattern, insert, len, True, True );
+ string_sub2( s, pattern, insert, len, True, True, False );
}
void string_sub(char *s,const char *pattern, const char *insert, size_t len)
{
- string_sub2( s, pattern, insert, len, True, False );
+ string_sub2( s, pattern, insert, len, True, False, False );
}
void fstring_sub(char *s,const char *pattern,const char *insert)
@@ -1044,14 +1043,13 @@ char *realloc_string_sub(char *string, const char *pattern,
while ((p = strstr_m(s,pattern))) {
if (ld > 0) {
int offset = PTR_DIFF(s,string);
- char *t = SMB_REALLOC(string, ls + ld + 1);
- if (!t) {
+ string = SMB_REALLOC(string, ls + ld + 1);
+ if (!string) {
DEBUG(0, ("realloc_string_sub: out of memory!\n"));
SAFE_FREE(in);
return NULL;
}
- string = t;
- p = t + offset + (p - s);
+ p = string + offset + (p - s);
}
if (li != lp) {
memmove(p+li,p+lp,strlen(p+lp)+1);
@@ -1114,15 +1112,14 @@ 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);
- char *t = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1);
- if (!t) {
+ string = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1);
+ if (!string) {
DEBUG(0, ("talloc_string_sub: out of "
"memory!\n"));
SAFE_FREE(in);
return NULL;
}
- string = t;
- p = t + offset + (p - s);
+ p = string + offset + (p - s);
}
if (li != lp) {
memmove(p+li,p+lp,strlen(p+lp)+1);
@@ -1667,7 +1664,7 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
#define S_LIST_ABS 16 /* List Allocation Block Size */
-char **str_list_make(const char *string, const char *sep)
+static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
{
char **list, **rlist;
const char *str;
@@ -1677,7 +1674,11 @@ char **str_list_make(const char *string, const char *sep)
if (!string || !*string)
return NULL;
- s = SMB_STRDUP(string);
+ if (mem_ctx) {
+ s = talloc_strdup(mem_ctx, string);
+ } else {
+ s = SMB_STRDUP(string);
+ }
if (!s) {
DEBUG(0,("str_list_make: Unable to allocate memory"));
return NULL;
@@ -1691,32 +1692,67 @@ char **str_list_make(const char *string, const char *sep)
while (next_token(&str, tok, sep, sizeof(tok))) {
if (num == lsize) {
lsize += S_LIST_ABS;
- rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1);
+ if (mem_ctx) {
+ rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1);
+ } else {
+ /* We need to keep the old list on error so we can free the elements
+ if the realloc fails. */
+ rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
+ }
if (!rlist) {
DEBUG(0,("str_list_make: Unable to allocate memory"));
str_list_free(&list);
- SAFE_FREE(s);
+ if (mem_ctx) {
+ TALLOC_FREE(s);
+ } else {
+ SAFE_FREE(s);
+ }
return NULL;
- } else
+ } else {
list = rlist;
+ }
memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
}
+
+ if (mem_ctx) {
+ list[num] = talloc_strdup(mem_ctx, tok);
+ } else {
+ list[num] = SMB_STRDUP(tok);
+ }
- list[num] = SMB_STRDUP(tok);
if (!list[num]) {
DEBUG(0,("str_list_make: Unable to allocate memory"));
str_list_free(&list);
- SAFE_FREE(s);
+ if (mem_ctx) {
+ TALLOC_FREE(s);
+ } else {
+ SAFE_FREE(s);
+ }
return NULL;
}
num++;
}
-
- SAFE_FREE(s);
+
+ if (mem_ctx) {
+ TALLOC_FREE(s);
+ } else {
+ SAFE_FREE(s);
+ }
+
return list;
}
+char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
+{
+ return str_list_make_internal(mem_ctx, string, sep);
+}
+
+char **str_list_make(const char *string, const char *sep)
+{
+ return str_list_make_internal(NULL, string, sep);
+}
+
BOOL str_list_copy(char ***dest, const char **src)
{
char **list, **rlist;
@@ -1732,13 +1768,14 @@ BOOL str_list_copy(char ***dest, const char **src)
while (src[num]) {
if (num == lsize) {
lsize += S_LIST_ABS;
- rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1);
+ rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
if (!rlist) {
DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
str_list_free(&list);
return False;
- } else
+ } else {
list = rlist;
+ }
memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
}
@@ -1778,16 +1815,35 @@ BOOL str_list_compare(char **list1, char **list2)
return True;
}
-void str_list_free(char ***list)
+static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
{
char **tlist;
if (!list || !*list)
return;
tlist = *list;
- for(; *tlist; tlist++)
- SAFE_FREE(*tlist);
- SAFE_FREE(*list);
+ for(; *tlist; tlist++) {
+ if (mem_ctx) {
+ TALLOC_FREE(*tlist);
+ } else {
+ SAFE_FREE(*tlist);
+ }
+ }
+ if (mem_ctx) {
+ TALLOC_FREE(*tlist);
+ } else {
+ SAFE_FREE(*list);
+ }
+}
+
+void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
+{
+ str_list_free_internal(mem_ctx, list);
+}
+
+void str_list_free(char ***list)
+{
+ str_list_free_internal(NULL, list);
}
/******************************************************************************
@@ -2206,8 +2262,9 @@ void string_append(char **left, const char *right)
*left = SMB_REALLOC(*left, new_len);
}
- if (*left == NULL)
+ if (*left == NULL) {
return;
+ }
safe_strcat(*left, right, new_len-1);
}
@@ -2274,14 +2331,16 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
}
if (increased) {
- if (mem_ctx != NULL)
+ if (mem_ctx != NULL) {
*string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
*bufsize);
- else
+ } else {
*string = SMB_REALLOC_ARRAY(*string, char, *bufsize);
+ }
- if (*string == NULL)
+ if (*string == NULL) {
goto error;
+ }
}
StrnCpy((*string)+(*len), newstr, ret);
@@ -2320,3 +2379,23 @@ char *sstring_sub(const char *src, char front, char back)
temp3[len-1] = '\0';
return temp3;
}
+
+/********************************************************************
+ Check a string for any occurrences of a specified list of invalid
+ characters.
+********************************************************************/
+
+BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
+{
+ int i;
+
+ for ( i=0; i<max_len && name[i]; i++ ) {
+ /* fail if strchr_m() finds one of the invalid characters */
+ if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
+ return False;
+ }
+ }
+
+ return True;
+}
+
diff --git a/source/lib/util_unistr.c b/source/lib/util_unistr.c
index b979745d366..eef484148db 100644
--- a/source/lib/util_unistr.c
+++ b/source/lib/util_unistr.c
@@ -31,6 +31,9 @@
static smb_ucs2_t *upcase_table;
static smb_ucs2_t *lowcase_table;
static uint8 *valid_table;
+static BOOL upcase_table_use_unmap;
+static BOOL lowcase_table_use_unmap;
+static BOOL valid_table_use_unmap;
/**
* This table says which Unicode characters are valid dos
@@ -40,6 +43,32 @@ static uint8 *valid_table;
**/
static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */
+/**
+ * Destroy global objects allocated by load_case_tables()
+ **/
+void gfree_case_tables(void)
+{
+ if ( upcase_table ) {
+ if ( upcase_table_use_unmap )
+ unmap_file(upcase_table, 0x20000);
+ else
+ SAFE_FREE(upcase_table);
+ }
+
+ if ( lowcase_table ) {
+ if ( lowcase_table_use_unmap )
+ unmap_file(lowcase_table, 0x20000);
+ else
+ SAFE_FREE(lowcase_table);
+ }
+
+ if ( valid_table ) {
+ if ( valid_table_use_unmap )
+ unmap_file(valid_table, 0x10000);
+ else
+ SAFE_FREE(valid_table);
+ }
+}
/**
* Load or generate the case handling tables.
@@ -51,6 +80,7 @@ static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */
void load_case_tables(void)
{
static int initialised;
+ char *old_locale = NULL, *saved_locale = NULL;
int i;
if (initialised) {
@@ -59,7 +89,21 @@ void load_case_tables(void)
initialised = 1;
upcase_table = 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_use_unmap = ( lowcase_table != NULL );
+
+#ifdef HAVE_SETLOCALE
+ /* Get the name of the current locale. */
+ old_locale = setlocale(LC_ALL, NULL);
+
+ /* Save it as it is in static storage. */
+ saved_locale = SMB_STRDUP(old_locale);
+
+ /* We set back the locale to C to get ASCII-compatible toupper/lower functions. */
+ setlocale(LC_ALL, "C");
+#endif
/* we would like Samba to limp along even if these tables are
not available */
@@ -92,6 +136,12 @@ void load_case_tables(void)
lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i);
}
}
+
+#ifdef HAVE_SETLOCALE
+ /* Restore the old locale. */
+ setlocale (LC_ALL, saved_locale);
+ SAFE_FREE(saved_locale);
+#endif
}
/*
@@ -178,6 +228,7 @@ void init_valid_table(void)
if (valid_file) {
valid_table = valid_file;
mapped_file = 1;
+ valid_table_use_unmap = True;
return;
}
@@ -185,7 +236,11 @@ void init_valid_table(void)
* It might need to be regenerated if the code page changed.
* We know that we're not using a mapped file, so we can
* free() the old one. */
- if (valid_table) free(valid_table);
+ if (valid_table)
+ SAFE_FREE(valid_table);
+
+ /* use free rather than unmap */
+ valid_table_use_unmap = False;
DEBUG(2,("creating default valid table\n"));
valid_table = SMB_MALLOC(0x10000);
@@ -211,7 +266,7 @@ void init_valid_table(void)
null termination if applied
********************************************************************/
-size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
+size_t dos_PutUniCode(char *dst,const char *src, size_t len, BOOL null_terminate)
{
int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
: STR_UNICODE|STR_NOALIGN;
@@ -273,30 +328,24 @@ int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
* have been to manually talloc_strdup them in rpc_client/cli_netlogon.c.
*/
-size_t rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, char **dest,
- UNISTR2 *src)
+char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, const UNISTR2 *src)
{
pstring tmp;
size_t result;
result = pull_ucs2(NULL, tmp, src->buffer, sizeof(tmp),
src->uni_str_len * 2, 0);
- if (result < 0) {
- return result;
- }
-
- *dest = talloc_strdup(mem_ctx, tmp);
- if (*dest == NULL) {
- return -1;
+ if (result == (size_t)-1) {
+ return NULL;
}
- return result;
+ return talloc_strdup(mem_ctx, tmp);
}
/* Converts a string from internal samba format to unicode
*/
-int rpcstr_push(void* dest, const char *src, int dest_len, int flags)
+int rpcstr_push(void* dest, const char *src, size_t dest_len, int flags)
{
return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
}
@@ -997,3 +1046,41 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src)
return dst;
}
+
+/*************************************************************
+ ascii only toupper - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int toupper_ascii(int c)
+{
+ smb_ucs2_t uc = toupper_w(UCS2_CHAR(c));
+ return UCS2_TO_CHAR(uc);
+}
+
+/*************************************************************
+ ascii only tolower - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int tolower_ascii(int c)
+{
+ smb_ucs2_t uc = tolower_w(UCS2_CHAR(c));
+ return UCS2_TO_CHAR(uc);
+}
+
+/*************************************************************
+ ascii only isupper - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int isupper_ascii(int c)
+{
+ return isupper_w(UCS2_CHAR(c));
+}
+
+/*************************************************************
+ ascii only islower - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int islower_ascii(int c)
+{
+ return islower_w(UCS2_CHAR(c));
+}
diff --git a/source/lib/wins_srv.c b/source/lib/wins_srv.c
index c139f427ca8..dbe4fceaccc 100644
--- a/source/lib/wins_srv.c
+++ b/source/lib/wins_srv.c
@@ -245,6 +245,9 @@ char **wins_srv_tags(void)
/* add it to the list */
ret = SMB_REALLOC_ARRAY(ret, char *, count+2);
+ if (!ret) {
+ return NULL;
+ }
ret[count] = SMB_STRDUP(t_ip.tag);
if (!ret[count]) break;
count++;
diff --git a/source/lib/xfile.c b/source/lib/xfile.c
index 5bb93179af3..71f8bdbcbb6 100644
--- a/source/lib/xfile.c
+++ b/source/lib/xfile.c
@@ -96,13 +96,16 @@ XFILE *x_fopen(const char *fname, int flags, mode_t mode)
XFILE *ret;
ret = SMB_MALLOC_P(XFILE);
- if (!ret) return NULL;
+ if (!ret) {
+ return NULL;
+ }
memset(ret, 0, sizeof(XFILE));
if ((flags & O_ACCMODE) == O_RDWR) {
/* we don't support RDWR in XFILE - use file
descriptors instead */
+ SAFE_FREE(ret);
errno = EINVAL;
return NULL;
}
diff --git a/source/libads/ads_ldap.c b/source/libads/ads_ldap.c
index fea4cd0fd09..42821496c34 100644
--- a/source/libads/ads_ldap.c
+++ b/source/libads/ads_ldap.c
@@ -83,7 +83,6 @@ ADS_STATUS ads_sid_to_dn(ADS_STRUCT *ads,
*dn = talloc_strdup(mem_ctx, dn2);
if (!*dn) {
- ads_memfree(ads, dn2);
rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
goto done;
}
diff --git a/source/libads/ads_utils.c b/source/libads/ads_utils.c
index 1aad0bed547..0cbf235989e 100644
--- a/source/libads/ads_utils.c
+++ b/source/libads/ads_utils.c
@@ -25,21 +25,28 @@
/*
translated the ACB_CTRL Flags to UserFlags (userAccountControl)
*/
-uint32 ads_acb2uf(uint16 acb)
+uint32 ads_acb2uf(uint32 acb)
{
uint32 uf = 0x00000000;
- if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE;
- if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED;
- if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD;
- if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT;
- if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT;
- if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT;
- if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT;
- if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT;
- if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT;
- if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD;
- if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT;
+ if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE;
+ if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED;
+ if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD;
+ if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT;
+ if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT;
+ if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT;
+ if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT;
+ if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT;
+ if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT;
+ if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD;
+ if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT;
+ if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY;
+ if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED;
+ if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION;
+ if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH;
+ if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED;
+ if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED;
+ if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED;
return uf;
}
@@ -47,9 +54,9 @@ uint32 ads_acb2uf(uint16 acb)
/*
translated the UserFlags (userAccountControl) to ACB_CTRL Flags
*/
-uint16 ads_uf2acb(uint32 uf)
+uint32 ads_uf2acb(uint32 uf)
{
- uint16 acb = 0x0000;
+ uint32 acb = 0x00000000;
if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED;
if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ;
@@ -57,6 +64,13 @@ uint16 ads_uf2acb(uint32 uf)
if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS;
if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP;
if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK;
+ if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY;
+ if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED;
+ if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION;
+ if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH;
+ if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD;
+ if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED;
+ if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED;
switch (uf & UF_ACCOUNT_TYPE_MASK)
{
diff --git a/source/libads/gpo.c b/source/libads/gpo.c
new file mode 100644
index 00000000000..9cf7aae9770
--- /dev/null
+++ b/source/libads/gpo.c
@@ -0,0 +1,680 @@
+/*
+ * 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"
+
+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;
+ int i;
+
+ DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
+
+ ext_list = str_list_make_talloc(mem_ctx, extension_raw, "]");
+ if (ext_list == NULL) {
+ goto parse_error;
+ }
+
+ for (i = 0; ext_list[i] != NULL; i++) {
+ /* no op */
+ }
+
+ gp_ext->num_exts = i;
+
+ gp_ext->extensions = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+ gp_ext->extensions_guid = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+ gp_ext->snapins = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+ gp_ext->snapins_guid = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+
+ gp_ext->gp_extension = talloc_strdup(mem_ctx, extension_raw);
+
+ if (gp_ext->extensions == NULL || gp_ext->extensions_guid == NULL ||
+ gp_ext->snapins == NULL || gp_ext->snapins_guid == NULL ||
+ gp_ext->gp_extension == NULL) {
+ goto parse_error;
+ }
+
+ for (i = 0; ext_list[i] != NULL; i++) {
+
+ int k;
+ char *p, *q;
+
+ DEBUGADD(10,("extension #%d\n", i));
+
+ p = ext_list[i];
+
+ if (p[0] == '[') {
+ p++;
+ }
+
+ ext_strings = str_list_make_talloc(mem_ctx, p, "}");
+ if (ext_strings == NULL) {
+ goto parse_error;
+ }
+
+ for (k = 0; ext_strings[k] != NULL; k++) {
+ /* no op */
+ }
+
+ q = ext_strings[0];
+
+ if (q[0] == '{') {
+ q++;
+ }
+
+ gp_ext->extensions[i] = talloc_strdup(mem_ctx, cse_gpo_guid_string_to_name(q));
+ gp_ext->extensions_guid[i] = talloc_strdup(mem_ctx, q);
+
+ /* we might have no name for the guid */
+ if (gp_ext->extensions_guid[i] == NULL) {
+ goto parse_error;
+ }
+
+ for (k = 1; ext_strings[k] != NULL; k++) {
+
+ char *m = ext_strings[k];
+
+ if (m[0] == '{') {
+ m++;
+ }
+
+ /* FIXME: theoretically there could be more than one snapin per extension */
+ gp_ext->snapins[i] = talloc_strdup(mem_ctx, cse_snapin_gpo_guid_string_to_name(m));
+ gp_ext->snapins_guid[i] = talloc_strdup(mem_ctx, m);
+
+ /* we might have no name for the guid */
+ if (gp_ext->snapins_guid[i] == NULL) {
+ goto parse_error;
+ }
+ }
+ }
+
+ if (ext_list) {
+ str_list_free_talloc(mem_ctx, &ext_list);
+ }
+ if (ext_strings) {
+ str_list_free_talloc(mem_ctx, &ext_strings);
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+
+parse_error:
+ if (ext_list) {
+ str_list_free_talloc(mem_ctx, &ext_list);
+ }
+ if (ext_strings) {
+ str_list_free_talloc(mem_ctx, &ext_strings);
+ }
+
+ return ADS_ERROR(LDAP_NO_MEMORY);
+}
+
+ADS_STATUS ads_parse_gplink(TALLOC_CTX *mem_ctx,
+ const char *gp_link_raw,
+ uint32 options,
+ struct GP_LINK *gp_link)
+{
+ char **link_list;
+ int i;
+
+ DEBUG(10,("ads_parse_gplink: gPLink: %s\n", gp_link_raw));
+
+ link_list = str_list_make_talloc(mem_ctx, gp_link_raw, "]");
+ if (link_list == NULL) {
+ goto parse_error;
+ }
+
+ for (i = 0; link_list[i] != NULL; i++) {
+ /* no op */
+ }
+
+ gp_link->gp_opts = options;
+ gp_link->num_links = i;
+
+ gp_link->link_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_link->num_links);
+ gp_link->link_opts = TALLOC_ZERO_ARRAY(mem_ctx, uint32, gp_link->num_links);
+
+ gp_link->gp_link = talloc_strdup(mem_ctx, gp_link_raw);
+
+ if (gp_link->link_names == NULL || gp_link->link_opts == NULL || gp_link->gp_link == NULL) {
+ goto parse_error;
+ }
+
+ for (i = 0; link_list[i] != NULL; i++) {
+
+ char *p, *q;
+
+ DEBUGADD(10,("ads_parse_gplink: processing link #%d\n", i));
+
+ q = link_list[i];
+ if (q[0] == '[') {
+ q++;
+ };
+
+ p = strchr(q, ';');
+
+ if (p == NULL) {
+ goto parse_error;
+ }
+
+ gp_link->link_names[i] = talloc_strdup(mem_ctx, q);
+ if (gp_link->link_names[i] == NULL) {
+ goto parse_error;
+ }
+ gp_link->link_names[i][PTR_DIFF(p, q)] = 0;
+
+ gp_link->link_opts[i] = atoi(p + 1);
+
+ DEBUGADD(10,("ads_parse_gplink: link: %s\n", gp_link->link_names[i]));
+ DEBUGADD(10,("ads_parse_gplink: opt: %d\n", gp_link->link_opts[i]));
+
+ }
+
+ if (link_list) {
+ str_list_free_talloc(mem_ctx, &link_list);
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+
+parse_error:
+ if (link_list) {
+ str_list_free_talloc(mem_ctx, &link_list);
+ }
+
+ return ADS_ERROR(LDAP_NO_MEMORY);
+}
+
+ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *link_dn,
+ struct GP_LINK *gp_link_struct)
+{
+ ADS_STATUS status;
+ const char *attrs[] = {"gPLink", "gPOptions", NULL};
+ void *res = NULL;
+ const char *gp_link;
+ uint32 gp_options;
+
+ ZERO_STRUCTP(gp_link_struct);
+
+ status = ads_search_dn(ads, &res, link_dn, attrs);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(10,("ads_get_gpo_link: search failed with %s\n", ads_errstr(status)));
+ return status;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ DEBUG(10,("ads_get_gpo_link: no result\n"));
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
+ if (gp_link == NULL) {
+ DEBUG(10,("ads_get_gpo_link: no 'gPLink' attribute found\n"));
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
+ }
+
+ if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
+ DEBUG(10,("ads_get_gpo_link: no 'gPOptions' attribute found\n"));
+ gp_options = 0;
+ }
+
+ ads_msgfree(ads, res);
+
+ return ads_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct);
+}
+
+ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *link_dn,
+ const char *gpo_dn,
+ uint32 gpo_opt)
+{
+ ADS_STATUS status;
+ const char *attrs[] = {"gPLink", NULL};
+ void *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 */
+
+ if (!strnequal(gpo_dn, "LDAP://CN={", strlen("LDAP://CN={")) != 0) {
+ return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
+ }
+
+ status = ads_search_dn(ads, &res, link_dn, attrs);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(10,("ads_add_gpo_link: search failed with %s\n", ads_errstr(status)));
+ return status;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ DEBUG(10,("ads_add_gpo_link: no result\n"));
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
+ if (gp_link == NULL) {
+ gp_link_new = talloc_asprintf(mem_ctx, "[%s;%d]", gpo_dn, gpo_opt);
+ } else {
+ 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);
+ }
+
+ mods = ads_init_mods(mem_ctx);
+ if (mods == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ return ads_gen_mod(ads, link_dn, mods);
+}
+
+/* untested & broken */
+ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *link_dn,
+ const char *gpo_dn)
+{
+ ADS_STATUS status;
+ const char *attrs[] = {"gPLink", NULL};
+ void *res = NULL;
+ const char *gp_link, *gp_link_new = NULL;
+ ADS_MODLIST mods;
+
+ /* check for a sane gpo_dn */
+ if (gpo_dn[0] != '[') {
+ DEBUG(10,("ads_delete_gpo_link: first char not: [\n"));
+ return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
+ }
+
+ if (gpo_dn[strlen(gpo_dn)] != ']') {
+ DEBUG(10,("ads_delete_gpo_link: last char not: ]\n"));
+ return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
+ }
+
+ status = ads_search_dn(ads, &res, link_dn, attrs);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(10,("ads_delete_gpo_link: search failed with %s\n", ads_errstr(status)));
+ return status;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ DEBUG(10,("ads_delete_gpo_link: no result\n"));
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink");
+ if (gp_link == NULL) {
+ return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
+ }
+
+ /* find link to delete */
+// 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);
+ }
+
+ mods = ads_init_mods(mem_ctx);
+ if (mods == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ 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)
+{
+ ZERO_STRUCTP(gpo);
+
+ if (res == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ gpo->name = ads_pull_string(ads, mem_ctx, res, "name");
+ if (gpo->name == NULL) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* ???, 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);
+}
+
+ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *gpo_dn,
+ const char *display_name,
+ const char *guid_name,
+ struct GROUP_POLICY_OBJECT *gpo)
+{
+ ADS_STATUS status;
+ void *res = NULL;
+ char *dn;
+ const char *filter;
+ const char *attrs[] = { "cn", "displayName", "flags", "gPCFileSysPath",
+ "gPCFunctionalityVersion", "gPCMachineExtensionNames",
+ "gPCUserExtensionNames", "gPCWQLFilter", "name",
+ "versionNumber", NULL};
+
+ ZERO_STRUCTP(gpo);
+
+ if (!gpo_dn && !display_name && !guid_name) {
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ if (gpo_dn) {
+
+ if (strnequal(gpo_dn, "LDAP://", strlen("LDAP://")) != 0) {
+ gpo_dn = gpo_dn + strlen("LDAP://");
+ }
+
+ status = ads_search_dn(ads, &res, gpo_dn, attrs);
+
+ } else if (display_name || guid_name) {
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectclass=groupPolicyContainer)(%s=%s))",
+ display_name ? "displayName" : "name",
+ display_name ? display_name : guid_name);
+ if (filter == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_do_search_all(ads, ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE, filter,
+ attrs, &res);
+ }
+
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(10,("ads_get_gpo: search failed with %s\n", ads_errstr(status)));
+ return status;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ DEBUG(10,("ads_get_gpo: no result\n"));
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ dn = ads_get_dn(ads, res);
+ if (dn == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
+
+ ads_memfree(ads, dn);
+
+ return status;
+}
+
+ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT **gpo_list,
+ const char *link_dn,
+ struct GP_LINK *gp_link,
+ enum GPO_LINK_TYPE link_type,
+ BOOL only_add_forced_gpos)
+{
+ ADS_STATUS status;
+ int i;
+
+ for (i = 0; i < gp_link->num_links; i++) {
+
+ struct GROUP_POLICY_OBJECT *new_gpo = NULL;
+
+ if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
+ DEBUG(10,("skipping disabled GPO\n"));
+ continue;
+ }
+
+ if (only_add_forced_gpos) {
+
+ if (! (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED)) {
+ DEBUG(10,("skipping nonenforced GPO link because GPOPTIONS_BLOCK_INHERITANCE has been set\n"));
+ continue;
+ } else {
+ DEBUG(10,("adding enforced GPO link although the GPOPTIONS_BLOCK_INHERITANCE has been set\n"));
+ }
+ }
+
+ new_gpo = TALLOC_P(mem_ctx, struct GROUP_POLICY_OBJECT);
+ if (new_gpo == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ ZERO_STRUCTP(new_gpo);
+
+ status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, new_gpo);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ new_gpo->link = link_dn;
+ new_gpo->link_type = link_type;
+
+ DLIST_ADD(*gpo_list, new_gpo);
+
+ DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s to GPO list\n",
+ i, gp_link->link_names[i]));
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *dn,
+ uint32 flags,
+ struct GROUP_POLICY_OBJECT **gpo_list)
+{
+ /* (L)ocal (S)ite (D)omain (O)rganizational(U)nit */
+
+ ADS_STATUS status;
+ struct GP_LINK gp_link;
+ const char *parent_dn, *site_dn, *tmp_dn;
+ BOOL add_only_forced_gpos = False;
+
+ ZERO_STRUCTP(gpo_list);
+
+ DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn));
+
+ /* (L)ocal */
+ /* not yet... */
+
+ /* (S)ite */
+
+ /* are site GPOs valid for users as well ??? */
+ if (flags & GPO_LIST_FLAG_MACHINE) {
+
+ status = ads_site_dn_for_machine(ads, mem_ctx, ads->config.ldap_server_name, &site_dn);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n", site_dn));
+
+ status = ads_get_gpo_link(ads, mem_ctx, site_dn, &gp_link);
+ if (ADS_ERR_OK(status)) {
+
+ if (DEBUGLEVEL >= 100) {
+ dump_gplink(ads, mem_ctx, &gp_link);
+ }
+
+ status = add_gplink_to_gpo_list(ads, mem_ctx, gpo_list,
+ site_dn, &gp_link, GP_LINK_SITE,
+ add_only_forced_gpos);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ if (flags & GPO_LIST_FLAG_SITEONLY) {
+ return ADS_ERROR(LDAP_SUCCESS);
+ }
+
+ /* inheritance can't be blocked at the site level */
+ }
+ }
+
+ tmp_dn = dn;
+
+ while ( (parent_dn = ads_parent_dn(tmp_dn)) &&
+ (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path))) ) {
+
+ /* (D)omain */
+
+ /* An account can just be a member of one domain */
+ if (strncmp(parent_dn, "DC=", strlen("DC=")) == 0) {
+
+ DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n", parent_dn));
+
+ status = ads_get_gpo_link(ads, mem_ctx, parent_dn, &gp_link);
+ if (ADS_ERR_OK(status)) {
+
+ if (DEBUGLEVEL >= 100) {
+ dump_gplink(ads, mem_ctx, &gp_link);
+ }
+
+ /* block inheritance from now on */
+ if (gp_link.gp_opts & GPOPTIONS_BLOCK_INHERITANCE) {
+ add_only_forced_gpos = True;
+ }
+
+ status = add_gplink_to_gpo_list(ads, mem_ctx,
+ gpo_list, parent_dn,
+ &gp_link, GP_LINK_DOMAIN,
+ add_only_forced_gpos);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+ }
+ }
+
+ tmp_dn = parent_dn;
+ }
+
+ /* reset dn again */
+ tmp_dn = dn;
+
+ while ( (parent_dn = ads_parent_dn(tmp_dn)) &&
+ (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path))) ) {
+
+
+ /* (O)rganizational(U)nit */
+
+ /* An account can be a member of more OUs */
+ if (strncmp(parent_dn, "OU=", strlen("OU=")) == 0) {
+
+ DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n", parent_dn));
+
+ status = ads_get_gpo_link(ads, mem_ctx, parent_dn, &gp_link);
+ if (ADS_ERR_OK(status)) {
+
+ if (DEBUGLEVEL >= 100) {
+ dump_gplink(ads, mem_ctx, &gp_link);
+ }
+
+ /* block inheritance from now on */
+ if (gp_link.gp_opts & GPOPTIONS_BLOCK_INHERITANCE) {
+ add_only_forced_gpos = True;
+ }
+
+ status = add_gplink_to_gpo_list(ads, mem_ctx,
+ gpo_list, parent_dn,
+ &gp_link, GP_LINK_OU,
+ add_only_forced_gpos);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+ }
+ }
+
+ tmp_dn = parent_dn;
+
+ };
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
diff --git a/source/libads/gpo_util.c b/source/libads/gpo_util.c
new file mode 100644
index 00000000000..8f913c19714
--- /dev/null
+++ b/source/libads/gpo_util.c
@@ -0,0 +1,496 @@
+/*
+ * 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 DEFAULT_DOMAIN_POLICY "Default Domain Policy"
+#define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
+
+/* should we store a parsed guid ? UUID_FLAT guid; */
+struct gpo_table {
+ const char *name;
+ const char *guid_string;
+};
+
+struct snapin_table {
+ const char *name;
+ const char *guid_string;
+ ADS_STATUS (*snapin_fn)(ADS_STRUCT *, TALLOC_CTX *mem_ctx, const char *, const char *);
+};
+
+static struct gpo_table gpo_default_policy[] = {
+ { DEFAULT_DOMAIN_POLICY,
+ "31B2F340-016D-11D2-945F-00C04FB984F9" },
+ { DEFAULT_DOMAIN_CONTROLLERS_POLICY,
+ "6AC1786C-016F-11D2-945F-00C04fB984F9" },
+ { NULL, NULL }
+};
+
+
+/* the following is seen in gPCMachineExtensionNames or gPCUserExtensionNames */
+
+static struct gpo_table gpo_cse_extensions[] = {
+ { "Administrative Templates Extension",
+ "35378EAC-683F-11D2-A89A-00C04FBBCFA2" }, /* Registry Policy ? */
+ { "Microsoft Disc Quota",
+ "3610EDA5-77EF-11D2-8DC5-00C04FA31A66" },
+ { "EFS recovery",
+ "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A" },
+ { "Folder Redirection",
+ "25537BA6-77A8-11D2-9B6C-0000F8080861" },
+ { "IP Security",
+ "E437BC1C-AA7D-11D2-A382-00C04F991E27" },
+ { "Internet Explorer Branding",
+ "A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B" },
+ { "QoS Packet Scheduler",
+ "426031c0-0b47-4852-b0ca-ac3d37bfcb39" },
+ { "Scripts",
+ "42B5FAAE-6536-11D2-AE5A-0000F87571E3" },
+ { "Security",
+ "827D319E-6EAC-11D2-A4EA-00C04F79F83A" },
+ { "Software Installation",
+ "C6DC5466-785A-11D2-84D0-00C04FB169F7" },
+ { "Wireless Group Policy",
+ "0ACDD40C-75AC-BAA0-BF6DE7E7FE63" },
+ { NULL, NULL }
+};
+
+/* guess work */
+static struct snapin_table gpo_cse_snapin_extensions[] = {
+ { "Administrative Templates",
+ "0F6B957D-509E-11D1-A7CC-0000F87571E3", gpo_snapin_handler_none },
+ { "Certificates",
+ "53D6AB1D-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
+ { "EFS recovery policy processing",
+ "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_none },
+ { "Folder Redirection policy processing",
+ "25537BA6-77A8-11D2-9B6C-0000F8080861", gpo_snapin_handler_none },
+ { "Folder Redirection",
+ "88E729D6-BDC1-11D1-BD2A-00C04FB9603F", gpo_snapin_handler_none },
+ { "Registry policy processing",
+ "35378EAC-683F-11D2-A89A-00C04FBBCFA2", gpo_snapin_handler_none },
+ { "Remote Installation Services",
+ "3060E8CE-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
+ { "Security Settings",
+ "803E14A0-B4FB-11D0-A0D0-00A0C90F574B", gpo_snapin_handler_security_settings },
+ { "Security policy processing",
+ "827D319E-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_security_settings },
+ { "unknown",
+ "3060E8D0-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
+ { "unknown2",
+ "53D6AB1B-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
+ { NULL, NULL, NULL }
+};
+
+static const char *name_to_guid_string(const char *name, struct gpo_table *table)
+{
+ int i;
+
+ for (i = 0; table[i].name; i++) {
+ if (strequal(name, table[i].name)) {
+ return table[i].guid_string;
+ }
+ }
+
+ return NULL;
+}
+
+static const char *guid_string_to_name(const char *guid_string, struct gpo_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;
+}
+
+static const char *default_gpo_name_to_guid_string(const char *name)
+{
+ return name_to_guid_string(name, gpo_default_policy);
+}
+
+static const char *default_gpo_guid_string_to_name(const char *guid)
+{
+ return guid_string_to_name(guid, gpo_default_policy);
+}
+
+const char *cse_gpo_guid_string_to_name(const char *guid)
+{
+ return guid_string_to_name(guid, gpo_cse_extensions);
+}
+
+static const char *cse_gpo_name_to_guid_string(const char *name)
+{
+ return name_to_guid_string(name, gpo_cse_extensions);
+}
+
+const char *cse_snapin_gpo_guid_string_to_name(const char *guid)
+{
+ return guid_string_to_name(guid, gpo_cse_snapin_extensions);
+}
+
+void dump_gp_ext(struct GP_EXT *gp_ext)
+{
+ int lvl = 10;
+ int i;
+
+ if (gp_ext == NULL) {
+ return;
+ }
+
+ DEBUG(lvl,("---------------------\n\n"));
+ DEBUGADD(lvl,("name:\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,("snapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
+ DEBUGADD(lvl,("snapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
+ }
+}
+
+void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo)
+{
+ int lvl = 1;
+
+ if (gpo == NULL) {
+ return;
+ }
+
+ DEBUG(lvl,("---------------------\n\n"));
+
+ 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,("filesyspath:\t\t%s\n", gpo->file_sys_path));
+ DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
+
+ DEBUGADD(lvl,("options:\t\t%d ", gpo->options));
+ if (gpo->options & GPFLAGS_USER_SETTINGS_DISABLED) {
+ DEBUGADD(lvl,("GPFLAGS_USER_SETTINGS_DISABLED "));
+ }
+ if (gpo->options & GPFLAGS_MACHINE_SETTINGS_DISABLED) {
+ DEBUGADD(lvl,("GPFLAGS_MACHINE_SETTINGS_DISABLED"));
+ }
+ DEBUGADD(lvl,("\n"));
+
+ DEBUGADD(lvl,("link:\t\t\t%s\n", gpo->link));
+ DEBUGADD(lvl,("link_type:\t\t%d ", gpo->link_type));
+ switch (gpo->link_type) {
+ case GP_LINK_UNKOWN:
+ DEBUGADD(lvl,("GP_LINK_UNKOWN\n"));
+ break;
+ case GP_LINK_OU:
+ DEBUGADD(lvl,("GP_LINK_OU\n"));
+ break;
+ case GP_LINK_DOMAIN:
+ DEBUGADD(lvl,("GP_LINK_DOMAIN\n"));
+ break;
+ case GP_LINK_SITE:
+ DEBUGADD(lvl,("GP_LINK_SITE\n"));
+ break;
+ case GP_LINK_MACHINE:
+ DEBUGADD(lvl,("GP_LINK_MACHINE\n"));
+ break;
+ default:
+ break;
+ }
+
+ if (gpo->machine_extensions) {
+
+ struct GP_EXT gp_ext;
+ ADS_STATUS status;
+
+ DEBUGADD(lvl,("machine_extensions:\t%s\n", gpo->machine_extensions));
+
+ status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
+ if (!ADS_ERR_OK(status)) {
+ return;
+ }
+ dump_gp_ext(&gp_ext);
+ }
+
+ if (gpo->user_extensions) {
+
+ struct GP_EXT gp_ext;
+ ADS_STATUS status;
+
+ DEBUGADD(lvl,("user_extensions:\t%s\n", gpo->user_extensions));
+
+ status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
+ if (!ADS_ERR_OK(status)) {
+ return;
+ }
+ dump_gp_ext(&gp_ext);
+ }
+};
+
+void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
+{
+ ADS_STATUS status;
+ int i;
+ int lvl = 10;
+
+ if (gp_link == NULL) {
+ return;
+ }
+
+ DEBUG(lvl,("---------------------\n\n"));
+
+ DEBUGADD(lvl,("gplink: %s\n", gp_link->gp_link));
+ DEBUGADD(lvl,("gpopts: %d ", gp_link->gp_opts));
+ switch (gp_link->gp_opts) {
+ case GPOPTIONS_INHERIT:
+ DEBUGADD(lvl,("GPOPTIONS_INHERIT\n"));
+ break;
+ case GPOPTIONS_BLOCK_INHERITANCE:
+ DEBUGADD(lvl,("GPOPTIONS_BLOCK_INHERITANCE\n"));
+ break;
+ default:
+ break;
+ }
+
+ DEBUGADD(lvl,("num links: %d\n", gp_link->num_links));
+
+ for (i = 0; i < gp_link->num_links; i++) {
+
+ DEBUGADD(lvl,("---------------------\n\n"));
+
+ DEBUGADD(lvl,("link: #%d\n", i + 1));
+ DEBUGADD(lvl,("name: %s\n", gp_link->link_names[i]));
+
+ DEBUGADD(lvl,("opt: %d ", gp_link->link_opts[i]));
+ if (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) {
+ DEBUGADD(lvl,("GPO_LINK_OPT_ENFORCED "));
+ }
+ if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
+ DEBUGADD(lvl,("GPO_LINK_OPT_DISABLED"));
+ }
+ DEBUGADD(lvl,("\n"));
+
+ if (ads != NULL && mem_ctx != NULL) {
+
+ struct GROUP_POLICY_OBJECT gpo;
+
+ status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, &gpo);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
+ return;
+ }
+ dump_gpo(mem_ctx, &gpo);
+ }
+ }
+}
+
+ADS_STATUS process_extension_with_snapin(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *extension_guid,
+ const char *snapin_guid)
+{
+ int i;
+
+ for (i=0; gpo_cse_snapin_extensions[i].guid_string; i++) {
+
+ if (strcmp(gpo_cse_snapin_extensions[i].guid_string, snapin_guid) == 0) {
+
+ return gpo_cse_snapin_extensions[i].snapin_fn(ads, mem_ctx,
+ extension_guid, snapin_guid);
+ }
+ }
+
+ DEBUG(10,("process_extension_with_snapin: no snapin handler for extension %s (%s) found\n",
+ extension_guid, snapin_guid));
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT *gpo,
+ const char *extension_guid,
+ uint32 flags)
+{
+ ADS_STATUS status;
+ struct GP_EXT gp_ext;
+ int i;
+
+ if (flags & GPO_LIST_FLAG_MACHINE) {
+
+ if (gpo->machine_extensions) {
+
+ status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
+
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ } else {
+ /* nothing to apply */
+ return ADS_ERROR(LDAP_SUCCESS);
+ }
+
+ } else {
+
+ if (gpo->user_extensions) {
+
+ status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
+
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+ } else {
+ /* nothing to apply */
+ return ADS_ERROR(LDAP_SUCCESS);
+ }
+ }
+
+ for (i=0; i<gp_ext.num_exts; i++) {
+
+ if (extension_guid && !strequal(extension_guid, gp_ext.extensions_guid[i])) {
+ continue;
+ }
+
+ status = process_extension_with_snapin(ads, mem_ctx, gp_ext.extensions_guid[i],
+ gp_ext.snapins_guid[i]);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ struct GROUP_POLICY_OBJECT **gpo_list,
+ const char *extensions_guid,
+ uint32 flags)
+{
+ ADS_STATUS status;
+ struct GROUP_POLICY_OBJECT *gpo = *gpo_list;
+
+ for (gpo = *gpo_list; gpo; gpo = gpo->next) {
+
+ status = gpo_process_a_gpo(ads, mem_ctx, gpo,
+ extensions_guid, flags);
+
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_snapin_handler_none(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *extension_guid,
+ const char *snapin_guid)
+{
+ DEBUG(10,("gpo_snapin_handler_none\n"));
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_snapin_handler_security_settings(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *extension_guid,
+ const char *snapin_guid)
+{
+ DEBUG(10,("gpo_snapin_handler_security_settings\n"));
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_lockout_policy(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *hostname,
+ SAM_UNK_INFO_12 *lockout_policy)
+{
+ return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
+}
+
+ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ const char *hostname,
+ SAM_UNK_INFO_1 *password_policy)
+{
+ ADS_STATUS status;
+ struct GROUP_POLICY_OBJECT *gpo_list;
+ const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
+ char *filter, *dn;
+ void *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);
+ }
+
+ status = ads_do_search_all(ads, ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ filter, attrs, &res);
+
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ dn = ads_get_dn(ads, res);
+ if (dn == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
+ 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)) {
+ return status;
+ }
+
+ status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list,
+ cse_gpo_name_to_guid_string("Security"),
+ GPO_LIST_FLAG_MACHINE);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ return ADS_ERROR(LDAP_SUCCESS);
+}
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index d5b4b11fa24..e5211813d36 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -58,17 +58,21 @@ kerb_prompter(krb5_context ctx, void *data,
place in default cache location.
remus@snapserver.com
*/
-int kerberos_kinit_password(const char *principal,
+int kerberos_kinit_password_ext(const char *principal,
const char *password,
int time_offset,
time_t *expire_time,
- const char *cache_name)
+ time_t *renew_till_time,
+ const char *cache_name,
+ BOOL request_pac,
+ time_t renewable_time)
{
krb5_context ctx = NULL;
krb5_error_code code = 0;
krb5_ccache cc = NULL;
krb5_principal me;
krb5_creds my_creds;
+ krb5_get_init_creds_opt opt;
initialize_krb5_error_table();
if ((code = krb5_init_context(&ctx)))
@@ -77,9 +81,11 @@ int kerberos_kinit_password(const char *principal,
if (time_offset != 0) {
krb5_set_real_time(ctx, time(NULL) + time_offset, 0);
}
-
- if ((code = krb5_cc_resolve(ctx, cache_name ?
- cache_name : krb5_cc_default_name(ctx), &cc))) {
+
+ DEBUG(10,("kerberos_kinit_password: using %s as ccache\n",
+ cache_name ? cache_name: krb5_cc_default_name(ctx)));
+
+ if ((code = krb5_cc_resolve(ctx, cache_name ? cache_name : krb5_cc_default_name(ctx), &cc))) {
krb5_free_context(ctx);
return code;
}
@@ -88,10 +94,20 @@ int kerberos_kinit_password(const char *principal,
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) {
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
+ krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+#endif
+ }
+
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
- kerb_prompter,
- NULL, 0, NULL, NULL))) {
+ kerb_prompter, NULL, 0, NULL, &opt)))
+ {
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
return code;
@@ -111,9 +127,14 @@ int kerberos_kinit_password(const char *principal,
krb5_free_context(ctx);
return code;
}
-
- if (expire_time)
+
+ if (expire_time) {
*expire_time = (time_t) my_creds.times.endtime;
+ }
+
+ if (renew_till_time) {
+ *renew_till_time = (time_t) my_creds.times.renew_till;
+ }
krb5_cc_close(ctx, cc);
krb5_free_cred_contents(ctx, &my_creds);
@@ -156,8 +177,8 @@ int ads_kinit_password(ADS_STRUCT *ads)
return KRB5_LIBOS_CANTREADPWD;
}
- ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset,
- &ads->auth.expire, NULL);
+ ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
+ &ads->auth.expire, NULL, NULL, False, ads->auth.renewable);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
@@ -349,10 +370,10 @@ static krb5_error_code get_service_ticket(krb5_context ctx,
if (password == NULL) {
goto out;
}
- if ((err = kerberos_kinit_password(machine_account, password, 0, NULL, LIBADS_CCACHE_NAME)) != 0) {
- DEBUG(0,("get_service_ticket: kerberos_kinit_password %s@%s failed: %s\n",
+ if ((err = kerberos_kinit_password(machine_account, password,
+ 0, LIBADS_CCACHE_NAME)) != 0) {
+ DEBUG(0,("get_service_ticket: kerberos_kinit_password %s failed: %s\n",
machine_account,
- lp_realm(),
error_message(err)));
goto out;
}
@@ -780,4 +801,20 @@ BOOL kerberos_derive_cifs_salting_principals(void)
}
return retval;
}
+
+int kerberos_kinit_password(const char *principal,
+ const char *password,
+ int time_offset,
+ const char *cache_name)
+{
+ return kerberos_kinit_password_ext(principal,
+ password,
+ time_offset,
+ 0,
+ 0,
+ cache_name,
+ False,
+ 0);
+}
+
#endif
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index 220bf14e32c..934c1131eb0 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -111,6 +111,22 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
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",
@@ -243,11 +259,17 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
krb5_free_keyblock(context, key);
break;
}
-
+
DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
(unsigned int)enctypes[i], error_message(ret)));
+ /* successfully decrypted but ticket is just not valid at the moment */
+ if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
+ ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+ break;
+ }
+
krb5_free_keyblock(context, key);
}
@@ -377,10 +399,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n",
error_message(ret)));
goto out;
- } else {
- authtime = get_authtime_from_tkt(tkt);
- client_principal = get_principal_from_tkt(tkt);
- }
+ }
+
+ authtime = get_authtime_from_tkt(tkt);
+ client_principal = get_principal_from_tkt(tkt);
ret = krb5_mk_rep(context, auth_context, &packet);
if (ret) {
@@ -437,8 +459,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
#endif
#endif
- if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
- principal))) {
+ if ((ret = krb5_unparse_name(context, client_principal, principal))) {
DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
diff --git a/source/libads/krb5_errs.c b/source/libads/krb5_errs.c
new file mode 100644
index 00000000000..0c2e704702c
--- /dev/null
+++ b/source/libads/krb5_errs.c
@@ -0,0 +1,109 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Kerberos error mapping functions
+ * 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"
+
+#ifdef HAVE_KRB5
+
+static const struct {
+ krb5_error_code krb5_code;
+ NTSTATUS ntstatus;
+} krb5_to_nt_status_map[] = {
+ {KRB5_CC_IO, NT_STATUS_UNEXPECTED_IO_ERROR},
+ {KRB5KDC_ERR_BADOPTION, NT_STATUS_INVALID_PARAMETER},
+ {KRB5KDC_ERR_CLIENT_REVOKED, NT_STATUS_ACCESS_DENIED},
+ {KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, NT_STATUS_INVALID_ACCOUNT_NAME},
+ {KRB5KDC_ERR_ETYPE_NOSUPP, NT_STATUS_LOGON_FAILURE},
+#if defined(KRB5KDC_ERR_KEY_EXPIRED) /* Heimdal */
+ {KRB5KDC_ERR_KEY_EXPIRED, NT_STATUS_PASSWORD_EXPIRED},
+#elif defined(KRB5KDC_ERR_KEY_EXP) /* MIT */
+ {KRB5KDC_ERR_KEY_EXP, NT_STATUS_PASSWORD_EXPIRED},
+#else
+#error Neither KRB5KDC_ERR_KEY_EXPIRED nor KRB5KDC_ERR_KEY_EXP available
+#endif
+ {25, NT_STATUS_PASSWORD_EXPIRED}, /* FIXME: bug in heimdal 0.7 krb5_get_init_creds_password (Inappropriate ioctl for device (25)) */
+ {KRB5KDC_ERR_NULL_KEY, NT_STATUS_LOGON_FAILURE},
+ {KRB5KDC_ERR_POLICY, NT_STATUS_PASSWORD_RESTRICTION},
+ {KRB5KDC_ERR_PREAUTH_FAILED, NT_STATUS_LOGON_FAILURE},
+ {KRB5KDC_ERR_SERVICE_REVOKED, NT_STATUS_ACCESS_DENIED},
+ {KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, NT_STATUS_INVALID_ACCOUNT_NAME},
+ {KRB5KDC_ERR_SUMTYPE_NOSUPP, NT_STATUS_LOGON_FAILURE},
+ {KRB5KDC_ERR_TGT_REVOKED, NT_STATUS_ACCESS_DENIED},
+ {KRB5_KDC_UNREACH, NT_STATUS_NO_LOGON_SERVERS},
+ {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},
+ {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
+ {0, NT_STATUS_OK}
+};
+
+static const struct {
+ NTSTATUS ntstatus;
+ krb5_error_code krb5_code;
+} nt_status_to_krb5_map[] = {
+ {NT_STATUS_LOGON_FAILURE, KRB5KDC_ERR_PREAUTH_FAILED},
+ {NT_STATUS_NO_LOGON_SERVERS, KRB5_KDC_UNREACH},
+ {NT_STATUS_OK, 0}
+};
+
+/*****************************************************************************
+convert a KRB5 error to a NT status32 code
+ *****************************************************************************/
+ NTSTATUS krb5_to_nt_status(krb5_error_code kerberos_error)
+{
+ int i;
+
+ if (kerberos_error == 0) {
+ return NT_STATUS_OK;
+ }
+
+ for (i=0; NT_STATUS_V(krb5_to_nt_status_map[i].ntstatus); i++) {
+ if (kerberos_error == krb5_to_nt_status_map[i].krb5_code)
+ return krb5_to_nt_status_map[i].ntstatus;
+ }
+
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+/*****************************************************************************
+convert an NT status32 code to a KRB5 error
+ *****************************************************************************/
+ krb5_error_code nt_status_to_krb5(NTSTATUS nt_status)
+{
+ int i;
+
+ if NT_STATUS_IS_OK(nt_status) {
+ return 0;
+ }
+
+ for (i=0; NT_STATUS_V(nt_status_to_krb5_map[i].ntstatus); i++) {
+ if (NT_STATUS_EQUAL(nt_status,nt_status_to_krb5_map[i].ntstatus))
+ return nt_status_to_krb5_map[i].krb5_code;
+ }
+
+ return KRB5KRB_ERR_GENERIC;
+}
+
+#endif
+
diff --git a/source/libads/krb5_setpw.c b/source/libads/krb5_setpw.c
index 31d0a02cad0..415c1e92294 100644
--- a/source/libads/krb5_setpw.c
+++ b/source/libads/krb5_setpw.c
@@ -24,9 +24,17 @@
#ifdef HAVE_KRB5
#define DEFAULT_KPASSWD_PORT 464
+
#define KRB5_KPASSWD_VERS_CHANGEPW 1
+
#define KRB5_KPASSWD_VERS_SETPW 0xff80
#define KRB5_KPASSWD_VERS_SETPW_ALT 2
+
+#define KRB5_KPASSWD_SUCCESS 0
+#define KRB5_KPASSWD_MALFORMED 1
+#define KRB5_KPASSWD_HARDERROR 2
+#define KRB5_KPASSWD_AUTHERROR 3
+#define KRB5_KPASSWD_SOFTERROR 4
#define KRB5_KPASSWD_ACCESSDENIED 5
#define KRB5_KPASSWD_BAD_VERSION 6
#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7
@@ -57,19 +65,22 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
princ = SMB_STRDUP(principal);
if ((c = strchr_m(princ, '/')) == NULL) {
- c = princ;
+ c = princ;
} else {
- *c = '\0';
- c++;
- princ_part1 = princ;
+ *c = '\0';
+ c++;
+ princ_part1 = princ;
}
princ_part2 = c;
if ((c = strchr_m(c, '@')) != NULL) {
- *c = '\0';
- c++;
- realm = c;
+ *c = '\0';
+ c++;
+ realm = c;
+ } else {
+ /* We must have a realm component. */
+ return data_blob(NULL, 0);
}
memset(&req, 0, sizeof(req));
@@ -89,8 +100,9 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
asn1_push_tag(&req, ASN1_CONTEXT(1));
asn1_push_tag(&req, ASN1_SEQUENCE(0));
- if (princ_part1)
- asn1_write_GeneralString(&req, princ_part1);
+ if (princ_part1) {
+ asn1_write_GeneralString(&req, princ_part1);
+ }
asn1_write_GeneralString(&req, princ_part2);
asn1_pop_tag(&req);
@@ -143,6 +155,10 @@ static krb5_error_code build_kpasswd_request(uint16 pversion,
else
return EINVAL;
+ if (setpw.data == NULL || setpw.length == 0) {
+ return EINVAL;
+ }
+
encoded_setpw.data = (char *)setpw.data;
encoded_setpw.length = setpw.length;
@@ -213,6 +229,25 @@ static krb5_error_code setpw_result_code_string(krb5_context context,
return (0);
}
+ krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code)
+{
+ switch(res_code) {
+ case KRB5_KPASSWD_ACCESSDENIED:
+ return KRB5KDC_ERR_BADOPTION;
+ case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+ return KRB5KDC_ERR_BADOPTION;
+ /* return KV5M_ALT_METHOD; MIT-only define */
+ case KRB5_KPASSWD_ETYPE_NOSUPP:
+ return KRB5KDC_ERR_ETYPE_NOSUPP;
+ case KRB5_KPASSWD_BAD_PRINCIPAL:
+ return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ case KRB5_KPASSWD_POLICY_REJECT:
+ case KRB5_KPASSWD_SOFTERROR:
+ return KRB5KDC_ERR_POLICY;
+ default:
+ return KRB5KRB_ERR_GENERIC;
+ }
+}
static krb5_error_code parse_setpw_reply(krb5_context context,
krb5_auth_context auth_context,
krb5_data *packet)
@@ -312,23 +347,9 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
else {
const char *errstr;
setpw_result_code_string(context, res_code, &errstr);
- DEBUG(1, ("Error changing password: %s\n", errstr));
-
- switch(res_code) {
- case KRB5_KPASSWD_ACCESSDENIED:
- return KRB5KDC_ERR_BADOPTION;
- case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
- return KRB5KDC_ERR_BADOPTION;
- /* return KV5M_ALT_METHOD; MIT-only define */
- case KRB5_KPASSWD_ETYPE_NOSUPP:
- return KRB5KDC_ERR_ETYPE_NOSUPP;
- case KRB5_KPASSWD_BAD_PRINCIPAL:
- return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
- case KRB5_KPASSWD_POLICY_REJECT:
- return KRB5KDC_ERR_POLICY;
- default:
- return KRB5KRB_ERR_GENERIC;
- }
+ DEBUG(1, ("Error changing password: %s (%d)\n", errstr, res_code));
+
+ return kpasswd_err_to_krb5_err(res_code);
}
}
@@ -664,7 +685,7 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
{
int ret;
- if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL, NULL))) {
+ if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL))) {
DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index 4479568f5dc..c2ebf14d2f9 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 2001
Copyright (C) Remus Koos 2001
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
+ 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
@@ -136,6 +137,10 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
ads->ldap_port = port;
ads->ldap_ip = *interpret_addr2(srv);
free(srv);
+
+ /* cache the successful connection */
+
+ saf_store( ads->server.workgroup, server );
return True;
}
@@ -804,6 +809,37 @@ 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
+ **/
+char *ads_parent_dn(const char *dn)
+{
+ char *p = strchr(dn, ',');
+
+ if (p == NULL) {
+ return NULL;
+ }
+
+ return p+1;
+}
+
+/**
* Find a machine account given a hostname
* @param ads connection to ads server
* @param res ** which will contain results - free res* with ads_msgfree()
@@ -1047,7 +1083,8 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn)
/**
* Build an org unit string
* if org unit is Computers or blank then assume a container, otherwise
- * assume a \ separated list of organisational units
+ * assume a / separated list of organisational units.
+ * jmcd: '\' is now used for escapes so certain chars can be in the ou (e.g. #)
* @param ads connection to ads server
* @param org_unit Organizational unit
* @return org unit string - caller must free
@@ -1068,7 +1105,10 @@ char *ads_ou_string(ADS_STRUCT *ads, const char *org_unit)
return SMB_STRDUP("cn=Computers");
}
- return ads_build_path(org_unit, "\\/", "ou=", 1);
+ /* jmcd: removed "\\" from the separation chars, because it is
+ needed as an escape for chars like '#' which are valid in an
+ OU name */
+ return ads_build_path(org_unit, "/", "ou=", 1);
}
/**
@@ -1490,9 +1530,9 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name
if (!exists) {
ads_mod_str(ctx, &mods, "cn", machine_name);
ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
- ads_mod_str(ctx, &mods, "userAccountControl", controlstr);
ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
}
+ ads_mod_str(ctx, &mods, "userAccountControl", controlstr);
ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
ads_mod_str(ctx, &mods, "userPrincipalName", host_upn);
ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
@@ -1620,6 +1660,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
void (*handler)(const char *, struct berval **);
} handlers[] = {
{"objectGUID", False, dump_guid},
+ {"netbootGUID", False, dump_guid},
{"nTSecurityDescriptor", False, dump_sd},
{"dnsRecord", False, dump_binary},
{"objectSid", False, dump_sid},
@@ -1877,7 +1918,10 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
* we have to bail out before prs_init */
ps_wire.is_dynamic = False;
- if (!ads) return ADS_ERROR(LDAP_SERVER_DOWN);
+ if (!ads) {
+ SAFE_FREE(escaped_hostname);
+ return ADS_ERROR(LDAP_SERVER_DOWN);
+ }
ret = ADS_ERROR(LDAP_SUCCESS);
@@ -1895,6 +1939,8 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
ret = ads_search(ads, (void *) &res, expr, attrs);
+ SAFE_FREE(expr);
+
if (!ADS_ERR_OK(ret)) return ret;
if ( !(msg = ads_first_entry(ads, res) )) {
@@ -2655,7 +2701,7 @@ ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *
asprintf(&expr, "(&(objectclass=computer)(dnshostname=%s.%s))",
ads->config.ldap_server_name, ads->config.realm);
if (expr == NULL) {
- ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
rc = ads_search(ads, &res, expr, attrs);
@@ -2701,4 +2747,167 @@ ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *
return ADS_SUCCESS;
}
+/**
+ * find our site name
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param site_name Pointer to the sitename
+ * @return status of search
+ **/
+ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name)
+{
+ ADS_STATUS status;
+ void *res;
+ const char *dn, *service_name;
+ const char *attrs[] = { "dsServiceName", NULL };
+
+ status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ service_name = ads_pull_string(ads, mem_ctx, res, "dsServiceName");
+ if (service_name == NULL) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ /* go up three levels */
+ dn = ads_parent_dn(ads_parent_dn(ads_parent_dn(service_name)));
+ if (dn == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ *site_name = talloc_strdup(mem_ctx, dn);
+ if (*site_name == NULL) {
+ 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
+ */
+}
+
+/**
+ * find the site dn where a machine resides
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param computer_name name of the machine
+ * @param site_name Pointer to the sitename
+ * @return status of search
+ **/
+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;
+ const char *parent, *config_context, *filter;
+ const char *attrs[] = { "configurationNamingContext", NULL };
+ char *dn;
+
+ /* shortcut a query */
+ if (strequal(computer_name, ads->config.ldap_server_name)) {
+ return ads_site_dn(ads, mem_ctx, site_dn);
+ }
+
+ status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
+ if (config_context == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
+ if (filter == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ 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) {
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ dn = ads_get_dn(ads, res);
+ if (dn == NULL) {
+ 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_memfree(ads, dn);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ *site_dn = talloc_strdup(mem_ctx, parent);
+ if (*site_dn == NULL) {
+ ads_memfree(ads, dn);
+ ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ ads_memfree(ads, dn);
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+/**
+ * get the upn suffixes for a domain
+ * @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
+ * @return status of search
+ **/
+ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixes, size_t *num_suffixes)
+{
+ ADS_STATUS status;
+ void *res;
+ const char *config_context, *base;
+ const char *attrs[] = { "configurationNamingContext", NULL };
+ const char *attrs2[] = { "uPNSuffixes", NULL };
+
+ status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
+ if (config_context == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ base = talloc_asprintf(mem_ctx, "cn=Partitions,%s", config_context);
+ if (base == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_search_dn(ads, &res, base, attrs2);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+ }
+
+ suffixes = ads_pull_strings(ads, mem_ctx, &res, "uPNSuffixes", num_suffixes);
+ if (suffixes == NULL) {
+ ads_msgfree(ads, res);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
#endif
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index 44a95f59908..d8d33a924f2 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -294,16 +294,28 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
/* we need to fetch a service ticket as the ldap user in the
servers realm, regardless of our realm */
asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm);
- krb5_init_context(&ctx);
- krb5_set_default_tgs_ktypes(ctx, enc_types);
- krb5_parse_name(ctx, sname, &principal);
+
+ initialize_krb5_error_table();
+ status = ADS_ERROR_KRB5(krb5_init_context(&ctx));
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+ status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types));
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+ status = ADS_ERROR_KRB5(krb5_parse_name(ctx, sname, &principal));
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
free(sname);
krb5_free_context(ctx);
input_name.value = &principal;
input_name.length = sizeof(principal);
- gss_rc = gss_import_name(&minor_status,&input_name,&nt_principal, &serv_name);
+ gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name);
if (gss_rc) {
return ADS_ERROR_GSS(gss_rc, minor_status);
}
@@ -375,8 +387,9 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
p = (uint8 *)output_token.value;
+#if 0
file_save("sasl_gssapi.dat", output_token.value, output_token.length);
-
+#endif
max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
sec_layer = *p;
@@ -419,7 +432,7 @@ failed:
ber_bvfree(scred);
return status;
}
-#endif
+#endif /* HAVE_GGSAPI */
/* mapping between SASL mechanisms and functions */
static struct {
@@ -466,5 +479,5 @@ ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
}
-#endif
+#endif /* HAVE_LDAP */
diff --git a/source/libmsrpc/cac_lsarpc.c b/source/libmsrpc/cac_lsarpc.c
index d2e52f01a4c..72f22de5f22 100644
--- a/source/libmsrpc/cac_lsarpc.c
+++ b/source/libmsrpc/cac_lsarpc.c
@@ -59,7 +59,13 @@ int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenP
hnd->_internal.pipes[PI_LSARPC] = True;
}
- policy = SMB_MALLOC_P(POLICY_HND);
+ 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;
@@ -89,7 +95,6 @@ int cac_LsaOpenPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpenP
}
if(!NT_STATUS_IS_OK(hnd->status)) {
- SAFE_FREE(policy);
return CAC_FAILURE;
}
@@ -119,14 +124,13 @@ int cac_LsaClosePolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *po
return CAC_FAILURE;
}
-
hnd->status = rpccli_lsa_close(pipe_hnd, mem_ctx, pol);
+ TALLOC_FREE(pol);
+
if(!NT_STATUS_IS_OK(hnd->status))
return CAC_FAILURE;
- SAFE_FREE(pol);
-
return CAC_SUCCESS;
}
@@ -298,7 +302,7 @@ int cac_LsaGetSidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Ls
/*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, &sids, &types);
+ (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*/
@@ -424,7 +428,7 @@ int cac_LsaFetchSid(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaFetchSi
op->out.local_sid->domain = dom_name;
sid_copy(&op->out.local_sid->sid, local_sid);
- talloc_free(local_sid);
+ TALLOC_FREE(local_sid);
}
domain:
@@ -436,7 +440,7 @@ domain:
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 = (result == CAC_SUCCESS) ? CAC_PARTIAL_SUCCESS : CAC_FAILURE;
+ result = CAC_FAILURE;
goto done;
}
else if(result == CAC_FAILURE) {
@@ -453,7 +457,7 @@ domain:
op->out.domain_sid->domain = dom_name;
sid_copy(&op->out.domain_sid->sid, domain_sid);
- talloc_free(domain_sid);
+ TALLOC_FREE(domain_sid);
}
done:
@@ -477,7 +481,7 @@ int cac_LsaQueryInfoPolicy(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Lsa
return CAC_FAILURE;
}
- if(!op->in.pol) {
+ if(!op || !op->in.pol) {
hnd->status = NT_STATUS_INVALID_PARAMETER;
return CAC_FAILURE;
}
@@ -521,6 +525,7 @@ int cac_LsaEnumSids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaEnumSid
if(!op || !op->in.pol) {
hnd->status = NT_STATUS_INVALID_PARAMETER;
+ return CAC_FAILURE;
}
pipe_hnd = cac_GetPipe(hnd, PI_LSARPC);
@@ -577,7 +582,7 @@ int cac_LsaEnumAccountRights(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct L
uint32 *type;
/*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+ 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;
@@ -792,6 +797,11 @@ int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpen
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) {
@@ -799,7 +809,7 @@ int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpen
uint32 *type;
/*lookup the SID*/
- hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+ 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;
@@ -816,7 +826,7 @@ int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpen
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);
+ TALLOC_FREE(user_pol);
return CAC_FAILURE;
}
@@ -859,7 +869,7 @@ int cac_LsaAddPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAd
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), &user_sid, &type);
+ 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;
@@ -909,7 +919,7 @@ int cac_LsaRemovePrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Ls
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), &user_sid, &type);
+ 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;
@@ -959,7 +969,7 @@ int cac_LsaClearPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Lsa
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), &user_sid, &type);
+ 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;
@@ -1008,7 +1018,7 @@ int cac_LsaSetPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAd
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), &user_sid, &type);
+ 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;
diff --git a/source/libmsrpc/cac_samr.c b/source/libmsrpc/cac_samr.c
index bf34ec55b83..60c6562988e 100644
--- a/source/libmsrpc/cac_samr.c
+++ b/source/libmsrpc/cac_samr.c
@@ -300,7 +300,7 @@ int cac_SamOpenUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamOpenUse
return CAC_FAILURE;
}
- talloc_free(rid_types);
+ TALLOC_FREE(rid_types);
}
else {
@@ -518,8 +518,8 @@ int cac_SamGetNamesFromRids(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Sa
map_out[i].rid = op->in.rids[i];
}
- talloc_free(names_out);
- talloc_free(name_types_out);
+ TALLOC_FREE(names_out);
+ TALLOC_FREE(name_types_out);
op->out.num_names = num_names_out;
op->out.map = map_out;
@@ -602,8 +602,8 @@ int cac_SamGetRidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Sa
op->out.num_rids = num_rids_out;
op->out.map = map_out;
- talloc_free(rids_out);
- talloc_free(rid_types_out);
+ TALLOC_FREE(rids_out);
+ TALLOC_FREE(rid_types_out);
if(NT_STATUS_EQUAL(hnd->status, STATUS_SOME_UNMAPPED))
return CAC_PARTIAL_SUCCESS;
@@ -665,7 +665,7 @@ int cac_SamGetGroupsForUser(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Sa
attr_out[i] = groups[i].attr;
}
- talloc_free(groups);
+ TALLOC_FREE(groups);
op->out.num_groups = num_groups_out;
op->out.rids = rids_out;
@@ -941,7 +941,7 @@ int cac_SamClearGroupMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_H
result = CAC_FAILURE;
}
- talloc_free(attr);
+ TALLOC_FREE(attr);
return result;
}
@@ -1040,24 +1040,24 @@ int cac_SamEnumGroups(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnumG
names_out = talloc_array(mem_ctx, char *, num_groups_out);
if(!names_out) {
hnd->status = NT_STATUS_NO_MEMORY;
- talloc_free(acct_buf);
+ 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);
+ 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);
+ TALLOC_FREE(acct_buf);
+ TALLOC_FREE(names_out);
+ TALLOC_FREE(desc_out);
return CAC_FAILURE;
}
@@ -1135,24 +1135,24 @@ int cac_SamEnumAliases(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamEnum
names_out = talloc_array(mem_ctx, char *, num_als_out);
if(!names_out) {
hnd->status = NT_STATUS_NO_MEMORY;
- talloc_free(acct_buf);
+ 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);
+ 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);
+ TALLOC_FREE(acct_buf);
+ TALLOC_FREE(names_out);
+ TALLOC_FREE(desc_out);
return CAC_FAILURE;
}
@@ -1438,7 +1438,7 @@ int cac_SamClearAliasMembers(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_H
result = CAC_FAILURE;
}
- talloc_free(sid);
+ TALLOC_FREE(sid);
return result;
}
@@ -2343,7 +2343,7 @@ int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct S
struct rpc_pipe_client *pipe_hnd = NULL;
/*this number taken from rpcclient/cmd_samr.c, I think it is the only supported level*/
- uint16 info_level = 4;
+ uint32 sec_info = DACL_SECURITY_INFORMATION;
SEC_DESC_BUF *sec_out = NULL;
@@ -2366,7 +2366,7 @@ int cac_SamGetSecurityObject(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct S
return CAC_FAILURE;
}
- hnd->status = rpccli_samr_query_sec_obj(pipe_hnd, mem_ctx, op->in.pol, info_level, 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;
@@ -2405,7 +2405,7 @@ int cac_SamFlush(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SamFlush *op)
/*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;
}
diff --git a/source/libmsrpc/cac_svcctl.c b/source/libmsrpc/cac_svcctl.c
index 2651be64abc..83dc0364930 100644
--- a/source/libmsrpc/cac_svcctl.c
+++ b/source/libmsrpc/cac_svcctl.c
@@ -154,7 +154,7 @@ int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnu
return CAC_FAILURE;
}
- talloc_free(svc_buf);
+ TALLOC_FREE(svc_buf);
op->out.num_services = num_svc_out;
diff --git a/source/libmsrpc/cac_winreg.c b/source/libmsrpc/cac_winreg.c
index 1d60cc8fb21..acd83f40760 100644
--- a/source/libmsrpc/cac_winreg.c
+++ b/source/libmsrpc/cac_winreg.c
@@ -56,6 +56,12 @@ int cac_RegConnect(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegConnect
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;
@@ -244,15 +250,15 @@ int cac_RegEnumKeys(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumKey
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);
+ 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);
+ TALLOC_FREE(key_names_out);
+ TALLOC_FREE(class_names_out);
return CAC_FAILURE;
}
@@ -495,6 +501,11 @@ int cac_RegDeleteValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegDele
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;
@@ -577,6 +588,7 @@ int cac_RegQueryKeyInfo(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQue
return CAC_FAILURE;
}
+#endif
int cac_RegQueryValue(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegQueryValue *op) {
struct rpc_pipe_client *pipe_hnd = NULL;
@@ -675,15 +687,15 @@ int cac_RegEnumValues(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegEnumV
values_out = talloc_array(mem_ctx, REG_VALUE_DATA *, op->in.max_values);
if(!values_out) {
- talloc_free(types_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);
+ TALLOC_FREE(types_out);
+ TALLOC_FREE(values_out);
hnd->status = NT_STATUS_NO_MEMORY;
return CAC_FAILURE;
}
@@ -817,7 +829,9 @@ int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegG
WERROR err;
uint32 buf_size;
- SEC_DESC_BUF *buf = NULL;
+ SEC_DESC_BUF buf;
+
+ ZERO_STRUCT(buf);
if(!hnd)
return CAC_FAILURE;
@@ -838,7 +852,7 @@ int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegG
return CAC_FAILURE;
}
- err = rpccli_reg_get_key_sec(pipe_hnd, mem_ctx, op->in.key, op->in.info_type, &buf_size, buf);
+ 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);
@@ -846,8 +860,12 @@ int cac_RegGetKeySecurity(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct RegG
return CAC_FAILURE;
}
- op->out.size = buf->len;
- op->out.descriptor = 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;
+ }
return CAC_SUCCESS;
}
@@ -954,6 +972,12 @@ int cac_Shutdown(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Shutdown *op)
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;
diff --git a/source/libmsrpc/libmsrpc.c b/source/libmsrpc/libmsrpc.c
index 036798b83dd..5f71af21da2 100644
--- a/source/libmsrpc/libmsrpc.c
+++ b/source/libmsrpc/libmsrpc.c
@@ -212,18 +212,9 @@ int cac_Connect(CacServerHandle *hnd, const char *srv) {
void cac_FreeHandle(CacServerHandle * hnd) {
- SMBCSRV *srv = NULL;
-
if(!hnd)
return;
-
- if(srv) {
- /*close all pipe sessions*/
- cli_nt_pipes_close(&(srv->cli));
- }
-
-
/*only free the context if we created it*/
if(!hnd->_internal.user_supplied_ctx) {
smbc_free_context(hnd->_internal.ctx, True);
diff --git a/source/libmsrpc/libmsrpc_internal.c b/source/libmsrpc/libmsrpc_internal.c
index 6a524cdb038..f57063dc42e 100644
--- a/source/libmsrpc/libmsrpc_internal.c
+++ b/source/libmsrpc/libmsrpc_internal.c
@@ -100,7 +100,6 @@ RPC_DATA_BLOB *cac_MakeRpcDataBlob(TALLOC_CTX *mem_ctx, uint32 data_type, REG_VA
RPC_DATA_BLOB *blob = NULL;
int i;
uint32 size = 0;
- uint32 len = 0;
uint8 *multi = NULL;
uint32 multi_idx = 0;
@@ -149,7 +148,7 @@ RPC_DATA_BLOB *cac_MakeRpcDataBlob(TALLOC_CTX *mem_ctx, uint32 data_type, REG_VA
/*do it using rpcstr_push()*/
multi_idx = 0;
for(i = 0; i < data.reg_multi_sz.num_strings; i++) {
- len = strlen(data.reg_multi_sz.strings[i]) + 1;
+ 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);
@@ -163,12 +162,13 @@ RPC_DATA_BLOB *cac_MakeRpcDataBlob(TALLOC_CTX *mem_ctx, uint32 data_type, REG_VA
break;
default:
- talloc_free(blob);
+ TALLOC_FREE(blob);
blob = NULL;
+ return NULL;
}
if(!(blob->buffer)) {
- talloc_free(blob);
+ TALLOC_FREE(blob);
return NULL;
}
@@ -226,7 +226,7 @@ REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGV
case REG_SZ:
data->reg_sz = cac_unistr_to_str(mem_ctx, buf.buffer, buf.buf_len);
if(!data->reg_sz) {
- talloc_free(data);
+ TALLOC_FREE(data);
errno = ENOMEM;
data = NULL;
}
@@ -237,7 +237,7 @@ REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGV
data->reg_expand_sz = cac_unistr_to_str(mem_ctx, buf.buffer, buf.buf_len);
if(!data->reg_expand_sz) {
- talloc_free(data);
+ TALLOC_FREE(data);
errno = ENOMEM;
data = NULL;
}
@@ -251,7 +251,7 @@ REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGV
data->reg_binary.data = talloc_memdup(mem_ctx, buf.buffer, size);
if(!data->reg_binary.data) {
- talloc_free(data);
+ TALLOC_FREE(data);
errno = ENOMEM;
data = NULL;
}
@@ -281,7 +281,7 @@ REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGV
strings = talloc_array(mem_ctx, char *, num_strings);
if(!strings) {
errno = ENOMEM;
- talloc_free(data);
+ TALLOC_FREE(data);
break;
}
@@ -313,7 +313,7 @@ REG_VALUE_DATA *cac_MakeRegValueData(TALLOC_CTX *mem_ctx, uint32 data_type, REGV
break;
default:
- talloc_free(data);
+ TALLOC_FREE(data);
data = NULL;
}
diff --git a/source/libsmb/asn1.c b/source/libsmb/asn1.c
index 09998407941..072fd302830 100644
--- a/source/libsmb/asn1.c
+++ b/source/libsmb/asn1.c
@@ -31,14 +31,11 @@ BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
{
if (data->has_error) return False;
if (data->length < data->ofs+len) {
- uint8 *newp;
- newp = SMB_REALLOC(data->data, data->ofs+len);
- if (!newp) {
- SAFE_FREE(data->data);
+ data->data = SMB_REALLOC(data->data, data->ofs+len);
+ if (!data->data) {
data->has_error = True;
return False;
}
- data->data = newp;
data->length = data->ofs+len;
}
memcpy(data->data + data->ofs, p, len);
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index ac7d1b1650c..48885f19d84 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -756,7 +756,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
int ret;
use_in_memory_ccache();
- ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL, NULL);
+ ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
if (ret){
SAFE_FREE(principal);
@@ -865,14 +865,16 @@ BOOL cli_session_setup(struct cli_state *cli,
DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
return False;
}
- return True;
+ } else {
+ /* 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;
+ }
}
- /* otherwise do a NT1 style session setup */
+ return True;
- return cli_session_setup_nt1(cli, user,
- pass, passlen, ntpass, ntpasslen,
- workgroup);
}
/****************************************************************************
@@ -1392,7 +1394,11 @@ again:
DEBUG(1,("cli_start_connection: failed to connect to %s (%s)\n",
nmb_namestr(&called), inet_ntoa(ip)));
cli_shutdown(cli);
- return NT_STATUS_UNSUCCESSFUL;
+ if (is_zero_ip(ip)) {
+ return NT_STATUS_BAD_NETWORK_NAME;
+ } else {
+ return NT_STATUS_CONNECTION_REFUSED;
+ }
}
if (retry)
@@ -1410,7 +1416,7 @@ again:
make_nmb_name(&called , "*SMBSERVER", 0x20);
goto again;
}
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_BAD_NETWORK_NAME;
}
cli_setup_signing_state(cli, signing_state);
@@ -1422,7 +1428,10 @@ again:
if (!cli_negprot(cli)) {
DEBUG(1,("failed negprot\n"));
- nt_status = NT_STATUS_UNSUCCESSFUL;
+ nt_status = cli_nt_error(cli);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ }
cli_shutdown(cli);
return nt_status;
}
diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c
index 51f21397f7c..03cfd4dd400 100644
--- a/source/libsmb/clidfs.c
+++ b/source/libsmb/clidfs.c
@@ -585,11 +585,11 @@ BOOL cli_resolve_path( const char *mountpt, struct cli_state *rootcli, const cha
SMB_STRUCT_STAT sbuf;
uint32 attributes;
- *targetcli = NULL;
-
if ( !rootcli || !path || !targetcli )
return False;
+ *targetcli = NULL;
+
/* send a trans2_query_path_info to check for a referral */
clean_path( cleanpath, path );
@@ -682,12 +682,15 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
CLIENT_DFS_REFERRAL *refs = NULL;
size_t num_refs;
uint16 consumed;
- struct cli_state *cli_ipc;
pstring fullpath;
+ BOOL res;
+ uint16 cnum;
if ( !cli || !sharename )
return False;
+ cnum = cli->cnum;
+
/* special case. never check for a referral on the IPC$ share */
if ( strequal( sharename, "IPC$" ) )
@@ -699,12 +702,19 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
/* check for the referral */
- if ( !(cli_ipc = cli_cm_open( cli->desthost, "IPC$", False )) )
+ if (!cli_send_tconX(cli, "IPC$", "IPC", NULL, 0)) {
return False;
-
- if ( !cli_dfs_get_referral(cli_ipc, fullpath, &refs, &num_refs, &consumed)
- || !num_refs )
- {
+ }
+
+ res = cli_dfs_get_referral(cli, fullpath, &refs, &num_refs, &consumed);
+
+ if (!cli_tdis(cli)) {
+ return False;
+ }
+
+ cli->cnum = cnum;
+
+ if (!res || !num_refs ) {
return False;
}
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 258cf8c7585..83664b0b328 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -353,14 +353,15 @@ struct cli_state *cli_initialise(struct cli_state *cli)
/****************************************************************************
External interface.
Close an open named pipe over SMB. Free any authentication data.
+ Returns False if the cli_close call failed.
****************************************************************************/
-void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
+BOOL cli_rpc_pipe_close(struct rpc_pipe_client *cli)
{
BOOL ret;
if (!cli) {
- return;
+ return False;
}
ret = cli_close(cli->cli, cli->fnum);
@@ -384,6 +385,7 @@ void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
DLIST_REMOVE(cli->cli->pipe_list, cli);
talloc_destroy(cli->mem_ctx);
+ return ret;
}
/****************************************************************************
diff --git a/source/libsmb/clierror.c b/source/libsmb/clierror.c
index 9d7555a7201..b84a8ee70f8 100644
--- a/source/libsmb/clierror.c
+++ b/source/libsmb/clierror.c
@@ -230,42 +230,6 @@ void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode)
if (ecode) *ecode = code;
}
-/****************************************************************************
- The following mappings need tidying up and moving into libsmb/errormap.c...
-****************************************************************************/
-
-/* Return a UNIX errno from a dos error class, error number tuple */
-
-static int cli_errno_from_dos(uint8 eclass, uint32 num)
-{
- if (eclass == ERRDOS) {
- switch (num) {
- case ERRbadfile: return ENOENT;
- case ERRbadpath: return ENOTDIR;
- case ERRnoaccess: return EACCES;
- case ERRfilexists: return EEXIST;
- case ERRrename: return EEXIST;
- case ERRbadshare: return EBUSY;
- case ERRlock: return EBUSY;
- case ERRinvalidname: return ENOENT;
- case ERRnosuchshare: return ENODEV;
- }
- }
-
- if (eclass == ERRSRV) {
- switch (num) {
- case ERRbadpw: return EPERM;
- case ERRaccess: return EACCES;
- case ERRnoresource: return ENOMEM;
- case ERRinvdevice: return ENODEV;
- case ERRinvnetname: return ENODEV;
- }
- }
-
- /* for other cases */
- return EINVAL;
-}
-
/* Return a UNIX errno from a NT status code */
static struct {
NTSTATUS status;
@@ -405,9 +369,11 @@ static int cli_errno_from_nt(NTSTATUS status)
int cli_errno(struct cli_state *cli)
{
+ NTSTATUS status;
+
if (cli_is_nt_error(cli)) {
- NTSTATUS status = cli_nt_error(cli);
- return cli_errno_from_nt(status);
+ status = cli_nt_error(cli);
+ return cli_errno_from_nt(status);
}
if (cli_is_dos_error(cli)) {
@@ -415,7 +381,8 @@ int cli_errno(struct cli_state *cli)
uint32 ecode;
cli_dos_error(cli, &eclass, &ecode);
- return cli_errno_from_dos(eclass, ecode);
+ status = dos_to_ntstatus(eclass, ecode);
+ return cli_errno_from_nt(status);
}
/* for other cases */
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index 443f5156653..46ff8af6d5c 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -816,6 +816,7 @@ BOOL cli_close(struct cli_state *cli, int fnum)
send a lock with a specified locktype
this is used for testing LOCKING_ANDX_CANCEL_LOCK
****************************************************************************/
+
NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
uint32 offset, uint32 len, int timeout, unsigned char locktype)
{
@@ -863,11 +864,11 @@ NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
return cli_nt_error(cli);
}
-
/****************************************************************************
Lock a file.
note that timeout is in units of 2 milliseconds
****************************************************************************/
+
BOOL cli_lock(struct cli_state *cli, int fnum,
uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
{
@@ -1068,6 +1069,108 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_
return True;
}
+/****************************************************************************
+ Get/unlock a POSIX lock on a file - internal function.
+****************************************************************************/
+
+static BOOL cli_posix_lock_internal(struct cli_state *cli, int fnum,
+ SMB_BIG_UINT offset, SMB_BIG_UINT len, BOOL wait_lock, enum brl_type lock_type)
+{
+ unsigned int param_len = 4;
+ unsigned int data_len = POSIX_LOCK_DATA_SIZE;
+ uint16 setup = TRANSACT2_SETFILEINFO;
+ char param[4];
+ unsigned char data[POSIX_LOCK_DATA_SIZE];
+ char *rparam=NULL, *rdata=NULL;
+ int saved_timeout = cli->timeout;
+
+ SSVAL(param,0,fnum);
+ SSVAL(param,2,SMB_SET_POSIX_LOCK);
+
+ switch (lock_type) {
+ case READ_LOCK:
+ SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ);
+ break;
+ case WRITE_LOCK:
+ SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE);
+ break;
+ case UNLOCK_LOCK:
+ SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
+ break;
+ default:
+ return False;
+ }
+
+ if (wait_lock) {
+ SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT);
+ cli->timeout = 0x7FFFFFFF;
+ } else {
+ SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT);
+ }
+
+ SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid);
+ SOFF_T(data, POSIX_LOCK_START_OFFSET, offset);
+ SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 2, /* param, length, max */
+ (char *)&data, data_len, cli->max_xmit /* data, length, max */
+ )) {
+ cli->timeout = saved_timeout;
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ cli->timeout = saved_timeout;
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return False;
+ }
+
+ cli->timeout = saved_timeout;
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ return True;
+}
+
+/****************************************************************************
+ POSIX Lock a file.
+****************************************************************************/
+
+BOOL cli_posix_lock(struct cli_state *cli, int fnum,
+ SMB_BIG_UINT offset, SMB_BIG_UINT len,
+ BOOL wait_lock, enum brl_type lock_type)
+{
+ if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
+ return False;
+ }
+ return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type);
+}
+
+/****************************************************************************
+ POSIX Unlock a file.
+****************************************************************************/
+
+BOOL cli_posix_unlock(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_UINT len)
+{
+ return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK);
+}
+
+/****************************************************************************
+ POSIX Get any lock covering a file.
+****************************************************************************/
+
+BOOL cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, SMB_BIG_UINT *plen)
+{
+ return True;
+}
/****************************************************************************
Do a SMBgetattrE call.
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index e0dcefeb1d7..4943f67b776 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -409,9 +409,10 @@ static BOOL ads_cleanup_expired_creds(krb5_context context,
krb5_creds *credsp)
{
krb5_error_code retval;
+ const char *cc_type = krb5_cc_get_type(context, ccache);
- DEBUG(3, ("Ticket in ccache[%s] expiration %s\n",
- krb5_cc_default_name(context),
+ DEBUG(3, ("ads_cleanup_expired_creds: Ticket in ccache[%s:%s] expiration %s\n",
+ cc_type, krb5_cc_get_name(context, ccache),
http_timestring(credsp->times.endtime)));
/* we will probably need new tickets if the current ones
@@ -425,11 +426,11 @@ static BOOL ads_cleanup_expired_creds(krb5_context context,
use memory ccaches, and a FILE one probably means that
we're using creds obtained outside of our exectuable
*/
- if (StrCaseCmp(krb5_cc_get_type(context, ccache), "FILE") == 0) {
- DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a FILE ccache\n"));
+ if (strequal(cc_type, "FILE")) {
+ DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a %s ccache\n", cc_type));
return False;
}
-
+
retval = krb5_cc_remove_cred(context, ccache, 0, credsp);
if (retval) {
DEBUG(1, ("ads_cleanup_expired_creds: krb5_cc_remove_cred failed, err %s\n",
@@ -467,7 +468,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
/* obtain ticket & session key */
ZERO_STRUCT(creds);
if ((retval = krb5_copy_principal(context, server, &creds.server))) {
- DEBUG(1,("krb5_copy_principal failed (%s)\n",
+ DEBUG(1,("ads_krb5_mk_req: krb5_copy_principal failed (%s)\n",
error_message(retval)));
goto cleanup_princ;
}
@@ -502,8 +503,8 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
i++;
}
- DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s) is valid until: (%s - %u)\n",
- principal, krb5_cc_default_name(context),
+ DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s:%s) is valid until: (%s - %u)\n",
+ principal, krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache),
http_timestring((unsigned)credsp->times.endtime),
(unsigned)credsp->times.endtime));
@@ -530,7 +531,8 @@ cleanup_princ:
get a kerberos5 ticket for the given service
*/
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
- DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
+ uint32 extra_ap_opts, const char *ccname)
{
krb5_error_code retval;
krb5_data packet;
@@ -544,7 +546,7 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
ENCTYPE_DES_CBC_MD5,
ENCTYPE_DES_CBC_CRC,
ENCTYPE_NULL};
-
+
initialize_krb5_error_table();
retval = krb5_init_context(&context);
if (retval) {
@@ -557,7 +559,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
krb5_set_real_time(context, time(NULL) + time_offset, 0);
}
- if ((retval = krb5_cc_default(context, &ccdef))) {
+ if ((retval = krb5_cc_resolve(context, ccname ?
+ ccname : krb5_cc_default_name(context), &ccdef))) {
DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n",
error_message(retval)));
goto failed;
@@ -895,7 +898,6 @@ krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);
krb5_keyblock **keyblock)
{
krb5_error_code ret;
- krb5_ap_req *ap_req = NULL;
krb5_kvno kvno;
krb5_enctype enctype;
krb5_keyblock *local_keyblock;
@@ -927,10 +929,6 @@ krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);
}
out:
- if (ap_req) {
- smb_krb5_free_ap_req(context, ap_req);
- }
-
if (ret && local_keyblock != NULL) {
krb5_free_keyblock(context, local_keyblock);
} else {
@@ -991,10 +989,154 @@ out:
#endif
}
+ krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, /* FILE:/tmp/krb5cc_0 */
+ const char *client_string, /* gd@BER.SUSE.DE */
+ const char *service_string, /* krbtgt/BER.SUSE.DE@BER.SUSE.DE */
+ time_t *new_start_time)
+{
+ krb5_error_code ret;
+ krb5_context context = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_principal client = NULL;
+
+ initialize_krb5_error_table();
+ ret = krb5_init_context(&context);
+ if (ret) {
+ goto done;
+ }
+
+ if (!ccache_string) {
+ ccache_string = krb5_cc_default_name(context);
+ }
+
+ DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string));
+
+ /* FIXME: we should not fall back to defaults */
+ ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache);
+ if (ret) {
+ goto done;
+ }
+
+#ifdef HAVE_KRB5_GET_RENEWED_CREDS /* MIT */
+ {
+ krb5_creds creds;
+
+ if (client_string) {
+ ret = krb5_parse_name(context, client_string, &client);
+ if (ret) {
+ goto done;
+ }
+ } else {
+ ret = krb5_cc_get_principal(context, ccache, &client);
+ if (ret) {
+ goto done;
+ }
+ }
+
+ ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string));
+ if (ret) {
+ DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
+ goto done;
+ }
+
+ /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
+ ret = krb5_cc_initialize(context, ccache, client);
+ if (ret) {
+ goto done;
+ }
+
+ ret = krb5_cc_store_cred(context, ccache, &creds);
+
+ if (new_start_time) {
+ *new_start_time = (time_t) creds.times.renew_till;
+ }
+
+ krb5_free_cred_contents(context, &creds);
+ }
+#elif defined(HAVE_KRB5_GET_KDC_CRED) /* Heimdal */
+ {
+ krb5_kdc_flags flags;
+ krb5_creds creds_in;
+ krb5_realm *client_realm;
+ krb5_creds *creds;
+
+ memset(&creds_in, 0, sizeof(creds_in));
+
+ if (client_string) {
+ ret = krb5_parse_name(context, client_string, &creds_in.client);
+ if (ret) {
+ goto done;
+ }
+ } else {
+ ret = krb5_cc_get_principal(context, ccache, &creds_in.client);
+ if (ret) {
+ goto done;
+ }
+ }
+
+ if (service_string) {
+ ret = krb5_parse_name(context, service_string, &creds_in.server);
+ if (ret) {
+ goto done;
+ }
+ } else {
+ /* build tgt service by default */
+ client_realm = krb5_princ_realm(context, client);
+ ret = krb5_make_principal(context, &creds_in.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL);
+ if (ret) {
+ goto done;
+ }
+ }
+
+ flags.i = 0;
+ flags.b.renewable = flags.b.renew = True;
+
+ ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &creds_in, &creds);
+ if (ret) {
+ DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
+ goto done;
+ }
+
+ /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
+ ret = krb5_cc_initialize(context, ccache, creds_in.client);
+ if (ret) {
+ goto done;
+ }
+
+ ret = krb5_cc_store_cred(context, ccache, creds);
+
+ if (new_start_time) {
+ *new_start_time = (time_t) creds->times.renew_till;
+ }
+
+ krb5_free_cred_contents(context, &creds_in);
+ krb5_free_creds(context, creds);
+ }
+#else
+#error No suitable krb5 ticket renew function available
+#endif
+
+
+done:
+ if (client) {
+ krb5_free_principal(context, client);
+ }
+ if (context) {
+ krb5_free_context(context);
+ }
+ if (ccache) {
+ krb5_cc_close(context, ccache);
+ }
+
+ return ret;
+
+}
+
#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)
+ DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
+ const char *ccname)
{
DEBUG(0,("NO KERBEROS SUPPORT\n"));
return 1;
diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c
index 48780e28dfa..1bd30c36e3c 100644
--- a/source/libsmb/clilist.c
+++ b/source/libsmb/clilist.c
@@ -169,13 +169,17 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
void (*fn)(const char *, file_info *, const char *, void *), void *state)
{
- int max_matches = 1366;
+#if 1
+ int max_matches = 1366; /* Match W2k - was 512. */
+#else
+ int max_matches = 512;
+#endif
int info_level;
char *p, *p2;
pstring mask;
file_info finfo;
int i;
- char *tdl, *dirlist = NULL;
+ char *dirlist = NULL;
int dirlist_len = 0;
int total_received = -1;
BOOL First = True;
@@ -334,15 +338,13 @@ 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 */
- tdl = SMB_REALLOC(dirlist,dirlist_len + data_len);
+ dirlist = SMB_REALLOC(dirlist,dirlist_len + data_len);
- if (!tdl) {
+ if (!dirlist) {
DEBUG(0,("cli_list_new: Failed to expand dirlist\n"));
SAFE_FREE(rdata);
SAFE_FREE(rparam);
break;
- } else {
- dirlist = tdl;
}
memcpy(dirlist+dirlist_len,p,data_len);
@@ -417,7 +419,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
int num_asked = (cli->max_xmit - 100)/DIR_STRUCT_SIZE;
int num_received = 0;
int i;
- char *tdl, *dirlist = NULL;
+ char *dirlist = NULL;
pstring mask;
ZERO_ARRAY(status);
@@ -462,14 +464,11 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
first = False;
- tdl = SMB_REALLOC(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
-
- if (!tdl) {
+ dirlist = SMB_REALLOC(dirlist,(num_received + received)*DIR_STRUCT_SIZE);
+ if (!dirlist) {
DEBUG(0,("cli_list_old: failed to expand dirlist"));
- SAFE_FREE(dirlist);
return 0;
}
- else dirlist = tdl;
p = smb_buf(cli->inbuf) + 3;
diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c
index 6716971fe2c..58fa9c8dfff 100644
--- a/source/libsmb/clirap.c
+++ b/source/libsmb/clirap.c
@@ -471,7 +471,6 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
char *rparam=NULL, *rdata=NULL;
int count=8;
BOOL ret;
- void (*date_fn)(struct cli_state *, char *buf,int offset,time_t unixdate);
char *p;
memset(param, 0, sizeof(param));
@@ -480,7 +479,7 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
p = param;
/* Add the information level */
- SSVAL(p, 0, SMB_INFO_STANDARD);
+ SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
/* Skip reserved */
p += 6;
@@ -492,26 +491,27 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
p = data;
- if (cli->win95) {
- date_fn = cli_put_dos_date;
- } else {
- date_fn = cli_put_dos_date2;
- }
-
- /* Add the create, last access, and modification times */
- (*date_fn)(cli, p, 0, c_time);
- (*date_fn)(cli, p, 4, a_time);
- (*date_fn)(cli, p, 8, m_time);
- p += 12;
+ /*
+ * Add the create, last access, modification, and status change times
+ */
+
+ /* Don't set create time, at offset 0 */
+ p += 8;
- /* Skip DataSize and AllocationSize */
+ put_long_date(p, a_time);
+ p += 8;
+
+ put_long_date(p, m_time);
+ p += 8;
+
+ put_long_date(p, c_time);
p += 8;
/* Add attributes */
- SSVAL(p, 0, mode);
- p += 2;
+ SIVAL(p, 0, mode);
+ p += 4;
- /* Add EA size (none) */
+ /* Add padding */
SIVAL(p, 0, 0);
p += 4;
diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c
index a080bd3c64d..650822bf8ed 100644
--- a/source/libsmb/clireadwrite.c
+++ b/source/libsmb/clireadwrite.c
@@ -262,9 +262,14 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset,
if (size > cli->bufsize) {
cli->outbuf = SMB_REALLOC(cli->outbuf, size + 1024);
+ if (!cli->outbuf) {
+ return False;
+ }
cli->inbuf = SMB_REALLOC(cli->inbuf, size + 1024);
- if (cli->outbuf == NULL || cli->inbuf == NULL)
+ if (cli->inbuf == NULL) {
+ SAFE_FREE(cli->outbuf);
return False;
+ }
cli->bufsize = size + 1024;
}
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index cc481a066ab..13bf1a866c9 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -333,7 +333,7 @@ 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);
+ &tkt, session_key_krb5, extra_ap_opts, NULL);
if (retval)
return retval;
diff --git a/source/libsmb/clitrans.c b/source/libsmb/clitrans.c
index 5d3710b92e2..082da67bb8b 100644
--- a/source/libsmb/clitrans.c
+++ b/source/libsmb/clitrans.c
@@ -153,7 +153,6 @@ BOOL cli_send_trans(struct cli_state *cli, int trans,
/* Note we're in a trans state. Save the sequence
* numbers for replies. */
- cli_signing_trans_start(cli, mid);
return(True);
}
@@ -169,13 +168,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
unsigned int total_param=0;
unsigned int this_data,this_param;
NTSTATUS status;
- char *tdata;
- char *tparam;
*data_len = *param_len = 0;
if (!cli_receive_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
@@ -186,7 +182,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
DEBUG(0,("Expected %s response, got command 0x%02x\n",
trans==SMBtrans?"SMBtrans":"SMBtrans2",
CVAL(cli->inbuf,smb_com)));
- cli_signing_trans_stop(cli);
return(False);
}
@@ -199,7 +194,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
status = cli_nt_error(cli);
if (NT_STATUS_IS_ERR(status) || NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES)) {
- cli_signing_trans_stop(cli);
return False;
}
@@ -209,25 +203,19 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
/* allocate it */
if (total_data!=0) {
- tdata = SMB_REALLOC(*data,total_data);
- if (!tdata) {
+ *data = SMB_REALLOC(*data,total_data);
+ if (!(*data)) {
DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
- cli_signing_trans_stop(cli);
return False;
}
- else
- *data = tdata;
}
if (total_param!=0) {
- tparam = SMB_REALLOC(*param,total_param);
- if (!tparam) {
+ *param = SMB_REALLOC(*param,total_param);
+ if (!(*param)) {
DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
- cli_signing_trans_stop(cli);
return False;
}
- else
- *param = tparam;
}
for (;;) {
@@ -237,7 +225,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
if (this_data + *data_len > total_data ||
this_param + *param_len > total_param) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -246,7 +233,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
this_param + *param_len < this_param ||
this_param + *param_len < *param_len) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -259,7 +245,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
data_offset_out + this_data < data_offset_out ||
data_offset_out + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
if (data_offset_in > cli->bufsize ||
@@ -267,7 +252,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
data_offset_in + this_data < data_offset_in ||
data_offset_in + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -282,7 +266,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
param_offset_out + this_param < param_offset_out ||
param_offset_out + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
if (param_offset_in > cli->bufsize ||
@@ -290,7 +273,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
param_offset_in + this_param < param_offset_in ||
param_offset_in + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -303,7 +285,6 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
break;
if (!cli_receive_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
@@ -314,11 +295,9 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
DEBUG(0,("Expected %s response, got command 0x%02x\n",
trans==SMBtrans?"SMBtrans":"SMBtrans2",
CVAL(cli->inbuf,smb_com)));
- cli_signing_trans_stop(cli);
return(False);
}
if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
- cli_signing_trans_stop(cli);
return(False);
}
@@ -332,8 +311,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans,
break;
}
-
- cli_signing_trans_stop(cli);
+
return(True);
}
@@ -459,7 +437,6 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
/* Note we're in a trans state. Save the sequence
* numbers for replies. */
- cli_signing_trans_start(cli, mid);
return(True);
}
@@ -476,13 +453,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
unsigned int this_data,this_param;
uint8 eclass;
uint32 ecode;
- char *tdata;
- char *tparam;
*data_len = *param_len = 0;
if (!cli_receive_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
@@ -492,7 +466,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
CVAL(cli->inbuf,smb_com)));
- cli_signing_trans_stop(cli);
return(False);
}
@@ -504,7 +477,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (cli_is_dos_error(cli)) {
cli_dos_error(cli, &eclass, &ecode);
if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
- cli_signing_trans_stop(cli);
return(False);
}
}
@@ -515,7 +487,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (cli_is_nt_error(cli)) {
if (!NT_STATUS_EQUAL(cli_nt_error(cli),
NT_STATUS_BUFFER_TOO_SMALL)) {
- cli_signing_trans_stop(cli);
return(False);
}
}
@@ -526,24 +497,18 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
/* allocate it */
if (total_data) {
- tdata = SMB_REALLOC(*data,total_data);
- if (!tdata) {
+ *data = SMB_REALLOC(*data,total_data);
+ if (!(*data)) {
DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
- cli_signing_trans_stop(cli);
return False;
- } else {
- *data = tdata;
}
}
if (total_param) {
- tparam = SMB_REALLOC(*param,total_param);
- if (!tparam) {
+ *param = SMB_REALLOC(*param,total_param);
+ if (!(*param)) {
DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
- cli_signing_trans_stop(cli);
return False;
- } else {
- *param = tparam;
}
}
@@ -554,7 +519,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (this_data + *data_len > total_data ||
this_param + *param_len > total_param) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -563,7 +527,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
this_param + *param_len < this_param ||
this_param + *param_len < *param_len) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -576,7 +539,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
data_offset_out + this_data < data_offset_out ||
data_offset_out + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
if (data_offset_in > cli->bufsize ||
@@ -584,7 +546,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
data_offset_in + this_data < data_offset_in ||
data_offset_in + this_data < this_data) {
DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -600,7 +561,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
param_offset_out + this_param < param_offset_out ||
param_offset_out + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
if (param_offset_in > cli->bufsize ||
@@ -608,7 +568,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
param_offset_in + this_param < param_offset_in ||
param_offset_in + this_param < this_param) {
DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
- cli_signing_trans_stop(cli);
return False;
}
@@ -622,7 +581,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
break;
if (!cli_receive_smb(cli)) {
- cli_signing_trans_stop(cli);
return False;
}
@@ -632,13 +590,11 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
CVAL(cli->inbuf,smb_com)));
- cli_signing_trans_stop(cli);
return(False);
}
if (cli_is_dos_error(cli)) {
cli_dos_error(cli, &eclass, &ecode);
if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
- cli_signing_trans_stop(cli);
return(False);
}
}
@@ -648,7 +604,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (cli_is_nt_error(cli)) {
if (!NT_STATUS_EQUAL(cli_nt_error(cli),
NT_STATUS_BUFFER_TOO_SMALL)) {
- cli_signing_trans_stop(cli);
return(False);
}
}
@@ -662,7 +617,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
if (total_data <= *data_len && total_param <= *param_len)
break;
}
-
- cli_signing_trans_stop(cli);
+
return(True);
}
diff --git a/source/libsmb/conncache.c b/source/libsmb/conncache.c
index 2af4d57b804..49512d7a2e5 100644
--- a/source/libsmb/conncache.c
+++ b/source/libsmb/conncache.c
@@ -25,8 +25,6 @@
#include "includes.h"
-#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
-
#define CONNCACHE_ADDR 1
#define CONNCACHE_NAME 2
@@ -44,10 +42,13 @@ struct failed_connection_cache {
static struct failed_connection_cache *failed_connection_cache;
/**********************************************************************
- Check for a previously failed connection
+ Check for a previously failed connection.
+ failed_cache_timeout is an a absolute number of seconds after which
+ we should time this out. If failed_cache_timeout == 0 then time out
+ immediately. If failed_cache_timeout == -1 then never time out.
**********************************************************************/
-NTSTATUS check_negative_conn_cache( const char *domain, const char *server )
+NTSTATUS check_negative_conn_cache_timeout( const char *domain, const char *server, unsigned int failed_cache_timeout )
{
struct failed_connection_cache *fcc;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -59,22 +60,24 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server )
for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
- if ( !(strequal(domain, fcc->domain_name) && strequal(server, fcc->controller)) )
+ if (!(strequal(domain, fcc->domain_name) && strequal(server, fcc->controller))) {
continue; /* no match; check the next entry */
+ }
/* we have a match so see if it is still current */
+ if (failed_cache_timeout != (unsigned int)-1) {
+ if (failed_cache_timeout == 0 ||
+ (time(NULL) - fcc->lookup_time) > (time_t)failed_cache_timeout) {
+ /* Cache entry has expired, delete it */
- if ((time(NULL) - fcc->lookup_time) > FAILED_CONNECTION_CACHE_TIMEOUT)
- {
- /* Cache entry has expired, delete it */
-
- DEBUG(10, ("check_negative_conn_cache: cache entry expired for %s, %s\n",
- domain, server ));
+ DEBUG(10, ("check_negative_conn_cache: cache entry expired for %s, %s\n",
+ domain, server ));
- DLIST_REMOVE(failed_connection_cache, fcc);
- SAFE_FREE(fcc);
+ DLIST_REMOVE(failed_connection_cache, fcc);
+ SAFE_FREE(fcc);
- return NT_STATUS_OK;
+ return NT_STATUS_OK;
+ }
}
/* The timeout hasn't expired yet so return false */
@@ -90,6 +93,11 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server )
return NT_STATUS_OK;
}
+NTSTATUS check_negative_conn_cache( const char *domain, const char *server)
+{
+ return check_negative_conn_cache_timeout(domain, server, FAILED_CONNECTION_CACHE_TIMEOUT);
+}
+
/**********************************************************************
Add an entry to the failed conneciton cache (aither a name of dotted
decimal IP
diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c
index ad06cd9015f..76fc5fc0621 100644
--- a/source/libsmb/credentials.c
+++ b/source/libsmb/credentials.c
@@ -25,7 +25,7 @@
Represent a credential as a string.
****************************************************************************/
-char *credstr(const uchar *cred)
+char *credstr(const unsigned char *cred)
{
static fstring buf;
slprintf(buf, sizeof(buf) - 1, "%02X%02X%02X%02X%02X%02X%02X%02X",
@@ -34,40 +34,106 @@ char *credstr(const uchar *cred)
return buf;
}
+/****************************************************************************
+ Setup the session key and the client and server creds in dc.
+ ADS-style 128 bit session keys.
+ Used by both client and server creds setup.
+****************************************************************************/
+
+static void creds_init_128(struct dcinfo *dc,
+ const DOM_CHAL *clnt_chal_in,
+ const DOM_CHAL *srv_chal_in,
+ const unsigned char mach_pw[16])
+{
+ unsigned char zero[4], tmp[16];
+ HMACMD5Context ctx;
+ struct MD5Context md5;
+
+ /* Just in case this isn't already there */
+ memcpy(dc->mach_pw, mach_pw, 16);
+
+ ZERO_STRUCT(dc->sess_key);
+
+ memset(zero, 0, sizeof(zero));
+
+ hmac_md5_init_rfc2104(mach_pw, 16, &ctx);
+ MD5Init(&md5);
+ MD5Update(&md5, zero, sizeof(zero));
+ MD5Update(&md5, clnt_chal_in->data, 8);
+ MD5Update(&md5, srv_chal_in->data, 8);
+ MD5Final(tmp, &md5);
+ hmac_md5_update(tmp, sizeof(tmp), &ctx);
+ hmac_md5_final(dc->sess_key, &ctx);
+
+ /* debug output */
+ DEBUG(5,("creds_init_128\n"));
+ DEBUG(5,("\tclnt_chal_in: %s\n", credstr(clnt_chal_in->data)));
+ DEBUG(5,("\tsrv_chal_in : %s\n", credstr(srv_chal_in->data)));
+ dump_data_pw("\tsession_key ", (const unsigned char *)dc->sess_key, 16);
+
+ /* Generate the next client and server creds. */
+
+ des_crypt112(dc->clnt_chal.data, /* output */
+ clnt_chal_in->data, /* input */
+ dc->sess_key, /* input */
+ 1);
+
+ des_crypt112(dc->srv_chal.data, /* output */
+ srv_chal_in->data, /* input */
+ dc->sess_key, /* input */
+ 1);
+
+ /* Seed is the client chal. */
+ memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
+}
/****************************************************************************
- Setup the session key.
- Input: 8 byte challenge block
- 8 byte server challenge block
- 16 byte md4 encrypted password
- Output:
- 16 byte session key (last 8 bytes zero).
+ Setup the session key and the client and server creds in dc.
+ Used by both client and server creds setup.
****************************************************************************/
-static void cred_create_session_key(const DOM_CHAL *clnt_chal_in,
+static void creds_init_64(struct dcinfo *dc,
+ const DOM_CHAL *clnt_chal_in,
const DOM_CHAL *srv_chal_in,
- const uchar *pass_in,
- uchar session_key_out[16])
+ const unsigned char mach_pw[16])
{
uint32 sum[2];
unsigned char sum2[8];
+ /* Just in case this isn't already there */
+ memcpy(dc->mach_pw, mach_pw, 16);
+
sum[0] = IVAL(clnt_chal_in->data, 0) + IVAL(srv_chal_in->data, 0);
sum[1] = IVAL(clnt_chal_in->data, 4) + IVAL(srv_chal_in->data, 4);
SIVAL(sum2,0,sum[0]);
SIVAL(sum2,4,sum[1]);
- cred_hash1(session_key_out, sum2, pass_in);
- memset(&session_key_out[8], '\0', 8);
+ ZERO_STRUCT(dc->sess_key);
+
+ des_crypt128(dc->sess_key, sum2, dc->mach_pw);
/* debug output */
- DEBUG(4,("cred_create_session_key\n"));
+ DEBUG(5,("creds_init_64\n"));
+ DEBUG(5,("\tclnt_chal_in: %s\n", credstr(clnt_chal_in->data)));
+ DEBUG(5,("\tsrv_chal_in : %s\n", credstr(srv_chal_in->data)));
+ DEBUG(5,("\tclnt+srv : %s\n", credstr(sum2)));
+ DEBUG(5,("\tsess_key_out : %s\n", credstr(dc->sess_key)));
+
+ /* Generate the next client and server creds. */
+
+ des_crypt112(dc->clnt_chal.data, /* output */
+ clnt_chal_in->data, /* input */
+ dc->sess_key, /* input */
+ 1);
+
+ des_crypt112(dc->srv_chal.data, /* output */
+ srv_chal_in->data, /* input */
+ dc->sess_key, /* input */
+ 1);
- DEBUG(5,(" clnt_chal_in: %s\n", credstr(clnt_chal_in->data)));
- DEBUG(5,(" srv_chal_in : %s\n", credstr(srv_chal_in->data)));
- DEBUG(5,(" clnt+srv : %s\n", credstr(sum2)));
- DEBUG(5,(" sess_key_out : %s\n", credstr(session_key_out)));
+ /* Seed is the client chal. */
+ memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
}
/****************************************************************************
@@ -88,7 +154,7 @@ static void creds_step(struct dcinfo *dc)
DEBUG(5,("\tseed+seq %s\n", credstr(time_chal.data) ));
- cred_hash2(dc->clnt_chal.data, time_chal.data, dc->sess_key);
+ des_crypt112(dc->clnt_chal.data, time_chal.data, dc->sess_key, 1);
DEBUG(5,("\tCLIENT %s\n", credstr(dc->clnt_chal.data) ));
@@ -97,49 +163,42 @@ static void creds_step(struct dcinfo *dc)
DEBUG(5,("\tseed+seq+1 %s\n", credstr(time_chal.data) ));
- cred_hash2(dc->srv_chal.data, time_chal.data, dc->sess_key);
+ des_crypt112(dc->srv_chal.data, time_chal.data, dc->sess_key, 1);
DEBUG(5,("\tSERVER %s\n", credstr(dc->srv_chal.data) ));
}
-
/****************************************************************************
Create a server credential struct.
****************************************************************************/
-void creds_server_init(struct dcinfo *dc,
+void creds_server_init(uint32 neg_flags,
+ struct dcinfo *dc,
DOM_CHAL *clnt_chal,
DOM_CHAL *srv_chal,
- const char mach_pw[16],
+ const unsigned char mach_pw[16],
DOM_CHAL *init_chal_out)
{
+ DEBUG(10,("creds_server_init: neg_flags : %x\n", (unsigned int)neg_flags));
DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) ));
DEBUG(10,("creds_server_init: server chal : %s\n", credstr(srv_chal->data) ));
- dump_data_pw("creds_server_init: machine pass", (const unsigned char *)mach_pw, 16);
-
- /* Just in case this isn't already there */
- memcpy(dc->mach_pw, mach_pw, 16);
-
- /* Generate the session key. */
- cred_create_session_key(clnt_chal, /* Stored client challenge. */
- srv_chal, /* Stored server challenge. */
- dc->mach_pw, /* input machine password. */
- dc->sess_key); /* output session key. */
+ dump_data_pw("creds_server_init: machine pass", mach_pw, 16);
+
+ /* Generate the session key and the next client and server creds. */
+ if (neg_flags & NETLOGON_NEG_128BIT) {
+ creds_init_128(dc,
+ clnt_chal,
+ srv_chal,
+ mach_pw);
+ } else {
+ creds_init_64(dc,
+ clnt_chal,
+ srv_chal,
+ mach_pw);
+ }
dump_data_pw("creds_server_init: session key", dc->sess_key, 16);
- /* Generate the next client and server creds. */
- cred_hash2(dc->clnt_chal.data, /* output */
- clnt_chal->data, /* input */
- dc->sess_key); /* input */
-
- cred_hash2(dc->srv_chal.data, /* output */
- srv_chal->data, /* input */
- dc->sess_key); /* input */
-
- /* Seed is the client chal. */
- memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
-
DEBUG(10,("creds_server_init: clnt : %s\n", credstr(dc->clnt_chal.data) ));
DEBUG(10,("creds_server_init: server : %s\n", credstr(dc->srv_chal.data) ));
DEBUG(10,("creds_server_init: seed : %s\n", credstr(dc->seed_chal.data) ));
@@ -185,24 +244,38 @@ static void creds_reseed(struct dcinfo *dc)
BOOL creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRED *cred_out)
{
- dc->sequence = received_cred->timestamp.time;
+ BOOL ret;
+ struct dcinfo tmp_dc = *dc;
- creds_step(dc);
+ /* Do all operations on a temporary copy of the dc,
+ which we throw away if the checks fail. */
+
+ tmp_dc.sequence = received_cred->timestamp.time;
+
+ creds_step(&tmp_dc);
/* Create the outgoing credentials */
- cred_out->timestamp.time = dc->sequence + 1;
- cred_out->challenge = dc->srv_chal;
+ cred_out->timestamp.time = tmp_dc.sequence + 1;
+ cred_out->challenge = tmp_dc.srv_chal;
- creds_reseed(dc);
+ creds_reseed(&tmp_dc);
+
+ ret = creds_server_check(&tmp_dc, &received_cred->challenge);
+ if (!ret) {
+ return False;
+ }
- return creds_server_check(dc, &received_cred->challenge);
+ /* creds step succeeded - replace the current creds. */
+ *dc = tmp_dc;
+ return True;
}
/****************************************************************************
Create a client credential struct.
****************************************************************************/
-void creds_client_init(struct dcinfo *dc,
+void creds_client_init(uint32 neg_flags,
+ struct dcinfo *dc,
DOM_CHAL *clnt_chal,
DOM_CHAL *srv_chal,
const unsigned char mach_pw[16],
@@ -210,33 +283,26 @@ void creds_client_init(struct dcinfo *dc,
{
dc->sequence = time(NULL);
+ DEBUG(10,("creds_client_init: neg_flags : %x\n", (unsigned int)neg_flags));
DEBUG(10,("creds_client_init: client chal : %s\n", credstr(clnt_chal->data) ));
DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) ));
dump_data_pw("creds_client_init: machine pass", (const unsigned char *)mach_pw, 16);
- /* Just in case this isn't already there */
- memcpy(dc->mach_pw, mach_pw, 16);
-
- /* Generate the session key. */
- cred_create_session_key(clnt_chal, /* Stored client challenge. */
- srv_chal, /* Stored server challenge. */
- dc->mach_pw, /* input machine password. */
- dc->sess_key); /* output session key. */
+ /* Generate the session key and the next client and server creds. */
+ if (neg_flags & NETLOGON_NEG_128BIT) {
+ creds_init_128(dc,
+ clnt_chal,
+ srv_chal,
+ mach_pw);
+ } else {
+ creds_init_64(dc,
+ clnt_chal,
+ srv_chal,
+ mach_pw);
+ }
dump_data_pw("creds_client_init: session key", dc->sess_key, 16);
- /* Generate the next client and server creds. */
- cred_hash2(dc->clnt_chal.data, /* output */
- clnt_chal->data, /* input */
- dc->sess_key); /* input */
-
- cred_hash2(dc->srv_chal.data, /* output */
- srv_chal->data, /* input */
- dc->sess_key); /* input */
-
- /* Seed is the client cred. */
- memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
-
DEBUG(10,("creds_client_init: clnt : %s\n", credstr(dc->clnt_chal.data) ));
DEBUG(10,("creds_client_init: server : %s\n", credstr(dc->srv_chal.data) ));
DEBUG(10,("creds_client_init: seed : %s\n", credstr(dc->seed_chal.data) ));
diff --git a/source/libsmb/dcerpc_err.c b/source/libsmb/dcerpc_err.c
new file mode 100644
index 00000000000..7121ba396dd
--- /dev/null
+++ b/source/libsmb/dcerpc_err.c
@@ -0,0 +1,55 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Copyright (C) Stefan 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"
+
+struct dcerpc_fault_table {
+ const char *errstr;
+ uint32_t faultcode;
+};
+
+static const struct dcerpc_fault_table dcerpc_faults[] =
+{
+ { "DCERPC_FAULT_OP_RNG_ERROR", DCERPC_FAULT_OP_RNG_ERROR },
+ { "DCERPC_FAULT_UNK_IF", DCERPC_FAULT_UNK_IF },
+ { "DCERPC_FAULT_NDR", DCERPC_FAULT_NDR },
+ { "DCERPC_FAULT_INVALID_TAG", DCERPC_FAULT_INVALID_TAG },
+ { "DCERPC_FAULT_CONTEXT_MISMATCH", DCERPC_FAULT_CONTEXT_MISMATCH },
+ { "DCERPC_FAULT_OTHER", DCERPC_FAULT_OTHER },
+ { "DCERPC_FAULT_ACCESS_DENIED", DCERPC_FAULT_ACCESS_DENIED },
+
+ { NULL, 0}
+};
+
+const char *dcerpc_errstr(uint32 fault_code)
+{
+ static pstring msg;
+ int idx = 0;
+
+ slprintf(msg, sizeof(msg), "DCERPC fault 0x%08x", fault_code);
+
+ while (dcerpc_faults[idx].errstr != NULL) {
+ if (dcerpc_faults[idx].faultcode == fault_code) {
+ return dcerpc_faults[idx].errstr;
+ }
+ idx++;
+ }
+
+ return msg;
+}
diff --git a/source/libsmb/errormap.c b/source/libsmb/errormap.c
index 3c0b13ad6ff..b3caa0a80ce 100644
--- a/source/libsmb/errormap.c
+++ b/source/libsmb/errormap.c
@@ -407,7 +407,7 @@ static const struct {
{ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE},
{ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED},
{ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE},
- {ERRDOS, 124, NT_STATUS_INVALID_LEVEL},
+ {ERRDOS, ERRunknownlevel, NT_STATUS_INVALID_LEVEL},
{ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE},
{ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
{ERRDOS, 109, NT_STATUS_PIPE_BROKEN},
@@ -680,7 +680,7 @@ static const struct {
{ERRDOS, 121, NT_STATUS_IO_TIMEOUT},
{ERRDOS, 122, NT_STATUS_BUFFER_TOO_SMALL},
{ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID},
- {ERRDOS, 124, NT_STATUS_INVALID_LEVEL},
+ {ERRDOS, ERRunknownlevel, NT_STATUS_INVALID_LEVEL},
{ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND},
{ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND},
{ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY},
@@ -1411,6 +1411,13 @@ static const struct {
{NT_STATUS(0x80000289), W_ERROR(0x48e)},
{NT_STATUS_OK, WERR_OK}};
+static const struct {
+ WERROR werror;
+ NTSTATUS ntstatus;
+} werror_to_ntstatus_map[] = {
+ { W_ERROR(0x5), NT_STATUS_ACCESS_DENIED },
+ { WERR_OK, NT_STATUS_OK }
+};
/*****************************************************************************
convert a dos eclas/ecode to a NT status32 code
@@ -1460,6 +1467,14 @@ NTSTATUS werror_to_ntstatus(WERROR error)
{
int i;
if (W_ERROR_IS_OK(error)) return NT_STATUS_OK;
+
+ for (i=0; !W_ERROR_IS_OK(werror_to_ntstatus_map[i].werror); i++) {
+ if (W_ERROR_V(error) ==
+ W_ERROR_V(werror_to_ntstatus_map[i].werror)) {
+ return werror_to_ntstatus_map[i].ntstatus;
+ }
+ }
+
for (i=0; NT_STATUS_V(ntstatus_to_werror_map[i].ntstatus); i++) {
if (W_ERROR_V(error) ==
W_ERROR_V(ntstatus_to_werror_map[i].werror)) {
diff --git a/source/libsmb/gpo.c b/source/libsmb/gpo.c
new file mode 100644
index 00000000000..0257138ece2
--- /dev/null
+++ b/source/libsmb/gpo.c
@@ -0,0 +1,167 @@
+/*
+ * 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 e6033faf50f..5d948ea5e25 100644
--- a/source/libsmb/libsmb_cache.c
+++ b/source/libsmb/libsmb_cache.c
@@ -94,6 +94,7 @@ static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * newsrv,
SAFE_FREE(srvcache->share_name);
SAFE_FREE(srvcache->workgroup);
SAFE_FREE(srvcache->username);
+ SAFE_FREE(srvcache);
return 1;
}
@@ -156,6 +157,21 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server,
continue;
}
+ /*
+ * Save the new share name. We've
+ * disconnected from the old share, and are
+ * about to connect to the new one.
+ */
+ SAFE_FREE(srv->share_name);
+ srv->share_name = SMB_STRDUP(share);
+ if (!srv->share_name) {
+ /* Out of memory. */
+ cli_shutdown(&srv->server->cli);
+ context->callbacks.remove_cached_srv_fn(context, srv->server);
+ continue;
+ }
+
+
return srv->server;
}
}
diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c
index 51f94e42e37..2436cc9136f 100644
--- a/source/libsmb/libsmbclient.c
+++ b/source/libsmb/libsmbclient.c
@@ -181,7 +181,8 @@ smbc_urldecode(char *dest, char * src, size_t max_dest_len)
*p = '\0';
- strncpy(dest, temp, max_dest_len);
+ strncpy(dest, temp, max_dest_len - 1);
+ dest[max_dest_len - 1] = '\0';
return err_count;
}
@@ -268,6 +269,7 @@ static const char *smbc_prefix = "smb:";
static int
smbc_parse_path(SMBCCTX *context,
const char *fname,
+ char *workgroup, int workgroup_len,
char *server, int server_len,
char *share, int share_len,
char *path, int path_len,
@@ -282,6 +284,16 @@ smbc_parse_path(SMBCCTX *context,
int len;
server[0] = share[0] = path[0] = user[0] = password[0] = (char)0;
+
+ /*
+ * Assume we wont find an authentication domain to parse, so default
+ * to the workgroup in the provided context.
+ */
+ if (workgroup != NULL) {
+ strncpy(workgroup, context->workgroup, workgroup_len - 1);
+ workgroup[workgroup_len - 1] = '\0';
+ }
+
if (options != NULL && options_len > 0) {
options[0] = (char)0;
}
@@ -328,6 +340,7 @@ smbc_parse_path(SMBCCTX *context,
((strlen(context->workgroup) < 16)
? strlen(context->workgroup)
: 16));
+ server[server_len - 1] = '\0';
return 0;
}
@@ -369,11 +382,20 @@ smbc_parse_path(SMBCCTX *context,
}
- if (username[0])
- strncpy(user, username, user_len); /* FIXME, domain */
+ if (domain[0] && workgroup) {
+ strncpy(workgroup, domain, workgroup_len - 1);
+ workgroup[workgroup_len - 1] = '\0';
+ }
- if (passwd[0])
- strncpy(password, passwd, password_len);
+ if (username[0]) {
+ strncpy(user, username, user_len - 1);
+ user[user_len - 1] = '\0';
+ }
+
+ if (passwd[0]) {
+ strncpy(password, passwd, password_len - 1);
+ password[password_len - 1] = '\0';
+ }
}
@@ -530,10 +552,21 @@ find_server(SMBCCTX *context,
workgroup, username);
if (!auth_called && !srv && (!username[0] || !password[0])) {
- context->callbacks.auth_fn(server, share,
- workgroup, sizeof(fstring),
- username, sizeof(fstring),
- password, sizeof(fstring));
+ if (context->internal->_auth_fn_with_context != NULL) {
+ context->internal->_auth_fn_with_context(
+ context,
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ } else {
+ context->callbacks.auth_fn(
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ }
+
/*
* However, smbc_auth_fn may have picked up info relating to
* an existing connection, so try for an existing connection
@@ -635,10 +668,20 @@ smbc_server(SMBCCTX *context,
*/
if (srv->cli.cnum == (uint16) -1) {
/* Ensure we have accurate auth info */
- context->callbacks.auth_fn(server, share,
- workgroup, sizeof(fstring),
- username, sizeof(fstring),
- password, sizeof(fstring));
+ if (context->internal->_auth_fn_with_context != NULL) {
+ context->internal->_auth_fn_with_context(
+ context,
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ } else {
+ context->callbacks.auth_fn(
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ }
if (! cli_send_tconX(&srv->cli, share, "?????",
password, strlen(password)+1)) {
@@ -879,10 +922,20 @@ smbc_attr_server(SMBCCTX *context,
/* We didn't find a cached connection. Get the password */
if (*password == '\0') {
/* ... then retrieve it now. */
- context->callbacks.auth_fn(server, share,
- workgroup, sizeof(fstring),
- username, sizeof(fstring),
- password, sizeof(fstring));
+ if (context->internal->_auth_fn_with_context != NULL) {
+ context->internal->_auth_fn_with_context(
+ context,
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ } else {
+ context->callbacks.auth_fn(
+ server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+ }
}
zero_ip(&ip);
@@ -1001,6 +1054,7 @@ smbc_open_ctx(SMBCCTX *context,
}
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -1013,8 +1067,6 @@ smbc_open_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -1049,6 +1101,7 @@ smbc_open_ctx(SMBCCTX *context,
if (!cli_resolve_path( "", &srv->cli, path, &targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
+ SAFE_FREE(file);
return NULL;
}
/*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
@@ -1178,7 +1231,7 @@ smbc_read_ctx(SMBCCTX *context,
* the call to cli_read() instead of file->offset fixes a problem
* retrieving data at an offset greater than 4GB.
*/
- off_t offset = file->offset;
+ off_t offset;
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -1197,6 +1250,8 @@ smbc_read_ctx(SMBCCTX *context,
}
+ offset = file->offset;
+
/* Check that the buffer exists ... */
if (buf == NULL) {
@@ -1208,6 +1263,7 @@ smbc_read_ctx(SMBCCTX *context,
/*d_printf(">>>read: parsing %s\n", file->fname);*/
if (smbc_parse_path(context, file->fname,
+ NULL, 0,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -1260,8 +1316,8 @@ smbc_write_ctx(SMBCCTX *context,
pstring path, targetpath;
struct cli_state *targetcli;
- offset = file->offset; /* See "offset" comment in smbc_read_ctx() */
-
+ /* First check all pointers before dereferencing them */
+
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -1286,8 +1342,11 @@ smbc_write_ctx(SMBCCTX *context,
}
+ offset = file->offset; /* See "offset" comment in smbc_read_ctx() */
+
/*d_printf(">>>write: parsing %s\n", file->fname);*/
if (smbc_parse_path(context, file->fname,
+ NULL, 0,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -1359,6 +1418,7 @@ smbc_close_ctx(SMBCCTX *context,
/*d_printf(">>>close: parsing %s\n", file->fname);*/
if (smbc_parse_path(context, file->fname,
+ NULL, 0,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -1499,39 +1559,6 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
int ret;
/*
- * Get the create time of the file (if not provided); we'll need it in
- * the set call.
- */
- if (! srv->no_pathinfo && c_time == 0) {
- if (! cli_qpathinfo(&srv->cli, path,
- &c_time, NULL, NULL, NULL, NULL)) {
- /* qpathinfo not available */
- srv->no_pathinfo = True;
- } else {
- /*
- * We got a creation time. Some OS versions don't
- * return a valid create time, though. If we got an
- * invalid time, start with the current time instead.
- */
- if (c_time == 0 || c_time == (time_t) -1) {
- c_time = time(NULL);
- }
-
- /*
- * We got a creation 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;
- }
- }
-
- /*
* First, try setpathinfo (if qpathinfo succeeded), for it is the
* modern function for "new code" to be using, and it works given a
* filename rather than requiring that the file be opened to have its
@@ -1645,6 +1672,7 @@ smbc_unlink_ctx(SMBCCTX *context,
}
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -1657,8 +1685,6 @@ smbc_unlink_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -1762,6 +1788,7 @@ smbc_rename_ctx(SMBCCTX *ocontext,
DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname));
smbc_parse_path(ocontext, oname,
+ workgroup, sizeof(workgroup),
server1, sizeof(server1),
share1, sizeof(share1),
path1, sizeof(path1),
@@ -1772,6 +1799,7 @@ smbc_rename_ctx(SMBCCTX *ocontext,
if (user1[0] == (char)0) fstrcpy(user1, ocontext->user);
smbc_parse_path(ncontext, nname,
+ NULL, 0,
server2, sizeof(server2),
share2, sizeof(share2),
path2, sizeof(path2),
@@ -1791,8 +1819,6 @@ smbc_rename_ctx(SMBCCTX *ocontext,
}
- fstrcpy(workgroup, ocontext->workgroup);
-
srv = smbc_server(ocontext, True,
server1, share1, workgroup, user1, password1);
if (!srv) {
@@ -1891,6 +1917,7 @@ smbc_lseek_ctx(SMBCCTX *context,
case SEEK_END:
/*d_printf(">>>lseek: parsing %s\n", file->fname);*/
if (smbc_parse_path(context, file->fname,
+ NULL, 0,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -2049,6 +2076,7 @@ smbc_stat_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_stat(%s)\n", fname));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -2061,8 +2089,6 @@ smbc_stat_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -2137,6 +2163,7 @@ smbc_fstat_ctx(SMBCCTX *context,
/*d_printf(">>>fstat: parsing %s\n", file->fname);*/
if (smbc_parse_path(context, file->fname,
+ NULL, 0,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -2270,8 +2297,12 @@ add_dirent(SMBCFILE *dir,
dirent->commentlen = comment_len;
dirent->dirlen = size;
+ /*
+ * dirent->namelen + 1 includes the null (no null termination needed)
+ * Ditto for dirent->commentlen.
+ * The space for the two null bytes was allocated.
+ */
strncpy(dirent->name, (name?name:""), dirent->namelen + 1);
-
dirent->comment = (char *)(&dirent->name + dirent->namelen + 1);
strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1);
@@ -2474,7 +2505,7 @@ done:
cli_rpc_pipe_close(pipe_hnd);
/* Free all memory which was allocated for this request */
- talloc_free(mem_ctx);
+ TALLOC_FREE(mem_ctx);
/* Tell 'em if it worked */
return W_ERROR_IS_OK(result) ? 0 : -1;
@@ -2510,6 +2541,7 @@ smbc_opendir_ctx(SMBCCTX *context,
}
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -2534,8 +2566,6 @@ smbc_opendir_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- pstrcpy(workgroup, context->workgroup);
-
dir = SMB_MALLOC_P(SMBCFILE);
if (!dir) {
@@ -2598,6 +2628,10 @@ smbc_opendir_ctx(SMBCCTX *context,
if (!find_master_ip(workgroup, &server_addr.ip)) {
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
+ }
errno = ENOENT;
return NULL;
}
@@ -2709,6 +2743,10 @@ smbc_opendir_ctx(SMBCCTX *context,
DEBUG(0, ("Could not get name of "
"local/domain master browser "
"for server %s\n", server));
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
+ }
errno = EPERM;
return NULL;
@@ -2832,6 +2870,10 @@ smbc_opendir_ctx(SMBCCTX *context,
&targetcli, targetpath))
{
d_printf("Could not resolve %s\n", path);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
+ }
return NULL;
}
@@ -2934,14 +2976,8 @@ smbc_readdir_internal(SMBCCTX * context,
dest->comment = dest->name + dest->namelen + 1;
/* Copy the comment */
- strncpy(dest->comment, src->comment, max_namebuf_len);
-
- /* Ensure the comment is null terminated */
- if (max_namebuf_len > src->commentlen) {
- dest->comment[src->commentlen] = '\0';
- } else {
- dest->comment[max_namebuf_len - 1] = '\0';
- }
+ strncpy(dest->comment, src->comment, max_namebuf_len - 1);
+ dest->comment[max_namebuf_len - 1] = '\0';
/* Save other fields */
dest->smbc_type = src->smbc_type;
@@ -3156,6 +3192,7 @@ smbc_mkdir_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_mkdir(%s)\n", fname));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -3168,8 +3205,6 @@ smbc_mkdir_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -3253,6 +3288,7 @@ smbc_rmdir_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_rmdir(%s)\n", fname));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -3266,8 +3302,6 @@ smbc_rmdir_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -3507,6 +3541,7 @@ smbc_chmod_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -3519,8 +3554,6 @@ smbc_chmod_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -3586,13 +3619,13 @@ smbc_utimes_ctx(SMBCCTX *context,
char atimebuf[32];
char mtimebuf[32];
- strncpy(atimebuf, ctime(&a_time), sizeof(atimebuf));
+ strncpy(atimebuf, ctime(&a_time), sizeof(atimebuf) - 1);
atimebuf[sizeof(atimebuf) - 1] = '\0';
if ((p = strchr(atimebuf, '\n')) != NULL) {
*p = '\0';
}
- strncpy(mtimebuf, ctime(&m_time), sizeof(mtimebuf));
+ strncpy(mtimebuf, ctime(&m_time), sizeof(mtimebuf) - 1);
mtimebuf[sizeof(mtimebuf) - 1] = '\0';
if ((p = strchr(mtimebuf, '\n')) != NULL) {
*p = '\0';
@@ -3603,6 +3636,7 @@ smbc_utimes_ctx(SMBCCTX *context,
}
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -3615,8 +3649,6 @@ smbc_utimes_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -3750,7 +3782,7 @@ convert_string_to_sid(struct cli_state *ipc_cli,
}
if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ipc_cli->mem_ctx,
- pol, 1, &str, &sids,
+ pol, 1, &str, NULL, &sids,
&types))) {
result = False;
goto done;
@@ -3921,7 +3953,7 @@ sec_desc_parse(TALLOC_CTX *ctx,
{
const char *p = str;
fstring tok;
- SEC_DESC *ret;
+ SEC_DESC *ret = NULL;
size_t sd_size;
DOM_SID *grp_sid=NULL;
DOM_SID *owner_sid=NULL;
@@ -3936,49 +3968,65 @@ sec_desc_parse(TALLOC_CTX *ctx,
}
if (StrnCaseCmp(tok,"OWNER:", 6) == 0) {
+ if (owner_sid) {
+ DEBUG(5, ("OWNER specified more than once!\n"));
+ goto done;
+ }
owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
if (!owner_sid ||
!convert_string_to_sid(ipc_cli, pol,
numeric,
owner_sid, tok+6)) {
DEBUG(5, ("Failed to parse owner sid\n"));
- return NULL;
+ goto done;
}
continue;
}
if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) {
+ if (owner_sid) {
+ DEBUG(5, ("OWNER specified more than once!\n"));
+ goto done;
+ }
owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
if (!owner_sid ||
!convert_string_to_sid(ipc_cli, pol,
False,
owner_sid, tok+7)) {
DEBUG(5, ("Failed to parse owner sid\n"));
- return NULL;
+ goto done;
}
continue;
}
if (StrnCaseCmp(tok,"GROUP:", 6) == 0) {
+ if (grp_sid) {
+ DEBUG(5, ("GROUP specified more than once!\n"));
+ goto done;
+ }
grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
if (!grp_sid ||
!convert_string_to_sid(ipc_cli, pol,
numeric,
grp_sid, tok+6)) {
DEBUG(5, ("Failed to parse group sid\n"));
- return NULL;
+ goto done;
}
continue;
}
if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) {
+ if (grp_sid) {
+ DEBUG(5, ("GROUP specified more than once!\n"));
+ goto done;
+ }
grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
if (!grp_sid ||
!convert_string_to_sid(ipc_cli, pol,
False,
grp_sid, tok+6)) {
DEBUG(5, ("Failed to parse group sid\n"));
- return NULL;
+ goto done;
}
continue;
}
@@ -3987,11 +4035,11 @@ sec_desc_parse(TALLOC_CTX *ctx,
SEC_ACE ace;
if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) {
DEBUG(5, ("Failed to parse ACL %s\n", tok));
- return NULL;
+ goto done;
}
if(!add_ace(&dacl, &ace, ctx)) {
DEBUG(5, ("Failed to add ACL %s\n", tok));
- return NULL;
+ goto done;
}
continue;
}
@@ -4000,22 +4048,23 @@ sec_desc_parse(TALLOC_CTX *ctx,
SEC_ACE ace;
if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) {
DEBUG(5, ("Failed to parse ACL %s\n", tok));
- return NULL;
+ goto done;
}
if(!add_ace(&dacl, &ace, ctx)) {
DEBUG(5, ("Failed to add ACL %s\n", tok));
- return NULL;
+ goto done;
}
continue;
}
DEBUG(5, ("Failed to parse security descriptor\n"));
- return NULL;
+ goto done;
}
ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE,
owner_sid, grp_sid, NULL, dacl, &sd_size);
+ done:
SAFE_FREE(grp_sid);
SAFE_FREE(owner_sid);
@@ -4808,11 +4857,19 @@ cacl_set(TALLOC_CTX *ctx,
CONST_DISCARD(char *, the_acl));
if (!sd) {
- errno = EINVAL;
- return -1;
+ errno = EINVAL;
+ return -1;
}
}
+ /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller
+ that doesn't deref sd */
+
+ if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
/* The desired access below is the only one I could find that works
with NT4, W2KP and Samba */
@@ -4999,6 +5056,7 @@ smbc_setxattr_ctx(SMBCCTX *context,
fname, name, (int) size, (const char*)value));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -5011,8 +5069,6 @@ smbc_setxattr_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
if (!srv) {
@@ -5267,6 +5323,7 @@ smbc_getxattr_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_getxattr(%s, %s)\n", fname, name));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -5279,8 +5336,6 @@ smbc_getxattr_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
if (!srv) {
@@ -5384,6 +5439,7 @@ smbc_removexattr_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_removexattr(%s, %s)\n", fname, name));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -5396,8 +5452,6 @@ smbc_removexattr_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
if (!srv) {
@@ -5539,6 +5593,7 @@ smbc_open_print_job_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_open_print_job_ctx(%s)\n", fname));
if (smbc_parse_path(context, fname,
+ NULL, 0,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -5676,6 +5731,7 @@ smbc_list_print_jobs_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -5688,8 +5744,6 @@ smbc_list_print_jobs_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -5747,6 +5801,7 @@ smbc_unlink_print_job_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname));
if (smbc_parse_path(context, fname,
+ workgroup, sizeof(workgroup),
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
@@ -5759,8 +5814,6 @@ smbc_unlink_print_job_ctx(SMBCCTX *context,
if (user[0] == (char)0) fstrcpy(user, context->user);
- fstrcpy(workgroup, context->workgroup);
-
srv = smbc_server(context, True,
server, share, workgroup, user, password);
@@ -5802,6 +5855,7 @@ smbc_new_context(void)
context->internal = SMB_MALLOC_P(struct smbc_internal_data);
if (!context->internal) {
+ SAFE_FREE(context);
errno = ENOMEM;
return NULL;
}
@@ -5947,22 +6001,57 @@ smbc_free_context(SMBCCTX *context,
void
smbc_option_set(SMBCCTX *context,
char *option_name,
- ...)
+ void *option_value)
{
- va_list args;
+ if (strcmp(option_name, "debug_stderr") == 0) {
+ /*
+ * Log to standard error instead of standard output.
+ */
+ context->internal->_debug_stderr =
+ (option_value == NULL ? False : True);
+ } 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;
+ } 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;
+ }
+}
- va_start(args, option_name);
+/*
+ * Retrieve the current value of an option
+ */
+void *
+smbc_option_get(SMBCCTX *context,
+ char *option_name)
+{
if (strcmp(option_name, "debug_stderr") == 0) {
/*
* Log to standard error instead of standard output.
- *
- * optional parameters: none (it can't be turned off once on)
*/
- context->internal->_debug_stderr = True;
+ return (void *) context->internal->_debug_stderr;
+ } else if (strcmp(option_name, "auth_function") == 0) {
+ /*
+ * Use the new-style authentication function which includes
+ * the context.
+ */
+ return (void *) context->internal->_auth_fn_with_context;
+ } else if (strcmp(option_name, "user_data") == 0) {
+ /*
+ * Save a user data handle which may be retrieved by the user
+ * with smbc_option_get()
+ */
+ return context->internal->_user_data;
}
- va_end(args);
+ return NULL;
}
@@ -5991,7 +6080,8 @@ smbc_init_context(SMBCCTX *context)
return 0;
}
- if (!context->callbacks.auth_fn ||
+ if ((!context->callbacks.auth_fn &&
+ !context->internal->_auth_fn_with_context) ||
context->debug < 0 ||
context->debug > 100) {
@@ -6025,7 +6115,7 @@ smbc_init_context(SMBCCTX *context)
home = getenv("HOME");
if (home) {
slprintf(conf, sizeof(conf), "%s/.smb/smb.conf", home);
- if (lp_load(conf, True, False, False)) {
+ if (lp_load(conf, True, False, False, True)) {
conf_loaded = True;
} else {
DEBUG(5, ("Could not load config file: %s\n",
@@ -6041,7 +6131,7 @@ smbc_init_context(SMBCCTX *context)
* defaults ...
*/
- if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
+ if (!lp_load(dyn_CONFIGFILE, True, False, False, False)) {
DEBUG(5, ("Could not load config file: %s\n",
dyn_CONFIGFILE));
} else if (home) {
@@ -6052,7 +6142,7 @@ smbc_init_context(SMBCCTX *context)
*/
slprintf(conf, sizeof(conf),
"%s/.smb/smb.conf.append", home);
- if (!lp_load(conf, True, False, False)) {
+ if (!lp_load(conf, True, False, False, False)) {
DEBUG(10,
("Could not append config file: "
"%s\n",
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 28b89db9087..1d40837f2bd 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -24,6 +24,94 @@
/* nmbd.c sets this to True. */
BOOL global_in_nmbd = False;
+
+/****************************
+ * SERVER AFFINITY ROUTINES *
+ ****************************/
+
+ /* Server affinity is the concept of preferring the last domain
+ controller with whom you had a successful conversation */
+
+/****************************************************************************
+****************************************************************************/
+#define SAFKEY_FMT "SAF/DOMAIN/%s"
+#define SAF_TTL 900
+
+static char *saf_key(const char *domain)
+{
+ char *keystr;
+
+ asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
+
+ return keystr;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+BOOL saf_store( const char *domain, const char *servername )
+{
+ char *key;
+ time_t expire;
+ BOOL ret = False;
+
+ if ( !domain || !servername ) {
+ DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
+ return False;
+ }
+
+ if ( !gencache_init() )
+ return False;
+
+ key = saf_key( domain );
+ expire = time( NULL ) + SAF_TTL;
+
+
+ DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%u]\n",
+ domain, servername, (unsigned int)expire ));
+
+ ret = gencache_set( key, servername, expire );
+
+ SAFE_FREE( key );
+
+ return ret;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+char *saf_fetch( const char *domain )
+{
+ char *server = NULL;
+ time_t timeout;
+ BOOL ret = False;
+ char *key = NULL;
+
+ if ( !domain ) {
+ DEBUG(2,("saf_fetch: Empty domain name!\n"));
+ return NULL;
+ }
+
+ if ( !gencache_init() )
+ return False;
+
+ key = saf_key( domain );
+
+ ret = gencache_get( key, &server, &timeout );
+
+ SAFE_FREE( key );
+
+ if ( !ret ) {
+ DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n", domain ));
+ } else {
+ DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n",
+ server, domain ));
+ }
+
+ return server;
+}
+
+
/****************************************************************************
Generate a random trn_id.
****************************************************************************/
@@ -413,7 +501,6 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
while (1) {
struct timeval tval2;
- struct in_addr *tmp_ip_list;
GetTimeOfDay(&tval2);
if (TvalDiff(&tval,&tval2) > retry_time) {
@@ -478,25 +565,22 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
continue;
}
- tmp_ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,
+ ip_list = SMB_REALLOC_ARRAY( ip_list, struct in_addr,
(*count) + nmb2->answers->rdlength/6 );
- if (!tmp_ip_list) {
+ if (!ip_list) {
DEBUG(0,("name_query: Realloc failed.\n"));
- SAFE_FREE(ip_list);
+ free_packet(p2);
+ return( NULL );
}
- ip_list = tmp_ip_list;
-
- if (ip_list) {
- DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
- for (i=0;i<nmb2->answers->rdlength/6;i++) {
- putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
- DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
- (*count)++;
- }
- DEBUGADD(2,(")\n"));
+ DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
+ for (i=0;i<nmb2->answers->rdlength/6;i++) {
+ putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
+ DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
+ (*count)++;
}
+ DEBUGADD(2,(")\n"));
found=True;
retries=0;
@@ -872,6 +956,7 @@ static BOOL resolve_lmhosts(const char *name, int name_type,
(*return_count)+1);
if ((*return_iplist) == NULL) {
+ endlmhosts(fp);
DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
return False;
}
@@ -1041,6 +1126,7 @@ BOOL internal_resolve_name(const char *name, int name_type,
/* if it's in the form of an IP address then get the lib to interpret it */
if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){
DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name));
+ SAFE_FREE(*return_iplist);
return False;
}
} else {
@@ -1261,6 +1347,18 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
int *count, BOOL ads_only, int *ordered)
{
fstring resolve_order;
+ char *saf_servername;
+ pstring pserver;
+ const char *p;
+ char *port_str;
+ int port;
+ fstring name;
+ int num_addresses = 0;
+ int local_count, i, j;
+ struct ip_service *return_iplist = NULL;
+ struct ip_service *auto_ip_list = NULL;
+ BOOL done_auto_lookup = False;
+ int auto_count = 0;
/* if we are restricted to solely using DNS for looking
up a domain controller, make sure that host lookups
@@ -1277,148 +1375,145 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list,
fstrcpy( resolve_order, "NULL" );
}
-
*ordered = False;
-
- /* If it's our domain then use the 'password server' parameter. */
-
+
+ /* fetch the server we have affinity for. Add the
+ 'password server' list to a search for our domain controllers */
+
+ saf_servername = saf_fetch( domain );
+
if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
- const char *p;
- char *pserver = lp_passwordserver(); /* UNIX charset. */
- char *port_str;
- int port;
- fstring name;
- int num_addresses = 0;
- int local_count, i, j;
- struct ip_service *return_iplist = NULL;
- struct ip_service *auto_ip_list = NULL;
- BOOL done_auto_lookup = False;
- int auto_count = 0;
-
+ pstr_sprintf( pserver, "%s, %s",
+ saf_servername ? saf_servername : "",
+ lp_passwordserver() );
+ } else {
+ pstr_sprintf( pserver, "%s, *",
+ saf_servername ? saf_servername : "" );
+ }
- if (!*pserver)
- return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
+ SAFE_FREE( saf_servername );
- p = pserver;
-
- /*
- * if '*' appears in the "password server" list then add
- * an auto lookup to the list of manually configured
- * DC's. If any DC is listed by name, then the list should be
- * considered to be ordered
- */
-
- 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) )
- num_addresses += auto_count;
- done_auto_lookup = True;
- DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
- } else {
- num_addresses++;
- }
+ /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
+
+ if ( !*pserver ) {
+ DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
+ return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
+ }
+
+ DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
+
+ /*
+ * if '*' appears in the "password server" list then add
+ * an auto lookup to the list of manually configured
+ * DC's. If any DC is listed by name, then the list should be
+ * considered to be ordered
+ */
+
+ 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) )
+ num_addresses += auto_count;
+ done_auto_lookup = True;
+ DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count));
+ } else {
+ num_addresses++;
}
+ }
- /* if we have no addresses and haven't done the auto lookup, then
- just return the list of DC's */
+ /* if we have no addresses and haven't done the auto lookup, then
+ just return the list of DC's. Or maybe we just failed. */
- if ( (num_addresses == 0) && !done_auto_lookup ) {
+ if ( (num_addresses == 0) ) {
+ if ( !done_auto_lookup ) {
return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
- }
-
- /* maybe we just failed? */
-
- if ( num_addresses == 0 ) {
- DEBUG(4,("get_dc_list: no servers found\n"));
- return False;
- }
-
- if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
- DEBUG(3,("get_dc_list: malloc fail !\n"));
+ } else {
+ DEBUG(4,("get_dc_list: no servers found\n"));
return False;
}
+ }
+
+ if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
+ DEBUG(3,("get_dc_list: malloc fail !\n"));
+ return False;
+ }
- p = pserver;
- local_count = 0;
+ p = pserver;
+ local_count = 0;
- /* fill in the return list now with real IP's */
+ /* fill in the return list now with real IP's */
- while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
- struct in_addr name_ip;
+ while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) {
+ struct in_addr name_ip;
- /* copy any addersses from the auto lookup */
+ /* copy any addersses from the auto lookup */
- if ( strequal(name, "*") ) {
- for ( j=0; j<auto_count; j++ ) {
- /* Check for and don't copy any known bad DC IP's. */
- if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain,
- inet_ntoa(auto_ip_list[j].ip)))) {
- DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
- inet_ntoa(auto_ip_list[j].ip) ));
- continue;
- }
- return_iplist[local_count].ip = auto_ip_list[j].ip;
- return_iplist[local_count].port = auto_ip_list[j].port;
- local_count++;
+ if ( strequal(name, "*") ) {
+ for ( j=0; j<auto_count; j++ ) {
+ /* Check for and don't copy any known bad DC IP's. */
+ if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain,
+ inet_ntoa(auto_ip_list[j].ip)))) {
+ DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",
+ inet_ntoa(auto_ip_list[j].ip) ));
+ continue;
}
- continue;
+ return_iplist[local_count].ip = auto_ip_list[j].ip;
+ return_iplist[local_count].port = auto_ip_list[j].port;
+ local_count++;
}
+ continue;
+ }
- /* added support for address:port syntax for ads (not that I think
- anyone will ever run the LDAP server in an AD domain on something
- other than port 389 */
+ /* added support for address:port syntax for ads (not that I think
+ anyone will ever run the LDAP server in an AD domain on something
+ other than port 389 */
- port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
- if ( (port_str=strchr(name, ':')) != NULL ) {
- *port_str = '\0';
- port_str++;
- port = atoi( port_str );
- }
-
- /* explicit lookup; resolve_name() will handle names & IP addresses */
- if ( resolve_name( name, &name_ip, 0x20 ) ) {
+ port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE;
+ if ( (port_str=strchr(name, ':')) != NULL ) {
+ *port_str = '\0';
+ port_str++;
+ port = atoi( port_str );
+ }
- /* Check for and don't copy any known bad DC IP's. */
- if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
- DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
- continue;
- }
+ /* explicit lookup; resolve_name() will handle names & IP addresses */
+ if ( resolve_name( name, &name_ip, 0x20 ) ) {
- return_iplist[local_count].ip = name_ip;
- return_iplist[local_count].port = port;
- local_count++;
- *ordered = True;
+ /* Check for and don't copy any known bad DC IP's. */
+ if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) {
+ DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name ));
+ continue;
}
+
+ return_iplist[local_count].ip = name_ip;
+ return_iplist[local_count].port = port;
+ local_count++;
+ *ordered = True;
}
+ }
- SAFE_FREE(auto_ip_list);
+ SAFE_FREE(auto_ip_list);
- /* need to remove duplicates in the list if we have any
- explicit password servers */
-
- if ( local_count ) {
- local_count = remove_duplicate_addrs2( return_iplist, local_count );
- }
+ /* need to remove duplicates in the list if we have any
+ explicit password servers */
+
+ if ( local_count ) {
+ local_count = remove_duplicate_addrs2( return_iplist, local_count );
+ }
- if ( DEBUGLEVEL >= 4 ) {
- DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count,
- *ordered ? "":"un"));
- DEBUG(4,("get_dc_list: "));
- for ( i=0; i<local_count; i++ )
- DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port ));
- DEBUGADD(4,("\n"));
- }
+ if ( DEBUGLEVEL >= 4 ) {
+ DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count,
+ *ordered ? "":"un"));
+ DEBUG(4,("get_dc_list: "));
+ for ( i=0; i<local_count; i++ )
+ DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port ));
+ DEBUGADD(4,("\n"));
+ }
- *ip_list = return_iplist;
- *count = local_count;
+ *ip_list = return_iplist;
+ *count = local_count;
- return (*count != 0);
- }
-
- DEBUG(10,("get_dc_list: defaulting to internal auto lookup for domain %s\n", domain));
-
- return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order);
+ return (*count != 0);
}
/*********************************************************************
diff --git a/source/libsmb/namequery_dc.c b/source/libsmb/namequery_dc.c
index 0c9f19313cb..b9a593bf2a7 100644
--- a/source/libsmb/namequery_dc.c
+++ b/source/libsmb/namequery_dc.c
@@ -75,31 +75,10 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip
struct ip_service *ip_list = NULL;
struct in_addr dc_ip, exclude_ip;
int count, i;
- BOOL use_pdc_only;
NTSTATUS result;
zero_ip(&exclude_ip);
- use_pdc_only = must_use_pdc(domain);
-
- /* Lookup domain controller name */
-
- if ( use_pdc_only && get_pdc_ip(domain, &dc_ip) )
- {
- DEBUG(10,("rpc_dc_name: Atempting to lookup PDC to avoid sam sync delays\n"));
-
- /* check the connection cache and perform the node status
- lookup only if the IP is not found to be bad */
-
- if (name_status_find(domain, 0x1b, 0x20, dc_ip, srv_name) ) {
- result = check_negative_conn_cache( domain, srv_name );
- if ( NT_STATUS_IS_OK(result) )
- goto done;
- }
- /* Didn't get name, remember not to talk to this DC. */
- exclude_ip = dc_ip;
- }
-
/* get a list of all domain controllers */
if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) {
@@ -109,13 +88,6 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip
/* Remove the entry we've already failed with (should be the PDC). */
- if ( use_pdc_only ) {
- for (i = 0; i < count; i++) {
- if (ip_equal( exclude_ip, ip_list[i].ip))
- zero_ip(&ip_list[i].ip);
- }
- }
-
for (i = 0; i < count; i++) {
if (is_zero_ip(ip_list[i].ip))
continue;
diff --git a/source/libsmb/nterr.c b/source/libsmb/nterr.c
index 677c5d84c73..4f97379ee07 100644
--- a/source/libsmb/nterr.c
+++ b/source/libsmb/nterr.c
@@ -541,6 +541,8 @@ static nt_err_code_struct nt_errs[] =
{ NULL, NT_STATUS(0) }
};
+/* These need sorting..... */
+
nt_err_code_struct nt_err_desc[] =
{
{ "Success", NT_STATUS_OK },
@@ -595,6 +597,8 @@ nt_err_code_struct nt_err_desc[] =
{ "Duplicate name on network", NT_STATUS_DUPLICATE_NAME },
{ "Print queue is full", NT_STATUS_PRINT_QUEUE_FULL },
{ "No print spool space available", NT_STATUS_NO_SPOOL_SPACE },
+ { "The network name cannot be found", NT_STATUS_BAD_NETWORK_NAME },
+ { "The connection was refused", NT_STATUS_CONNECTION_REFUSED },
{ "Too many names", NT_STATUS_TOO_MANY_NAMES },
{ "Too many sessions", NT_STATUS_TOO_MANY_SESSIONS },
{ "Invalid server state", NT_STATUS_INVALID_SERVER_STATE },
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index e1ef69aed99..986fa8cce9f 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -363,9 +363,6 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) {
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
- if (neg_flags & NTLMSSP_NEGOTIATE_56) {
- ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;
- }
}
if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) {
@@ -376,10 +373,23 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
}
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
+ }
+
+ if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL;
+ }
+
+ /* Woop Woop - unknown flag for Windows compatibility...
+ What does this really do ? JRA. */
+ if (!(neg_flags & NTLMSSP_UNKNOWN_02000000)) {
+ ntlmssp_state->neg_flags &= ~NTLMSSP_UNKNOWN_02000000;
+ }
+
if ((neg_flags & NTLMSSP_REQUEST_TARGET)) {
ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;
}
-
}
/**
@@ -840,6 +850,8 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
+ NTLMSSP_NEGOTIATE_56 |
+ NTLMSSP_UNKNOWN_02000000 |
NTLMSSP_NEGOTIATE_NTLM |
NTLMSSP_NEGOTIATE_NTLM2 |
NTLMSSP_NEGOTIATE_KEY_EXCH |
diff --git a/source/libsmb/ntlmssp_sign.c b/source/libsmb/ntlmssp_sign.c
index 42ed0f94184..10921d56e71 100644
--- a/source/libsmb/ntlmssp_sign.c
+++ b/source/libsmb/ntlmssp_sign.c
@@ -339,7 +339,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
debug_ntlmssp_flags(ntlmssp_state->neg_flags);
if (ntlmssp_state->session_key.length < 8) {
- talloc_free(mem_ctx);
+ TALLOC_FREE(mem_ctx);
DEBUG(3, ("NO session key, cannot intialise signing\n"));
return NT_STATUS_NO_USER_SESSION_KEY;
}
@@ -365,7 +365,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
recv_seal_const = CLI_SEAL;
break;
default:
- talloc_free(mem_ctx);
+ TALLOC_FREE(mem_ctx);
return NT_STATUS_INTERNAL_ERROR;
}
@@ -464,6 +464,6 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
ntlmssp_state->ntlmv1_seq_num = 0;
}
- talloc_free(mem_ctx);
+ TALLOC_FREE(mem_ctx);
return NT_STATUS_OK;
}
diff --git a/source/libsmb/passchange.c b/source/libsmb/passchange.c
index 8b811b06ead..673671d28db 100644
--- a/source/libsmb/passchange.c
+++ b/source/libsmb/passchange.c
@@ -24,7 +24,7 @@
Change a password on a remote machine using IPC calls.
*************************************************************/
-BOOL remote_password_change(const char *remote_machine, const char *user_name,
+NTSTATUS remote_password_change(const char *remote_machine, const char *user_name,
const char *old_passwd, const char *new_passwd,
char *err_str, size_t err_str_len)
{
@@ -41,7 +41,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
if(!resolve_name( remote_machine, &ip, 0x20)) {
slprintf(err_str, err_str_len-1, "unable to find an IP address for machine %s.\n",
remote_machine );
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
ZERO_STRUCT(cli);
@@ -49,7 +49,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
if (!cli_initialise(&cli) || !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 False;
+ return NT_STATUS_UNSUCCESSFUL;
}
make_nmb_name(&calling, global_myname() , 0x0);
@@ -59,7 +59,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
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 False;
+ return NT_STATUS_UNSUCCESSFUL;
}
cli.protocol = PROTOCOL_NT1;
@@ -67,8 +67,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
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);
- return False;
+ return result;
}
/* Given things like SMB signing, restrict anonymous and the like,
@@ -90,7 +91,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
"connect to machine %s: %s\n",
remote_machine, cli_errstr(&cli));
cli_shutdown(&cli);
- return False;
+ return result;
}
pass_must_change = True;
@@ -105,8 +106,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
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);
- return False;
+ return result;
}
cli_init_creds(&cli, "", "", NULL);
@@ -117,8 +119,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
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);
- return False;
+ return result;
}
/* Try not to give the password away too easily */
@@ -149,16 +152,18 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
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);
- return False;
+ 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);
+ result = cli_nt_error(&cli);
cli_shutdown(&cli);
- return False;
+ return result;
}
}
@@ -166,7 +171,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
new_passwd, old_passwd))) {
/* Great - it all worked! */
cli_shutdown(&cli);
- return True;
+ return NT_STATUS_OK;
} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)
|| NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
@@ -175,7 +180,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
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);
- return False;
+ return result;
}
/* OK, that failed, so try again... */
@@ -197,7 +202,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
old_passwd)))) {
/* Great - it all worked! */
cli_shutdown(&cli);
- return True;
+ return NT_STATUS_OK;
} else {
if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)
|| NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
@@ -207,7 +212,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
"machine %s rejected the (anonymous) password change: Error was : %s.\n",
remote_machine, get_friendly_nt_error_msg(result));
cli_shutdown(&cli);
- return False;
+ return result;
}
/* We have failed to change the user's password, and we think the server
@@ -219,20 +224,21 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
/* SAMR failed, but the old LanMan protocol worked! */
cli_shutdown(&cli);
- return True;
+ 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);
- return False;
+ 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);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
}
diff --git a/source/libsmb/samlogon_cache.c b/source/libsmb/samlogon_cache.c
index ef60055cf47..cc1c6bd6b24 100644
--- a/source/libsmb/samlogon_cache.c
+++ b/source/libsmb/samlogon_cache.c
@@ -208,6 +208,7 @@ NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, const DOM_SID *user
if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) {
prs_mem_free( &ps );
+ SAFE_FREE(user);
return False;
}
diff --git a/source/libsmb/smb_share_modes.c b/source/libsmb/smb_share_modes.c
index 43f25cd3787..090571b8107 100644
--- a/source/libsmb/smb_share_modes.c
+++ b/source/libsmb/smb_share_modes.c
@@ -2,7 +2,7 @@
Samba share mode database library external interface library.
Used by non-Samba products needing access to the Samba share mode db.
- Copyright (C) Jeremy Allison 2005.
+ Copyright (C) Jeremy Allison 2005 - 2006
sharemodes_procid functions (C) Copyright (C) Volker Lendecke 2005
@@ -115,28 +115,12 @@ int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
return tdb_chainunlock(db_ctx->smb_tdb, get_locking_key(dev, ino));
}
-/* Internal structure of Samba share mode db. */
-/* FIXME ! This should be moved into a Samba include file. */
-
-struct locking_data {
- union {
- struct {
- int num_share_mode_entries;
- BOOL delete_on_close;
- } s;
- struct share_mode_entry dummy; /* Needed for alignment. */
- } u;
- /* the following two entries are implicit
- struct share_mode_entry modes[num_share_mode_entries];
- char file_name[];
- */
-};
-
/*
* Check if an external smb_share_mode_entry and an internal share_mode entry match.
*/
-static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const struct share_mode_entry *entry)
+static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry,
+ const struct share_mode_entry *entry)
{
return (sharemodes_procid_equal(&e_entry->pid, &entry->pid) &&
e_entry->file_id == (uint32_t)entry->share_file_id &&
@@ -152,7 +136,8 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, co
* Create an internal Samba share_mode entry from an external smb_share_mode_entry.
*/
-static void create_share_mode_entry(struct share_mode_entry *out, const struct smb_share_mode_entry *in)
+static void create_share_mode_entry(struct share_mode_entry *out,
+ const struct smb_share_mode_entry *in)
{
memset(out, '\0', sizeof(struct share_mode_entry));
@@ -280,8 +265,11 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
return -1;
}
ld = (struct locking_data *)db_data.dptr;
+ 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);
@@ -326,7 +314,7 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
ld = (struct locking_data *)new_data_p;
ld->u.s.num_share_mode_entries++;
- /* Append the original filename */
+ /* Append the original delete_token and filenames. */
memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(struct share_mode_entry)),
db_data.dptr + ((orig_num_share_modes+1)*sizeof(struct share_mode_entry)),
db_data.dsize - ((orig_num_share_modes+1) * sizeof(struct share_mode_entry)));
@@ -376,9 +364,9 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
struct locking_data *ld = NULL; /* internal samba db state. */
struct share_mode_entry *shares = NULL;
char *new_data_p = NULL;
- size_t filename_size = 0;
+ size_t remaining_size = 0;
size_t i, num_share_modes;
- const char *fname_ptr = NULL;
+ const char *remaining_ptr = NULL;
db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
if (!db_data.dptr) {
@@ -438,13 +426,13 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
return tdb_delete(db_ctx->smb_tdb, locking_key);
}
- /* Copy the terminating filename. */
- fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(struct share_mode_entry));
- filename_size = db_data.dsize - (fname_ptr - db_data.dptr);
+ /* Copy any delete token plus the terminating filenames. */
+ remaining_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(struct share_mode_entry));
+ remaining_size = db_data.dsize - (remaining_ptr - db_data.dptr);
memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)),
- fname_ptr,
- filename_size);
+ remaining_ptr,
+ remaining_size);
free(db_data.dptr);
@@ -454,7 +442,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
ld = (struct locking_data *)db_data.dptr;
ld->u.s.num_share_mode_entries = num_share_modes;
- db_data.dsize = ((num_share_modes+1)*sizeof(struct share_mode_entry)) + filename_size;
+ db_data.dsize = ((num_share_modes+1)*sizeof(struct share_mode_entry)) + remaining_size;
if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {
free(db_data.dptr);
diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c
index f0f2024e7b9..4ff74ca464c 100644
--- a/source/libsmb/smb_signing.c
+++ b/source/libsmb/smb_signing.c
@@ -28,17 +28,9 @@ struct outstanding_packet_lookup {
struct outstanding_packet_lookup *prev, *next;
};
-/* Store the data for an ongoing trans/trans2/nttrans operation. */
-struct trans_info_context {
- uint16 mid;
- uint32 send_seq_num;
- uint32 reply_seq_num;
-};
-
struct smb_basic_signing_context {
DATA_BLOB mac_key;
uint32 send_seq_num;
- struct trans_info_context *trans_info;
struct outstanding_packet_lookup *outstanding_packet_list;
};
@@ -315,7 +307,6 @@ 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;
- uint32 send_seq_num;
if (!si->doing_signing)
return;
@@ -330,12 +321,8 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
/* mark the packet as signed - BEFORE we sign it...*/
mark_packet_signed(outbuf);
- if (data->trans_info)
- send_seq_num = data->trans_info->send_seq_num;
- else
- send_seq_num = data->send_seq_num;
-
- simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
+ simple_packet_signature(data, (const unsigned char *)outbuf,
+ data->send_seq_num, calc_md5_mac);
DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
dump_data(10, (const char *)calc_md5_mac, 8);
@@ -345,13 +332,7 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
/* cli->outbuf[smb_ss_field+2]=0;
Uncomment this to test if the remote server actually verifies signatures...*/
- if (data->trans_info)
- return;
-
- data->send_seq_num++;
- store_sequence_for_reply(&data->outstanding_packet_list,
- SVAL(outbuf,smb_mid), data->send_seq_num);
- data->send_seq_num++;
+ data->send_seq_num += 2;
}
/***********************************************************
@@ -362,7 +343,6 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
{
BOOL good;
uint32 reply_seq_number;
- uint32 saved_seq;
unsigned char calc_md5_mac[16];
unsigned char *server_sent_mac;
@@ -376,17 +356,9 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
return False;
}
- if (data->trans_info) {
- reply_seq_number = data->trans_info->reply_seq_num;
- } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
- SVAL(inbuf, smb_mid), &reply_seq_number)) {
- DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
- (unsigned int) SVAL(inbuf, smb_mid) ));
- return False;
- }
-
- saved_seq = reply_seq_number;
- simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
+ reply_seq_number = data->send_seq_num - 1;
+ simple_packet_signature(data, (const unsigned char *)inbuf,
+ reply_seq_number, calc_md5_mac);
server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
@@ -400,12 +372,11 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si,
#if 1 /* JRATEST */
{
int i;
- reply_seq_number -= 5;
- for (i = 0; i < 10; i++, reply_seq_number++) {
- simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
+ for (i = -5; i < 5; i++) {
+ simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number+i, calc_md5_mac);
if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
-We were expecting seq %u\n", reply_seq_number, saved_seq ));
+We were expecting seq %u\n", reply_seq_number+i, reply_seq_number ));
break;
}
}
@@ -416,7 +387,7 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
dump_data(10, (const char *)server_sent_mac, 8);
}
- return signing_good(inbuf, si, good, saved_seq, must_be_ok);
+ return signing_good(inbuf, si, good, reply_seq_number, must_be_ok);
}
/***********************************************************
@@ -426,19 +397,17 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
static void simple_free_signing_context(struct smb_sign_info *si)
{
struct smb_basic_signing_context *data = si->signing_context;
- struct outstanding_packet_lookup *list = data->outstanding_packet_list;
+ struct outstanding_packet_lookup *list;
+ struct outstanding_packet_lookup *next;
- while (list) {
- struct outstanding_packet_lookup *old_head = list;
- DLIST_REMOVE(list, list);
- SAFE_FREE(old_head);
+ for (list = data->outstanding_packet_list; list; list = next) {
+ next = list->next;
+ DLIST_REMOVE(data->outstanding_packet_list, list);
+ SAFE_FREE(list);
}
data_blob_free(&data->mac_key);
- if (data->trans_info)
- SAFE_FREE(data->trans_info);
-
SAFE_FREE(si->signing_context);
return;
@@ -501,65 +470,6 @@ BOOL cli_simple_set_signing(struct cli_state *cli,
}
/***********************************************************
- Tell client code we are in a multiple trans reply state.
- We call this after the last outgoing trans2 packet (which
- has incremented the sequence numbers), so we must save the
- current mid and sequence number -2.
-************************************************************/
-
-void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
-{
- struct smb_basic_signing_context *data = cli->sign_info.signing_context;
- uint32 reply_seq_num;
-
- if (!cli->sign_info.doing_signing || !data)
- return;
-
- data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
- ZERO_STRUCTP(data->trans_info);
-
- /* This ensures the sequence is pulled off the outstanding packet list */
- if (!get_sequence_for_reply(&data->outstanding_packet_list,
- mid, &reply_seq_num)) {
- DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
- return;
- }
-
- data->trans_info->send_seq_num = reply_seq_num - 1;
- data->trans_info->mid = mid;
- data->trans_info->reply_seq_num = reply_seq_num;
-
- DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
-data->send_seq_num = %u\n",
- (unsigned int)data->trans_info->mid,
- (unsigned int)data->trans_info->reply_seq_num,
- (unsigned int)data->trans_info->send_seq_num,
- (unsigned int)data->send_seq_num ));
-}
-
-/***********************************************************
- Tell client code we are out of a multiple trans reply state.
-************************************************************/
-
-void cli_signing_trans_stop(struct cli_state *cli)
-{
- struct smb_basic_signing_context *data = cli->sign_info.signing_context;
-
- if (!cli->sign_info.doing_signing || !data)
- return;
-
- DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
-data->send_seq_num = %u\n",
- (unsigned int)data->trans_info->mid,
- (unsigned int)data->trans_info->reply_seq_num,
- (unsigned int)data->trans_info->send_seq_num,
- (unsigned int)data->send_seq_num ));
-
- SAFE_FREE(data->trans_info);
- data->trans_info = NULL;
-}
-
-/***********************************************************
SMB signing - TEMP implementation - calculate a MAC to send.
************************************************************/
@@ -657,8 +567,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
unsigned char calc_md5_mac[16];
struct smb_basic_signing_context *data = si->signing_context;
- uint32 send_seq_number = data->send_seq_num;
- BOOL was_deferred_packet = False;
+ uint32 send_seq_number = data->send_seq_num-1;
uint16 mid;
if (!si->doing_signing) {
@@ -678,13 +587,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
mid = SVAL(outbuf, smb_mid);
/* See if this is a reply for a deferred packet. */
- was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
-
- if (data->trans_info && (data->trans_info->mid == mid)) {
- /* This is a reply in a trans stream. Use the sequence
- * number associated with the stream mid. */
- send_seq_number = data->trans_info->send_seq_num;
- }
+ get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
@@ -695,36 +598,6 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
/* cli->outbuf[smb_ss_field+2]=0;
Uncomment this to test if the remote client actually verifies signatures...*/
-
- /* Don't mess with the sequence number for a deferred packet. */
- if (was_deferred_packet) {
- return;
- }
-
- if (!data->trans_info) {
- /* Always increment if not in a trans stream. */
- data->send_seq_num++;
- } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
- /* Increment if this is the first reply in a trans stream or a
- * packet that doesn't belong to this stream (different mid). */
- data->send_seq_num++;
- }
-}
-
-/***********************************************************
- Is an incoming packet an oplock break reply ?
-************************************************************/
-
-static BOOL is_oplock_break(char *inbuf)
-{
- if (CVAL(inbuf,smb_com) != SMBlockingX)
- return False;
-
- if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
- return False;
-
- DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
- return True;
}
/***********************************************************
@@ -751,23 +624,8 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BO
mid = SVAL(inbuf, smb_mid);
- /* Is this part of a trans stream ? */
- if (data->trans_info && (data->trans_info->mid == mid)) {
- /* If so we don't increment the sequence. */
- reply_seq_number = data->trans_info->reply_seq_num;
- } else {
- /* We always increment the sequence number. */
- data->send_seq_num++;
-
- /* If we get an asynchronous oplock break reply and there
- * isn't a reply pending we need to re-sync the sequence
- * number.
- */
- if (is_oplock_break(inbuf)) {
- DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
- data->send_seq_num++;
- }
- }
+ /* We always increment the sequence number. */
+ data->send_seq_num += 2;
saved_seq = reply_seq_number;
simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
@@ -883,9 +741,8 @@ void srv_defer_sign_response(uint16 mid)
* Ensure we only store this mid reply once...
*/
- if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
- data->send_seq_num++;
- }
+ store_sequence_for_reply(&data->outstanding_packet_list, mid,
+ data->send_seq_num-1);
}
/***********************************************************
@@ -972,63 +829,6 @@ BOOL srv_signing_started(void)
return True;
}
-
-/***********************************************************
- Tell server code we are in a multiple trans reply state.
-************************************************************/
-
-void srv_signing_trans_start(uint16 mid)
-{
- struct smb_basic_signing_context *data;
-
- if (!srv_sign_info.doing_signing)
- return;
-
- data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
- if (!data)
- return;
-
- data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
- ZERO_STRUCTP(data->trans_info);
-
- data->trans_info->reply_seq_num = data->send_seq_num-1;
- data->trans_info->mid = mid;
- data->trans_info->send_seq_num = data->send_seq_num;
-
- DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
-data->send_seq_num = %u\n",
- (unsigned int)mid,
- (unsigned int)data->trans_info->reply_seq_num,
- (unsigned int)data->trans_info->send_seq_num,
- (unsigned int)data->send_seq_num ));
-}
-
-/***********************************************************
- Tell server code we are out of a multiple trans reply state.
-************************************************************/
-
-void srv_signing_trans_stop(void)
-{
- struct smb_basic_signing_context *data;
-
- if (!srv_sign_info.doing_signing)
- return;
-
- data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
- if (!data || !data->trans_info)
- return;
-
- DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
-data->send_seq_num = %u\n",
- (unsigned int)data->trans_info->mid,
- (unsigned int)data->trans_info->reply_seq_num,
- (unsigned int)data->trans_info->send_seq_num,
- (unsigned int)data->send_seq_num ));
-
- SAFE_FREE(data->trans_info);
- data->trans_info = NULL;
-}
-
/***********************************************************
Turn on signing from this packet onwards.
************************************************************/
diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c
index 4378385f3fd..ee43f4beee5 100644
--- a/source/libsmb/smbdes.c
+++ b/source/libsmb/smbdes.c
@@ -258,7 +258,8 @@ static void dohash(char *out, char *in, char *key, int forw)
permute(out, rl, perm6, 64);
}
-static void str_to_key(const unsigned char *str,unsigned char *key)
+/* Convert a 7 byte string to an 8 byte key. */
+static void str_to_key(const unsigned char str[7], unsigned char key[8])
{
int i;
@@ -330,7 +331,8 @@ void E_old_pw_hash( unsigned char *p14, const unsigned char *in, unsigned char *
des_crypt56(out+8, in+8, p14+7, 1);
}
-void cred_hash1(unsigned char *out, const unsigned char *in, const unsigned char *key)
+/* forward des encryption with a 128 bit key */
+void des_crypt128(unsigned char out[8], const unsigned char in[8], const unsigned char key[16])
{
unsigned char buf[8];
@@ -338,25 +340,49 @@ void cred_hash1(unsigned char *out, const unsigned char *in, const unsigned char
des_crypt56(out, buf, key+9, 1);
}
-void cred_hash2(unsigned char *out, const unsigned char *in, const unsigned char *key)
+/* forward des encryption with a 64 bit key */
+void des_crypt64(unsigned char out[8], const unsigned char in[8], const unsigned char key[8])
{
unsigned char buf[8];
- static unsigned char key2[8];
+ unsigned char key2[8];
+ memset(key2,'\0',8);
des_crypt56(buf, in, key, 1);
key2[0] = key[7];
des_crypt56(out, buf, key2, 1);
}
+/* des encryption with a 112 bit (14 byte) key */
+/* Note that if the forw is 1, and key is actually 8 bytes of key, followed by 6 bytes of zeros,
+ this is identical to des_crypt64(). JRA. */
+
+void des_crypt112(unsigned char out[8], const unsigned char in[8], const unsigned char key[14], int forw)
+{
+ unsigned char buf[8];
+ des_crypt56(buf, in, key, forw);
+ des_crypt56(out, buf, key+7, forw);
+}
+
void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw)
{
- static unsigned char key2[8];
+ unsigned char key2[8];
+ memset(key2,'\0',8);
des_crypt56(out, in, key, forw);
key2[0] = key[7];
des_crypt56(out + 8, in + 8, key2, forw);
}
+/* des encryption of a 16 byte lump of data with a 112 bit key */
+/* Note that if the key is actually 8 bytes of key, followed by 6 bytes of zeros,
+ this is identical to cred_hash3(). JRA. */
+
+void des_crypt112_16(unsigned char out[16], unsigned char in[16], const unsigned char key[14], int forw)
+{
+ des_crypt56(out, in, key, forw);
+ des_crypt56(out + 8, in + 8, key+7, forw);
+}
+
/*****************************************************************
arc4 crypt/decrypt with a 16 byte key.
*****************************************************************/
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index 99f99f23f8c..ddfe696b48e 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -531,6 +531,25 @@ BOOL decode_pw_buffer(uint8 in_buffer[516], char *new_pwrd,
}
/***********************************************************
+ Decode an arc4 encrypted password change buffer.
+************************************************************/
+
+void encode_or_decode_arc4_passwd_buffer(unsigned char pw_buf[532], const DATA_BLOB *psession_key)
+{
+ struct MD5Context tctx;
+ unsigned char key_out[16];
+
+ /* Confounder is last 16 bytes. */
+
+ MD5Init(&tctx);
+ MD5Update(&tctx, &pw_buf[516], 16);
+ MD5Update(&tctx, psession_key->data, psession_key->length);
+ MD5Final(key_out, &tctx);
+ /* arc4 with key_out. */
+ SamOEMhash(pw_buf, key_out, 516);
+}
+
+/***********************************************************
Encrypt/Decrypt used for LSA secrets and trusted domain
passwords.
************************************************************/
diff --git a/source/libsmb/spnego.c b/source/libsmb/spnego.c
index f6a66200bac..a2839578aef 100644
--- a/source/libsmb/spnego.c
+++ b/source/libsmb/spnego.c
@@ -48,6 +48,10 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
char *p_oid = NULL;
token->mechTypes =
SMB_REALLOC_ARRAY(token->mechTypes, const char *, i + 2);
+ if (!token->mechTypes) {
+ asn1->has_error = True;
+ return False;
+ }
asn1_read_OID(asn1, &p_oid);
token->mechTypes[i] = p_oid;
}
diff --git a/source/locking/brlock.c b/source/locking/brlock.c
index 25a1ed5e2f6..e6f0dd1c729 100644
--- a/source/locking/brlock.c
+++ b/source/locking/brlock.c
@@ -52,13 +52,7 @@ struct lock_struct {
br_off size;
int fnum;
enum brl_type lock_type;
-};
-
-/* The key used in the brlock database. */
-
-struct lock_key {
- SMB_DEV_T device;
- SMB_INO_T inode;
+ enum brl_flavour lock_flav;
};
/* The open brlock.tdb database. */
@@ -66,28 +60,31 @@ struct lock_key {
static TDB_CONTEXT *tdb;
/****************************************************************************
- Create a locking key - ensuring zero filled for pad purposes.
+ Debug info at level 10 for lock struct.
****************************************************************************/
-static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
+static void print_lock_struct(unsigned int i, struct lock_struct *pls)
{
- static struct 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;
+ DEBUG(10,("[%u]: smbpid = %u, tid = %u, pid = %u, ",
+ i,
+ (unsigned int)pls->context.smbpid,
+ (unsigned int)pls->context.tid,
+ (unsigned int)procid_to_pid(&pls->context.pid) ));
+
+ DEBUG(10,("start = %.0f, size = %.0f, fnum = %d, %s %s\n",
+ (double)pls->start,
+ (double)pls->size,
+ pls->fnum,
+ lock_type_name(pls->lock_type),
+ lock_flav_name(pls->lock_flav) ));
}
/****************************************************************************
See if two locking contexts are equal.
****************************************************************************/
-static BOOL brl_same_context(struct lock_context *ctx1,
- struct lock_context *ctx2)
+static BOOL brl_same_context(const struct lock_context *ctx1,
+ const struct lock_context *ctx2)
{
return (procid_equal(&ctx1->pid, &ctx2->pid) &&
(ctx1->smbpid == ctx2->smbpid) &&
@@ -98,8 +95,8 @@ static BOOL brl_same_context(struct lock_context *ctx1,
See if lck1 and lck2 overlap.
****************************************************************************/
-static BOOL brl_overlap(struct lock_struct *lck1,
- struct lock_struct *lck2)
+static BOOL brl_overlap(const struct lock_struct *lck1,
+ const struct lock_struct *lck2)
{
/* this extra check is not redundent - it copes with locks
that go beyond the end of 64 bit file space */
@@ -120,12 +117,14 @@ static BOOL brl_overlap(struct lock_struct *lck1,
See if lock2 can be added when lock1 is in place.
****************************************************************************/
-static BOOL brl_conflict(struct lock_struct *lck1,
- struct lock_struct *lck2)
+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 )
return False;
+ /* Read locks never conflict. */
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
return False;
}
@@ -138,9 +137,42 @@ static BOOL brl_conflict(struct lock_struct *lck1,
return brl_overlap(lck1, lck2);
}
+/****************************************************************************
+ See if lock2 can be added when lock1 is in place - when both locks are POSIX
+ flavour. POSIX locks ignore fnum - they only care about dev/ino which we
+ know already match.
+****************************************************************************/
+
+static BOOL brl_conflict_posix(const struct lock_struct *lck1,
+ const struct lock_struct *lck2)
+{
+#if defined(DEVELOPER)
+ SMB_ASSERT(lck1->lock_flav == POSIX_LOCK);
+ SMB_ASSERT(lck2->lock_flav == POSIX_LOCK);
+#endif
+
+ /* Ignore PENDING locks. */
+ if (lck1->lock_type == PENDING_LOCK || lck2->lock_type == PENDING_LOCK )
+ return False;
+
+ /* Read locks never conflict. */
+ if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK) {
+ return False;
+ }
+
+ /* Locks on the same context con't conflict. Ignore fnum. */
+ if (brl_same_context(&lck1->context, &lck2->context)) {
+ return False;
+ }
+
+ /* One is read, the other write, or the context is different,
+ do they overlap ? */
+ return brl_overlap(lck1, lck2);
+}
+
#if ZERO_ZERO
-static BOOL brl_conflict1(struct lock_struct *lck1,
- struct lock_struct *lck2)
+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 )
return False;
@@ -169,10 +201,11 @@ static BOOL brl_conflict1(struct lock_struct *lck1,
/****************************************************************************
Check to see if this lock conflicts, but ignore our own locks on the
- same fnum only.
+ same fnum only. This is the read/write lock check code path.
+ This is never used in the POSIX lock case.
****************************************************************************/
-static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck2)
+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 )
return False;
@@ -180,6 +213,12 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck
if (lck1->lock_type == READ_LOCK && lck2->lock_type == READ_LOCK)
return False;
+ /* POSIX flavour locks never conflict here - this is only called
+ in the read/write path. */
+
+ if (lck1->lock_flav == POSIX_LOCK && lck2->lock_flav == POSIX_LOCK)
+ return False;
+
/*
* Incoming WRITE locks conflict with existing READ locks even
* if the context is the same. JRA. See LOCKTEST7 in smbtorture.
@@ -200,7 +239,7 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck
app depends on this ?
****************************************************************************/
-static NTSTATUS brl_lock_failed(struct lock_struct *lock)
+static NTSTATUS brl_lock_failed(const struct lock_struct *lock)
{
static struct lock_struct last_lock_failure;
@@ -222,145 +261,431 @@ static NTSTATUS brl_lock_failed(struct lock_struct *lock)
return NT_STATUS_LOCK_NOT_GRANTED;
}
-#if DONT_DO_THIS
- /* doing this traversal could kill solaris machines under high load (tridge) */
- /* delete any dead locks */
-
/****************************************************************************
- Delete a record if it is for a dead process, if check_self is true, then
- delete any records belonging to this pid also (there shouldn't be any).
+ Open up the brlock.tdb database.
****************************************************************************/
-static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+void brl_init(int read_only)
{
- struct lock_struct *locks;
- int count, i;
- BOOL check_self = *(BOOL *)state;
- pid_t mypid = sys_getpid();
-
- tdb_chainlock(tdb, kbuf);
+ if (tdb) {
+ return;
+ }
+ tdb = tdb_open_log(lock_path("brlock.tdb"),
+ lp_open_files_db_hash_size(),
+ TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
+ read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
+ if (!tdb) {
+ DEBUG(0,("Failed to open byte range locking database %s\n",
+ lock_path("brlock.tdb")));
+ return;
+ }
+}
- locks = (struct lock_struct *)dbuf.dptr;
+/****************************************************************************
+ Close down the brlock.tdb database.
+****************************************************************************/
- count = dbuf.dsize / sizeof(*locks);
- for (i=0; i<count; i++) {
- struct lock_struct *lock = &locks[i];
+void brl_shutdown(int read_only)
+{
+ if (!tdb) {
+ return;
+ }
+ tdb_close(tdb);
+}
- /* If check_self is true we want to remove our own records. */
- if (check_self && (mypid == lock->context.pid)) {
+#if ZERO_ZERO
+/****************************************************************************
+ Compare two locks for sorting.
+****************************************************************************/
- DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
- (unsigned int)lock->context.pid ));
+static int lock_compare(const struct lock_struct *lck1,
+ const struct lock_struct *lck2)
+{
+ if (lck1->start != lck2->start) {
+ return (lck1->start - lck2->start);
+ }
+ if (lck2->size != lck1->size) {
+ return ((int)lck1->size - (int)lck2->size);
+ }
+ return 0;
+}
+#endif
- } else if (process_exists(&lock->context.pid)) {
+/****************************************************************************
+ Lock a range of bytes - Windows lock semantics.
+****************************************************************************/
- DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid ));
- continue;
+static NTSTATUS brl_lock_windows(struct byte_range_lock *br_lck,
+ const struct lock_struct *plock,
+ BOOL *my_lock_ctx)
+{
+ unsigned int i;
+ files_struct *fsp = br_lck->fsp;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+
+ 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;
+ }
+#if ZERO_ZERO
+ if (plock->start == 0 && plock->size == 0 &&
+ locks[i].size == 0) {
+ break;
}
+#endif
+ }
- DEBUG(10,("brlock : delete_fn. Deleting record for process %u\n",
- (unsigned int)lock->context.pid ));
+ /* 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 (count > 1 && i < count-1) {
- memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((count-1) - i));
+ 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) {
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ } else {
+ return map_nt_error_from_unix(errno);
+ }
}
- count--;
- i--;
}
- if (count == 0) {
- tdb_delete(tdb, kbuf);
- } else if (count < (dbuf.dsize / sizeof(*locks))) {
- dbuf.dsize = count * sizeof(*locks);
- tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ /* no conflicts - add it to the list of locks */
+ locks = (struct lock_struct *)SMB_REALLOC(locks, (br_lck->num_locks + 1) * sizeof(*locks));
+ if (!locks) {
+ return NT_STATUS_NO_MEMORY;
}
- tdb_chainunlock(tdb, kbuf);
- return 0;
+ memcpy(&locks[br_lck->num_locks], plock, sizeof(struct lock_struct));
+ br_lck->num_locks += 1;
+ br_lck->lock_data = (void *)locks;
+ br_lck->modified = True;
+
+ return NT_STATUS_OK;
}
-#endif
/****************************************************************************
- Open up the brlock.tdb database.
+ Cope with POSIX range splits and merges.
****************************************************************************/
-void brl_init(int read_only)
+static unsigned int brlock_posix_split_merge(struct lock_struct *lck_arr,
+ const struct lock_struct *ex,
+ const struct lock_struct *plock,
+ BOOL *lock_was_added)
{
- if (tdb)
- return;
- tdb = tdb_open_log(lock_path("brlock.tdb"), 0, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
- read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644 );
- if (!tdb) {
- DEBUG(0,("Failed to open byte range locking database\n"));
- return;
+ BOOL lock_types_differ = (ex->lock_type != plock->lock_type);
+
+ /* We can't merge non-conflicting locks on different context - ignore fnum. */
+
+ if (!brl_same_context(&ex->context, &plock->context)) {
+ /* Just copy. */
+ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
+ return 1;
}
-#if DONT_DO_THIS
- /* doing this traversal could kill solaris machines under high load (tridge) */
- /* delete any dead locks */
- if (!read_only) {
- BOOL check_self = False;
- tdb_traverse(tdb, delete_fn, &check_self);
+ /* We now know we have the same context. */
+
+ /* Did we overlap ? */
+
+/*********************************************
+ +---------+
+ | ex |
+ +---------+
+ +-------+
+ | plock |
+ +-------+
+OR....
+ +---------+
+ | ex |
+ +---------+
+**********************************************/
+
+ 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;
}
-#endif
+
+/*********************************************
+ +---------+
+ | ex |
+ +---------+
+ +---------------------------+
+ | plock | -> replace with plock.
+ +---------------------------+
+**********************************************/
+
+ if ( (ex->start >= plock->start) &&
+ (ex->start + ex->size <= plock->start + plock->size) ) {
+ memcpy(&lck_arr[0], plock, sizeof(struct lock_struct));
+ *lock_was_added = True;
+ return 1;
+ }
+
+/*********************************************
+ +---------------+
+ | ex |
+ +---------------+
+ +---------------+
+ | plock |
+ +---------------+
+BECOMES....
+ +---------------+-------+
+ | plock | ex | - different lock types.
+ +---------------+-------+
+OR....
+ +-----------------------+
+ | ex | - same lock type.
+ +-----------------------+
+**********************************************/
+
+ if ( (ex->start >= plock->start) &&
+ (ex->start < plock->start + plock->size) &&
+ (ex->start + ex->size > plock->start + plock->size) ) {
+
+ *lock_was_added = True;
+
+ /* If the lock types are the same, we merge, if different, we
+ add the new lock before the old. */
+
+ if (lock_types_differ) {
+ /* Add new. */
+ memcpy(&lck_arr[0], plock, sizeof(struct lock_struct));
+ memcpy(&lck_arr[1], ex, sizeof(struct lock_struct));
+ /* Adjust existing start and size. */
+ lck_arr[1].start = plock->start + plock->size;
+ lck_arr[1].size = (ex->start + ex->size) - (plock->start + plock->size);
+ return 2;
+ } else {
+ /* Merge. */
+ memcpy(&lck_arr[0], plock, sizeof(struct lock_struct));
+ /* Set new start and size. */
+ lck_arr[0].start = plock->start;
+ lck_arr[0].size = (ex->start + ex->size) - plock->start;
+ return 1;
+ }
+ }
+
+/*********************************************
+ +---------------+
+ | ex |
+ +---------------+
+ +---------------+
+ | plock |
+ +---------------+
+BECOMES....
+ +-------+---------------+
+ | ex | plock | - different lock types
+ +-------+---------------+
+
+OR
+ +-----------------------+
+ | ex | - same lock type.
+ +-----------------------+
+
+**********************************************/
+
+ if ( (ex->start < plock->start) &&
+ (ex->start + ex->size > plock->start) &&
+ (ex->start + ex->size <= plock->start + plock->size) ) {
+
+ *lock_was_added = True;
+
+ /* If the lock types are the same, we merge, if different, we
+ add the new lock after the old. */
+
+ if (lock_types_differ) {
+ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
+ memcpy(&lck_arr[1], plock, sizeof(struct lock_struct));
+ /* Adjust existing size. */
+ lck_arr[0].size = plock->start - ex->start;
+ return 2;
+ } else {
+ /* Merge. */
+ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
+ /* Adjust existing size. */
+ lck_arr[0].size = (plock->start + plock->size) - ex->start;
+ return 1;
+ }
+ }
+
+/*********************************************
+ +---------------------------+
+ | ex |
+ +---------------------------+
+ +---------+
+ | plock |
+ +---------+
+BECOMES.....
+ +-------+---------+---------+
+ | ex | plock | ex | - different lock types.
+ +-------+---------+---------+
+OR
+ +---------------------------+
+ | ex | - same lock type.
+ +---------------------------+
+**********************************************/
+
+ if ( (ex->start < plock->start) && (ex->start + ex->size > plock->start + plock->size) ) {
+ *lock_was_added = True;
+
+ if (lock_types_differ) {
+
+ /* We have to split ex into two locks here. */
+
+ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
+ memcpy(&lck_arr[1], plock, sizeof(struct lock_struct));
+ memcpy(&lck_arr[2], ex, sizeof(struct lock_struct));
+
+ /* Adjust first existing size. */
+ lck_arr[0].size = plock->start - ex->start;
+
+ /* Adjust second existing start and size. */
+ lck_arr[2].start = plock->start + plock->size;
+ lck_arr[2].size = (ex->start + ex->size) - (plock->start + plock->size);
+ return 3;
+ } else {
+ /* Just eat plock. */
+ memcpy(&lck_arr[0], ex, sizeof(struct lock_struct));
+ return 1;
+ }
+ }
+
+ /* Never get here. */
+ smb_panic("brlock_posix_split_merge\n");
+ /* Notreached. */
+ abort();
}
/****************************************************************************
- Close down the brlock.tdb database.
+ Lock a range of bytes - POSIX lock semantics.
+ We must cope with range splits and merges.
****************************************************************************/
-void brl_shutdown(int read_only)
+static NTSTATUS brl_lock_posix(struct byte_range_lock *br_lck,
+ const struct lock_struct *plock,
+ BOOL *my_lock_ctx)
{
- if (!tdb)
- return;
+ unsigned int i, count;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ struct lock_struct *tp;
+ BOOL lock_was_added = False;
+
+ /* No zero-zero locks for POSIX. */
+ if (plock->start == 0 && plock->size == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Don't allow 64-bit lock wrap. */
+ if (plock->start + plock->size < plock->start ||
+ plock->start + plock->size < plock->size) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* The worst case scenario here is we have to split an
+ existing POSIX lock range into two, and add our lock,
+ so we need at most 2 more entries. */
+
+ tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 2));
+ if (!tp) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ count = 0;
+ for (i=0; i < br_lck->num_locks; i++) {
+ if (locks[i].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;
+ }
+ /* 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));
+ count++;
+ } else {
+ /* POSIX conflict semantics are different. */
+ if (brl_conflict_posix(&locks[i], plock)) {
+ /* Can't block ourselves with POSIX locks. */
+ /* No games with error messages. */
+ SAFE_FREE(tp);
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
-#if DONT_DO_THIS
- /* doing this traversal could kill solaris machines under high load (tridge) */
- /* delete any dead locks */
- if (!read_only) {
- BOOL check_self = True;
- tdb_traverse(tdb, delete_fn, &check_self);
+ /* Work out overlaps. */
+ count += brlock_posix_split_merge(&tp[count], &locks[i], plock, &lock_was_added);
+ }
+ }
+
+ /* 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. */
+
+#if 0
+ /* FIXME - this call doesn't work correctly yet for POSIX locks... */
+
+ if ((plock->lock_type != PENDING_LOCK) && lp_posix_locking(SNUM(fsp->conn))) {
+ files_struct *fsp = br_lck->fsp;
+
+ if (!set_posix_lock(fsp, plock->start, plock->size, plock->lock_type, POSIX_LOCK)) {
+ if (errno == EACCES || errno == EAGAIN) {
+ SAFE_FREE(tp);
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ } else {
+ SAFE_FREE(tp);
+ return map_nt_error_from_unix(errno);
+ }
+ }
}
#endif
- tdb_close(tdb);
-}
+ if (!lock_was_added) {
+ memcpy(&tp[count], plock, sizeof(struct lock_struct));
+ count++;
+ }
-#if ZERO_ZERO
-/****************************************************************************
-compare two locks for sorting
-****************************************************************************/
-static int lock_compare(struct lock_struct *lck1,
- struct lock_struct *lck2)
-{
- if (lck1->start != lck2->start) return (lck1->start - lck2->start);
- if (lck2->size != lck1->size) {
- return ((int)lck1->size - (int)lck2->size);
+ /* Realloc so we don't leak entries per lock call. */
+ tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
+ if (!tp) {
+ return NT_STATUS_NO_MEMORY;
}
- return 0;
+ br_lck->num_locks = count;
+ br_lck->lock_data = (void *)tp;
+ br_lck->modified = True;
+ return NT_STATUS_OK;
}
-#endif
/****************************************************************************
Lock a range of bytes.
****************************************************************************/
-NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
- uint16 smbpid, struct process_id pid, uint16 tid,
- br_off start, br_off size,
- enum brl_type lock_type, BOOL *my_lock_ctx)
+NTSTATUS brl_lock(struct byte_range_lock *br_lck,
+ uint16 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)
{
- TDB_DATA kbuf, dbuf;
- int count, i;
- struct lock_struct lock, *locks;
- char *tp;
- NTSTATUS status = NT_STATUS_OK;
+ NTSTATUS ret;
+ struct lock_struct lock;
*my_lock_ctx = False;
- kbuf = locking_key(dev,ino);
-
- dbuf.dptr = NULL;
#if !ZERO_ZERO
if (start == 0 && size == 0) {
@@ -368,68 +693,27 @@ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
}
#endif
- tdb_chainlock(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
-
lock.context.smbpid = smbpid;
lock.context.pid = pid;
- lock.context.tid = tid;
+ lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = start;
lock.size = size;
- lock.fnum = fnum;
+ lock.fnum = br_lck->fsp->fnum;
lock.lock_type = lock_type;
+ lock.lock_flav = lock_flav;
- if (dbuf.dptr) {
- /* there are existing locks - make sure they don't conflict */
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
- for (i=0; i<count; i++) {
- if (brl_conflict(&locks[i], &lock)) {
- status = brl_lock_failed(&lock);;
- /* Did we block ourselves ? */
- if (brl_same_context(&locks[i].context, &lock.context))
- *my_lock_ctx = True;
- goto fail;
- }
-#if ZERO_ZERO
- if (lock.start == 0 && lock.size == 0 &&
- locks[i].size == 0) {
- break;
- }
-#endif
- }
- }
-
- /* no conflicts - add it to the list of locks */
- tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(*locks));
- if (!tp) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
+ if (lock_flav == WINDOWS_LOCK) {
+ ret = brl_lock_windows(br_lck, &lock, my_lock_ctx);
} else {
- dbuf.dptr = tp;
+ ret = brl_lock_posix(br_lck, &lock, my_lock_ctx);
}
- memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock));
- dbuf.dsize += sizeof(lock);
#if ZERO_ZERO
/* sort the lock list */
- qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare);
+ qsort(br_lck->lock_data, (size_t)br_lck->num_locks, sizeof(lock), lock_compare);
#endif
- if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
- status = NT_STATUS_INTERNAL_DB_CORRUPTION;
- goto fail;
- }
-
- SAFE_FREE(dbuf.dptr);
- tdb_chainunlock(tdb, kbuf);
- return NT_STATUS_OK;
-
- fail:
-
- SAFE_FREE(dbuf.dptr);
- tdb_chainunlock(tdb, kbuf);
- return status;
+ return ret;
}
/****************************************************************************
@@ -446,260 +730,532 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe
}
/****************************************************************************
- Unlock a range of bytes.
+ Unlock a range of bytes - Windows semantics.
****************************************************************************/
-BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
- uint16 smbpid, struct process_id pid, uint16 tid,
- br_off start, br_off size,
- BOOL remove_pending_locks_only,
- void (*pre_unlock_fn)(void *),
- void *pre_unlock_data)
+static BOOL brl_unlock_windows(struct byte_range_lock *br_lck, const struct lock_struct *plock)
{
- TDB_DATA kbuf, dbuf;
- int count, i, j;
- struct lock_struct *locks;
- struct lock_context context;
+ unsigned int i, j;
+ struct lock_struct *lock = NULL;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
- kbuf = locking_key(dev,ino);
+#if ZERO_ZERO
+ for (i = 0; i < br_lck->num_locks; i++) {
+ lock = &locks[i];
- dbuf.dptr = NULL;
+ if (lock->lock_type == WRITE_LOCK &&
+ brl_same_context(&lock->context, &plock->context) &&
+ lock->fnum == plock->fnum &&
+ lock->lock_flav == WINDOWS_LOCK &&
+ lock->start == plock->start &&
+ lock->size == plock->size) {
- tdb_chainlock(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
+ /* 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));
+ }
- if (!dbuf.dptr) {
- DEBUG(10,("brl_unlock: tdb_fetch failed !\n"));
- goto fail;
+ br_lck->num_locks -= 1;
+ br_lck->modified = True;
+ return True;
+ }
}
+#endif
- context.smbpid = smbpid;
- context.pid = pid;
- context.tid = tid;
+ for (i = 0; i < br_lck->num_locks; i++) {
+ lock = &locks[i];
- /* there are existing locks - find a match */
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
+ /* Only remove our own locks that match in start, size, and flavour. */
+ if (brl_same_context(&lock->context, &plock->context) &&
+ lock->fnum == plock->fnum &&
+ lock->lock_flav == WINDOWS_LOCK &&
+ lock->start == plock->start &&
+ lock->size == plock->size ) {
+ break;
+ }
+ }
-#if ZERO_ZERO
- for (i=0; i<count; i++) {
- struct lock_struct *lock = &locks[i];
+ if (i == br_lck->num_locks) {
+ /* we didn't find it */
+ return False;
+ }
- if (lock->lock_type == WRITE_LOCK &&
- brl_same_context(&lock->context, &context) &&
- lock->fnum == fnum &&
- lock->start == start &&
- lock->size == size) {
+ /* Unlock any POSIX regions. */
+ if(lp_posix_locking(br_lck->fsp->conn->cnum)) {
+ release_posix_lock(br_lck->fsp, plock->start, plock->size);
+ }
- if (pre_unlock_fn)
- (*pre_unlock_fn)(pre_unlock_data);
+ /* Send unlock messages to any pending waiters that overlap. */
+ for (j=0; j < br_lck->num_locks; j++) {
+ struct lock_struct *pend_lock = &locks[j];
- /* found it - delete it */
- if (count == 1) {
- tdb_delete(tdb, kbuf);
- } else {
- if (i < count-1) {
- memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((count-1) - i));
- }
- dbuf.dsize -= sizeof(*locks);
- tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
- }
+ /* Ignore non-pending locks. */
+ if (pend_lock->lock_type != PENDING_LOCK) {
+ continue;
+ }
- SAFE_FREE(dbuf.dptr);
- tdb_chainunlock(tdb, kbuf);
- return True;
+ /* We could send specific lock info here... */
+ if (brl_pending_overlap(lock, pend_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();
}
}
-#endif
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
- for (i=0; i<count; i++) {
- struct lock_struct *lock = &locks[i];
+ /* 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));
+ }
- if (brl_same_context(&lock->context, &context) &&
- lock->fnum == fnum &&
- lock->start == start &&
- lock->size == size) {
+ br_lck->num_locks -= 1;
+ br_lck->modified = True;
+ return True;
+}
+
+/****************************************************************************
+ Unlock a range of bytes - POSIX semantics.
+****************************************************************************/
- if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK)
- continue;
+static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_struct *plock)
+{
+ unsigned int i, j, count;
+ struct lock_struct *lock = NULL;
+ struct lock_struct *tp;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ BOOL overlap_found = False;
+
+ /* No zero-zero locks for POSIX. */
+ if (plock->start == 0 && plock->size == 0) {
+ return False;
+ }
+
+ /* Don't allow 64-bit lock wrap. */
+ if (plock->start + plock->size < plock->start ||
+ plock->start + plock->size < plock->size) {
+ DEBUG(10,("brl_unlock_posix: lock wrap\n"));
+ return False;
+ }
- if (lock->lock_type != PENDING_LOCK) {
+ /* The worst case scenario here is we have to split an
+ existing POSIX lock range into two, so we need at most
+ 1 more entry. */
- /* Do any POSIX unlocks needed. */
- if (pre_unlock_fn)
- (*pre_unlock_fn)(pre_unlock_data);
+ tp = SMB_MALLOC_ARRAY(struct lock_struct, (br_lck->num_locks + 1));
+ if (!tp) {
+ DEBUG(10,("brl_unlock_posix: malloc fail\n"));
+ return False;
+ }
- /* Send unlock messages to any pending waiters that overlap. */
- for (j=0; j<count; j++) {
- struct lock_struct *pend_lock = &locks[j];
+ count = 0;
+ for (i = 0; i < br_lck->num_locks; i++) {
+ struct lock_struct tmp_lock[3];
+ BOOL lock_was_added = False;
+ unsigned int tmp_count;
- /* Ignore non-pending locks. */
- if (pend_lock->lock_type != PENDING_LOCK)
- continue;
+ lock = &locks[i];
- /* We could send specific lock info here... */
- if (brl_pending_overlap(lock, pend_lock)) {
- DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
- procid_str_static(&pend_lock->context.pid )));
+ /* Only remove our own locks - ignore fnum. */
+ if (lock->lock_type == PENDING_LOCK ||
+ !brl_same_context(&lock->context, &plock->context)) {
+ memcpy(&tp[count], lock, sizeof(struct lock_struct));
+ count++;
+ continue;
+ }
- message_send_pid(pend_lock->context.pid,
- MSG_SMB_UNLOCK,
- NULL, 0, True);
- }
- }
+ /* Work out overlaps. */
+ tmp_count = brlock_posix_split_merge(&tmp_lock[0], &locks[i], plock, &lock_was_added);
+
+ if (tmp_count == 1) {
+ /* Ether the locks didn't overlap, or the unlock completely
+ overlapped this lock. If it didn't overlap, then there's
+ no change in the locks. */
+ if (tmp_lock[0].lock_type != UNLOCK_LOCK) {
+ SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
+ /* No change in this lock. */
+ memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
+ count++;
+ } else {
+ SMB_ASSERT(tmp_lock[0].lock_type == UNLOCK_LOCK);
+ overlap_found = True;
}
-
- /* found it - delete it */
- if (count == 1) {
- tdb_delete(tdb, kbuf);
+ continue;
+ } else if (tmp_count == 2) {
+ /* The unlock overlapped an existing lock. Copy the truncated
+ lock into the lock array. */
+ if (tmp_lock[0].lock_type != UNLOCK_LOCK) {
+ 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));
} else {
- if (i < count-1) {
- memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((count-1) - i));
- }
- dbuf.dsize -= sizeof(*locks);
- tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ 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));
+ }
+ count++;
+ overlap_found = True;
+ continue;
+ } else {
+ /* tmp_count == 3 - (we split a lock range in two). */
+ SMB_ASSERT(tmp_lock[0].lock_type == locks[i].lock_type);
+ SMB_ASSERT(tmp_lock[1].lock_type == UNLOCK_LOCK);
+ SMB_ASSERT(tmp_lock[2].lock_type != locks[i].lock_type);
+
+ memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
+ count++;
+ memcpy(&tp[count], &tmp_lock[2], sizeof(struct lock_struct));
+ count++;
+ overlap_found = True;
+ /* Optimisation... */
+ /* We know we're finished here as we can't overlap any
+ more POSIX locks. Copy the rest of the lock array. */
+ if (i < br_lck->num_locks - 1) {
+ memcpy(&tp[count], &locks[i+1],
+ sizeof(*locks)*((br_lck->num_locks-1) - i));
+ count += ((br_lck->num_locks-1) - i);
}
+ break;
+ }
+ }
- SAFE_FREE(dbuf.dptr);
- tdb_chainunlock(tdb, kbuf);
- return True;
+ if (!overlap_found) {
+ /* Just ignore - no change. */
+ SAFE_FREE(tp);
+ DEBUG(10,("brl_unlock_posix: No overlap - unlocked.\n"));
+ 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);
+ }
+#endif
+
+ /* Realloc so we don't leak entries per unlock call. */
+ if (count) {
+ tp = (struct lock_struct *)SMB_REALLOC(tp, count * sizeof(*locks));
+ if (!tp) {
+ DEBUG(10,("brl_unlock_posix: realloc fail\n"));
+ return False;
}
+ } else {
+ /* We deleted the last lock. */
+ SAFE_FREE(tp);
+ tp = NULL;
}
- /* we didn't find it */
+ br_lck->num_locks = count;
+ br_lck->lock_data = (void *)tp;
+ br_lck->modified = True;
- fail:
- SAFE_FREE(dbuf.dptr);
- tdb_chainunlock(tdb, kbuf);
- return False;
-}
+ /* Send unlock messages to any pending waiters that overlap. */
+ locks = tp;
+
+ for (j=0; j < br_lck->num_locks; j++) {
+ struct lock_struct *pend_lock = &locks[j];
+
+ /* Ignore non-pending locks. */
+ if (pend_lock->lock_type != PENDING_LOCK) {
+ continue;
+ }
+
+ /* We could send specific lock info here... */
+ if (brl_pending_overlap(lock, pend_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();
+ }
+ }
+
+ return True;
+}
/****************************************************************************
- Test if we could add a lock if we wanted to.
+ Unlock a range of bytes.
****************************************************************************/
-BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
- uint16 smbpid, struct process_id pid, uint16 tid,
- br_off start, br_off size,
- enum brl_type lock_type)
+BOOL brl_unlock(struct byte_range_lock *br_lck,
+ uint16 smbpid,
+ struct process_id pid,
+ br_off start,
+ br_off size,
+ enum brl_flavour lock_flav)
{
- TDB_DATA kbuf, dbuf;
- int count, i;
- struct lock_struct lock, *locks;
+ struct lock_struct lock;
- kbuf = locking_key(dev,ino);
+ lock.context.smbpid = smbpid;
+ lock.context.pid = pid;
+ lock.context.tid = br_lck->fsp->conn->cnum;
+ lock.start = start;
+ lock.size = size;
+ lock.fnum = br_lck->fsp->fnum;
+ lock.lock_type = UNLOCK_LOCK;
+ lock.lock_flav = lock_flav;
- dbuf.dptr = NULL;
+ if (lock_flav == WINDOWS_LOCK) {
+ return brl_unlock_windows(br_lck, &lock);
+ } else {
+ return brl_unlock_posix(br_lck, &lock);
+ }
+}
- dbuf = tdb_fetch(tdb, kbuf);
+/****************************************************************************
+ Test if we could add a lock if we wanted to.
+ Returns True if the region required is currently unlocked, False if locked.
+****************************************************************************/
+
+BOOL brl_locktest(struct byte_range_lock *br_lck,
+ uint16 smbpid,
+ struct process_id pid,
+ br_off start,
+ br_off size,
+ enum brl_type lock_type,
+ enum brl_flavour lock_flav)
+{
+ BOOL ret = True;
+ unsigned int i;
+ struct lock_struct lock;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ files_struct *fsp = br_lck->fsp;
lock.context.smbpid = smbpid;
lock.context.pid = pid;
- lock.context.tid = tid;
+ lock.context.tid = br_lck->fsp->conn->cnum;
lock.start = start;
lock.size = size;
- lock.fnum = fnum;
+ lock.fnum = fsp->fnum;
lock.lock_type = lock_type;
-
- if (dbuf.dptr) {
- /* there are existing locks - make sure they don't conflict */
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
- for (i=0; i<count; i++) {
- /*
- * Our own locks don't conflict.
- */
- if (brl_conflict_other(&locks[i], &lock))
- goto fail;
+ lock.lock_flav = lock_flav;
+
+ /* Make sure existing locks don't conflict */
+ for (i=0; i < br_lck->num_locks; i++) {
+ /*
+ * Our own locks don't conflict.
+ */
+ if (brl_conflict_other(&locks[i], &lock)) {
+ return False;
}
}
+ /*
+ * There is no lock held by an SMB daemon, check to
+ * see if there is a POSIX lock from a UNIX or NFS process.
+ * This only conflicts with Windows locks, not POSIX locks.
+ */
+
+ if(lp_posix_locking(fsp->conn->cnum) && (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",
+ (double)start, (double)size, ret ? "locked" : "unlocked",
+ fsp->fnum, fsp->fsp_name ));
+
+ /* We need to return the inverse of is_posix_locked. */
+ ret = !ret;
+ }
+
/* no conflicts - we could have added it */
- SAFE_FREE(dbuf.dptr);
- return True;
+ return ret;
+}
- fail:
- SAFE_FREE(dbuf.dptr);
- return False;
+/****************************************************************************
+ Query for existing locks.
+****************************************************************************/
+
+NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
+ uint16 *psmbpid,
+ struct process_id pid,
+ br_off *pstart,
+ br_off *psize,
+ enum brl_type *plock_type,
+ enum brl_flavour lock_flav)
+{
+ unsigned int i;
+ struct lock_struct lock;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ files_struct *fsp = br_lck->fsp;
+
+ lock.context.smbpid = *psmbpid;
+ lock.context.pid = pid;
+ lock.context.tid = br_lck->fsp->conn->cnum;
+ lock.start = *pstart;
+ lock.size = *psize;
+ lock.fnum = fsp->fnum;
+ lock.lock_type = *plock_type;
+ lock.lock_flav = lock_flav;
+
+ /* Make sure existing locks don't conflict */
+ for (i=0; i < br_lck->num_locks; i++) {
+ struct lock_struct *exlock = &locks[i];
+ BOOL conflict = False;
+
+ if (exlock->lock_flav == WINDOWS_LOCK) {
+ conflict = brl_conflict(exlock, &lock);
+ } else {
+ conflict = brl_conflict_posix(exlock, &lock);
+ }
+
+ if (conflict) {
+ *psmbpid = exlock->context.smbpid;
+ *pstart = exlock->start;
+ *psize = exlock->size;
+ *plock_type = exlock->lock_type;
+ return NT_STATUS_LOCK_NOT_GRANTED;
+ }
+ }
+
+ /*
+ * There is no lock held by an SMB daemon, check to
+ * see if there is a POSIX lock from a UNIX or NFS process.
+ */
+
+ if(lp_posix_locking(fsp->conn->cnum)) {
+ 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",
+ (double)*pstart, (double)*psize, ret ? "locked" : "unlocked",
+ fsp->fnum, fsp->fsp_name ));
+
+ if (ret) {
+ /* Hmmm. No clue what to set smbpid to - use -1. */
+ *psmbpid = 0xFFFF;
+ return NT_STATUS_LOCK_NOT_GRANTED;
+ }
+ }
+
+ return NT_STATUS_OK;
}
+
/****************************************************************************
- Remove any locks associated with a open file.
+ Remove a particular pending lock.
****************************************************************************/
-void brl_close(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, int tid, int fnum)
+BOOL brl_remove_pending_lock(struct byte_range_lock *br_lck,
+ uint16 smbpid,
+ struct process_id pid,
+ br_off start,
+ br_off size,
+ enum brl_flavour lock_flav)
{
- TDB_DATA kbuf, dbuf;
- int count, i, j, dcount=0;
- struct lock_struct *locks;
+ unsigned int i;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+ struct lock_context context;
+
+ context.smbpid = smbpid;
+ context.pid = pid;
+ context.tid = br_lck->fsp->conn->cnum;
+
+ for (i = 0; i < br_lck->num_locks; i++) {
+ struct lock_struct *lock = &locks[i];
+
+ /* 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 &&
+ lock->lock_flav == lock_flav &&
+ lock->start == start &&
+ lock->size == size) {
+ break;
+ }
+ }
+
+ if (i == br_lck->num_locks) {
+ /* Didn't find it. */
+ return False;
+ }
- kbuf = locking_key(dev,ino);
+ if (i < br_lck->num_locks - 1) {
+ /* Found this particular pending lock - delete it */
+ memmove(&locks[i], &locks[i+1],
+ sizeof(*locks)*((br_lck->num_locks-1) - i));
+ }
- dbuf.dptr = NULL;
+ br_lck->num_locks -= 1;
+ br_lck->modified = True;
+ return True;
+}
- tdb_chainlock(tdb, kbuf);
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr) goto fail;
+/****************************************************************************
+ Remove any locks associated with a open file.
+****************************************************************************/
- /* there are existing locks - remove any for this fnum */
- locks = (struct lock_struct *)dbuf.dptr;
- count = dbuf.dsize / sizeof(*locks);
+void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
+{
+ files_struct *fsp = br_lck->fsp;
+ uint16 tid = fsp->conn->cnum;
+ int fnum = fsp->fnum;
+ unsigned int i, j, dcount=0;
+ struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
+
+ /* Remove any existing locks for this fnum (or any fnum if they're POSIX). */
- for (i=0; i<count; i++) {
+ for (i=0; i < br_lck->num_locks; i++) {
struct lock_struct *lock = &locks[i];
+ BOOL del_this_lock = False;
- if (lock->context.tid == tid &&
- procid_equal(&lock->context.pid, &pid) &&
- lock->fnum == fnum) {
+ if (lock->context.tid == tid && procid_equal(&lock->context.pid, &pid)) {
+ if ((lock->lock_flav == WINDOWS_LOCK) && (lock->fnum == fnum)) {
+ del_this_lock = True;
+ } else if (lock->lock_flav == POSIX_LOCK) {
+ del_this_lock = True;
+ }
+ }
+ if (del_this_lock) {
/* Send unlock messages to any pending waiters that overlap. */
- for (j=0; j<count; j++) {
+ for (j=0; j < br_lck->num_locks; j++) {
struct lock_struct *pend_lock = &locks[j];
/* Ignore our own or non-pending locks. */
- if (pend_lock->lock_type != PENDING_LOCK)
+ if (pend_lock->lock_type != PENDING_LOCK) {
continue;
+ }
+ /* Optimisation - don't send to this fnum as we're
+ closing it. */
if (pend_lock->context.tid == tid &&
procid_equal(&pend_lock->context.pid, &pid) &&
- pend_lock->fnum == fnum)
+ pend_lock->fnum == fnum) {
continue;
+ }
/* We could send specific lock info here... */
- if (brl_pending_overlap(lock, pend_lock))
+ if (brl_pending_overlap(lock, pend_lock)) {
+ become_root();
message_send_pid(pend_lock->context.pid,
MSG_SMB_UNLOCK,
NULL, 0, True);
+ unbecome_root();
+ }
}
/* found it - delete it */
- if (count > 1 && i < count-1) {
+ if (br_lck->num_locks > 1 && i < br_lck->num_locks - 1) {
memmove(&locks[i], &locks[i+1],
- sizeof(*locks)*((count-1) - i));
+ sizeof(*locks)*((br_lck->num_locks-1) - i));
}
- count--;
+ br_lck->num_locks--;
+ br_lck->modified = True;
i--;
dcount++;
}
}
-
- if (count == 0) {
- tdb_delete(tdb, kbuf);
- } else if (count < (dbuf.dsize / sizeof(*locks))) {
- dbuf.dsize -= dcount * sizeof(*locks);
- tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
- }
-
- /* we didn't find it */
- fail:
- SAFE_FREE(dbuf.dptr);
- tdb_chainunlock(tdb, kbuf);
}
/****************************************************************************
@@ -719,9 +1275,11 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
key = (struct lock_key *)kbuf.dptr;
for (i=0;i<dbuf.dsize/sizeof(*locks);i++) {
- traverse_callback(key->device, key->inode,
+ traverse_callback(key->device,
+ key->inode,
locks[i].context.pid,
locks[i].lock_type,
+ locks[i].lock_flav,
locks[i].start,
locks[i].size);
}
@@ -734,6 +1292,96 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
int brl_forall(BRLOCK_FN(fn))
{
- if (!tdb) return 0;
+ if (!tdb) {
+ return 0;
+ }
return tdb_traverse(tdb, traverse_fn, (void *)fn);
}
+
+/*******************************************************************
+ Store a potentially modified set of byte range lock data back into
+ the database.
+ Unlock the record.
+********************************************************************/
+
+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->modified) {
+ goto done;
+ }
+
+ if (br_lck->num_locks == 0) {
+ /* No locks - delete this entry. */
+ if (tdb_delete(tdb, key) == -1) {
+ smb_panic("Could not delete byte range lock entry\n");
+ }
+ } else {
+ TDB_DATA data;
+ data.dptr = br_lck->lock_data;
+ data.dsize = br_lck->num_locks * sizeof(struct lock_struct);
+
+ if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) {
+ smb_panic("Could not store byte range mode entry\n");
+ }
+ }
+
+ done:
+
+ 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.
+********************************************************************/
+
+struct byte_range_lock *brl_get_locks(files_struct *fsp)
+{
+ TDB_DATA key;
+ TDB_DATA data;
+ struct byte_range_lock *br_lck = SMB_MALLOC_P(struct byte_range_lock);
+
+ if (br_lck == NULL) {
+ return NULL;
+ }
+
+ br_lck->fsp = fsp;
+ br_lck->num_locks = 0;
+ br_lck->modified = False;
+ memset(&br_lck->key, '\0', sizeof(struct lock_key));
+ br_lck->key.device = fsp->dev;
+ br_lck->key.inode = fsp->inode;
+
+ 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;
+ }
+
+ data = tdb_fetch(tdb, key);
+ br_lck->lock_data = (void *)data.dptr;
+ br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
+
+ 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",
+ br_lck->num_locks,
+ (double)fsp->dev, (double)fsp->inode ));
+ for( i = 0; i < br_lck->num_locks; i++) {
+ print_lock_struct(i, &locks[i]);
+ }
+ }
+ return br_lck;
+}
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 7b128736969..2b6023c0c41 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
Locking functions
Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Jeremy Allison 1992-2000
+ Copyright (C) Jeremy Allison 1992-2006
Copyright (C) Volker Lendecke 2005
This program is free software; you can redistribute it and/or modify
@@ -33,6 +33,7 @@
rewrtten completely to use new tdb code. Tridge, Dec '99
Added POSIX locking support. Jeremy Allison (jeremy@valinux.com), Apr. 2000.
+ Added Unix Extensions POSIX locking support. Jeremy Allison Mar 2006.
*/
#include "includes.h"
@@ -44,135 +45,180 @@ uint16 global_smbpid;
/* the locking database handle */
static TDB_CONTEXT *tdb;
-struct locking_data {
- union {
- struct {
- int num_share_mode_entries;
- BOOL delete_on_close;
- } s;
- struct share_mode_entry dummy; /* Needed for alignment. */
- } u;
- /* the following two entries are implicit
- struct share_mode_entry modes[num_share_mode_entries];
- char file_name[];
- */
-};
-
/****************************************************************************
- Debugging aid :-).
+ Debugging aids :-).
****************************************************************************/
-static const char *lock_type_name(enum brl_type lock_type)
+const char *lock_type_name(enum brl_type lock_type)
+{
+ switch (lock_type) {
+ case READ_LOCK:
+ return "READ";
+ case WRITE_LOCK:
+ return "WRITE";
+ case PENDING_LOCK:
+ return "PENDING";
+ default:
+ return "other";
+ }
+}
+
+const char *lock_flav_name(enum brl_flavour lock_flav)
{
- return (lock_type == READ_LOCK) ? "READ" : "WRITE";
+ return (lock_flav == WINDOWS_LOCK) ? "WINDOWS_LOCK" : "POSIX_LOCK";
}
/****************************************************************************
Utility function called to see if a file region is locked.
+ Called in the read/write codepath.
****************************************************************************/
-BOOL is_locked(files_struct *fsp,connection_struct *conn,
- SMB_BIG_UINT count,SMB_BIG_UINT offset,
- enum brl_type lock_type)
+BOOL is_locked(files_struct *fsp,
+ SMB_BIG_UINT count,
+ SMB_BIG_UINT offset,
+ enum brl_type lock_type)
{
- int snum = SNUM(conn);
+ int snum = SNUM(fsp->conn);
int strict_locking = lp_strict_locking(snum);
- BOOL ret;
+ enum brl_flavour lock_flav = lp_posix_cifsu_locktype();
+ BOOL ret = True;
- if (count == 0)
- return(False);
+ if (count == 0) {
+ return False;
+ }
- if (!lp_locking(snum) || !strict_locking)
- return(False);
+ if (!lp_locking(snum) || !strict_locking) {
+ return False;
+ }
if (strict_locking == Auto) {
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name ));
- ret = 0;
+ ret = False;
} else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
(lock_type == READ_LOCK)) {
DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
- ret = 0;
+ ret = False;
} else {
- ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
- global_smbpid, procid_self(), conn->cnum,
- offset, count, lock_type);
+ struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ if (!br_lck) {
+ return False;
+ }
+ ret = !brl_locktest(br_lck,
+ global_smbpid,
+ procid_self(),
+ offset,
+ count,
+ lock_type,
+ lock_flav);
+ byte_range_lock_destructor(br_lck);
}
} else {
- ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
- global_smbpid, procid_self(), conn->cnum,
- offset, count, lock_type);
+ struct byte_range_lock *br_lck = brl_get_locks(fsp);
+ if (!br_lck) {
+ return False;
+ }
+ ret = !brl_locktest(br_lck,
+ global_smbpid,
+ procid_self(),
+ offset,
+ count,
+ lock_type,
+ lock_flav);
+ byte_range_lock_destructor(br_lck);
}
- DEBUG(10,("is_locked: brl start=%.0f len=%.0f %s for file %s\n",
+ DEBUG(10,("is_locked: flavour = %s brl start=%.0f len=%.0f %s for fnum %d file %s\n",
+ lock_flav_name(lock_flav),
(double)offset, (double)count, ret ? "locked" : "unlocked",
- fsp->fsp_name ));
+ fsp->fnum, fsp->fsp_name ));
- /*
- * There is no lock held by an SMB daemon, check to
- * see if there is a POSIX lock from a UNIX or NFS process.
- */
+ return ret;
+}
- if(!ret && lp_posix_locking(snum)) {
- ret = is_posix_locked(fsp, offset, count, lock_type);
+/****************************************************************************
+ Find out if a lock could be granted - return who is blocking us if we can't.
+****************************************************************************/
+
+NTSTATUS query_lock(files_struct *fsp,
+ uint16 *psmbpid,
+ SMB_BIG_UINT *pcount,
+ SMB_BIG_UINT *poffset,
+ enum brl_type *plock_type,
+ enum brl_flavour lock_flav)
+{
+ 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;
+ }
- DEBUG(10,("is_locked: posix start=%.0f len=%.0f %s for file %s\n",
- (double)offset, (double)count, ret ? "locked" : "unlocked",
- fsp->fsp_name ));
+ if (!lp_locking(SNUM(fsp->conn))) {
+ return NT_STATUS_OK;
}
- return ret;
+ br_lck = brl_get_locks(fsp);
+ if (!br_lck) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = brl_lockquery(br_lck,
+ psmbpid,
+ procid_self(),
+ poffset,
+ pcount,
+ plock_type,
+ lock_flav);
+
+ byte_range_lock_destructor(br_lck);
+ return status;
}
/****************************************************************************
Utility function called by locking requests.
****************************************************************************/
-static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
- SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
+NTSTATUS do_lock(files_struct *fsp,
+ uint16 lock_pid,
+ SMB_BIG_UINT count,
+ SMB_BIG_UINT offset,
+ enum brl_type lock_type,
+ enum brl_flavour lock_flav,
+ BOOL *my_lock_ctx)
{
+ struct byte_range_lock *br_lck = NULL;
NTSTATUS status = NT_STATUS_LOCK_NOT_GRANTED;
- if (!lp_locking(SNUM(conn)))
+ if (!OPEN_FSP(fsp) || !fsp->can_lock) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ if (!lp_locking(SNUM(fsp->conn))) {
return NT_STATUS_OK;
+ }
/* NOTE! 0 byte long ranges ARE allowed and should be stored */
- DEBUG(10,("do_lock: lock type %s start=%.0f len=%.0f requested for file %s\n",
- lock_type_name(lock_type), (double)offset, (double)count, fsp->fsp_name ));
-
- if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
- status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
- lock_pid, procid_self(), conn->cnum,
- offset, count,
- lock_type, my_lock_ctx);
-
- if (NT_STATUS_IS_OK(status) && lp_posix_locking(SNUM(conn))) {
-
- /*
- * Try and get a POSIX lock on this range.
- * Note that this is ok if it is a read lock
- * overlapping on a different fd. JRA.
- */
-
- if (!set_posix_lock(fsp, offset, count, lock_type)) {
- if (errno == EACCES || errno == EAGAIN)
- status = NT_STATUS_FILE_LOCK_CONFLICT;
- else
- status = map_nt_error_from_unix(errno);
-
- /*
- * We failed to map - we must now remove the brl
- * lock entry.
- */
- (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- lock_pid, procid_self(), conn->cnum,
- offset, count, False,
- NULL, NULL);
- }
- }
+ DEBUG(10,("do_lock: lock flavour %s lock type %s start=%.0f len=%.0f requested for fnum %d file %s\n",
+ 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);
+ if (!br_lck) {
+ return NT_STATUS_NO_MEMORY;
}
+ status = brl_lock(br_lck,
+ lock_pid,
+ procid_self(),
+ offset,
+ count,
+ lock_type,
+ lock_flav,
+ my_lock_ctx);
+
+ byte_range_lock_destructor(br_lck);
return status;
}
@@ -183,20 +229,33 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
it, we need this. JRA.
****************************************************************************/
-NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
- SMB_BIG_UINT count,SMB_BIG_UINT offset,enum brl_type lock_type, BOOL *my_lock_ctx)
+NTSTATUS do_lock_spin(files_struct *fsp,
+ uint16 lock_pid,
+ SMB_BIG_UINT count,
+ SMB_BIG_UINT offset,
+ enum brl_type lock_type,
+ enum brl_flavour lock_flav,
+ BOOL *my_lock_ctx)
{
int j, maxj = lp_lock_spin_count();
int sleeptime = lp_lock_sleep_time();
NTSTATUS status, ret;
- if (maxj <= 0)
+ if (maxj <= 0) {
maxj = 1;
+ }
ret = NT_STATUS_OK; /* to keep dumb compilers happy */
for (j = 0; j < maxj; j++) {
- status = do_lock(fsp, conn, lock_pid, count, offset, lock_type, my_lock_ctx);
+ 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;
@@ -205,72 +264,66 @@ NTSTATUS do_lock_spin(files_struct *fsp,connection_struct *conn, uint16 lock_pid
if (j == 0) {
ret = status;
/* Don't spin if we blocked ourselves. */
- if (*my_lock_ctx)
+ if (*my_lock_ctx) {
+ return ret;
+ }
+
+ /* Only spin for Windows locks. */
+ if (lock_flav == POSIX_LOCK) {
return ret;
+ }
}
- if (sleeptime)
+
+ if (sleeptime) {
sys_usleep(sleeptime);
+ }
}
return ret;
}
-/* Struct passed to brl_unlock. */
-struct posix_unlock_data_struct {
- files_struct *fsp;
- SMB_BIG_UINT offset;
- SMB_BIG_UINT count;
-};
-
-/****************************************************************************
- Function passed to brl_unlock to allow POSIX unlock to be done first.
-****************************************************************************/
-
-static void posix_unlock(void *pre_data)
-{
- struct posix_unlock_data_struct *pdata = (struct posix_unlock_data_struct *)pre_data;
-
- if (lp_posix_locking(SNUM(pdata->fsp->conn)))
- release_posix_lock(pdata->fsp, pdata->offset, pdata->count);
-}
-
/****************************************************************************
Utility function called by unlocking requests.
****************************************************************************/
-NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
- SMB_BIG_UINT count,SMB_BIG_UINT offset)
+NTSTATUS do_unlock(files_struct *fsp,
+ uint16 lock_pid,
+ SMB_BIG_UINT count,
+ SMB_BIG_UINT offset,
+ enum brl_flavour lock_flav)
{
BOOL ok = False;
- struct posix_unlock_data_struct posix_data;
+ struct byte_range_lock *br_lck = NULL;
- if (!lp_locking(SNUM(conn)))
+ if (!lp_locking(SNUM(fsp->conn))) {
return NT_STATUS_OK;
+ }
- if (!OPEN_FSP(fsp) || !fsp->can_lock || (fsp->conn != conn)) {
+ if (!OPEN_FSP(fsp) || !fsp->can_lock) {
return NT_STATUS_INVALID_HANDLE;
}
- DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for file %s\n",
- (double)offset, (double)count, fsp->fsp_name ));
-
- /*
- * Remove the existing lock record from the tdb lockdb
- * before looking at POSIX locks. If this record doesn't
- * match then don't bother looking to remove POSIX locks.
- */
+ 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 ));
- posix_data.fsp = fsp;
- posix_data.offset = offset;
- posix_data.count = count;
+ br_lck = brl_get_locks(fsp);
+ if (!br_lck) {
+ return NT_STATUS_NO_MEMORY;
+ }
- ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- lock_pid, procid_self(), conn->cnum, offset, count,
- False, posix_unlock, (void *)&posix_data);
+ ok = brl_unlock(br_lck,
+ lock_pid,
+ procid_self(),
+ offset,
+ count,
+ lock_flav);
+ byte_range_lock_destructor(br_lck);
+
if (!ok) {
DEBUG(10,("do_unlock: returning ERRlock.\n" ));
return NT_STATUS_RANGE_NOT_LOCKED;
}
+
return NT_STATUS_OK;
}
@@ -280,6 +333,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
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)))
@@ -289,13 +343,14 @@ void locking_close_file(files_struct *fsp)
* Just release all the brl locks, no need to release individually.
*/
- brl_close(fsp->dev, fsp->inode, pid, fsp->conn->cnum, fsp->fnum);
+ 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.
- */
+ /* Release all the POSIX locks.*/
posix_locking_close_file(fsp);
}
@@ -315,7 +370,8 @@ BOOL locking_init(int read_only)
return True;
tdb = tdb_open_log(lock_path("locking.tdb"),
- SMB_OPEN_DATABASE_TDB_HASH_SIZE, TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
+ lp_open_files_db_hash_size(),
+ TDB_DEFAULT|(read_only?0x0:TDB_CLEAR_IF_FIRST),
read_only?O_RDONLY:O_RDWR|O_CREAT,
0644);
@@ -428,34 +484,36 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
int i;
if (dbuf.dsize < sizeof(struct locking_data)) {
- DEBUG(0, ("parse_share_modes: buffer too short\n"));
- return False;
+ smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
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, "
- "num_share_modes: %d\n", lck->delete_on_close,
- lck->num_share_modes));
+ "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)) {
DEBUG(0, ("invalid number of share modes: %d\n",
lck->num_share_modes));
- return False;
+ smb_panic("PANIC: invalid number of share modes");
}
lck->share_modes = NULL;
-
+
if (lck->num_share_modes != 0) {
if (dbuf.dsize < (sizeof(struct locking_data) +
(lck->num_share_modes *
sizeof(struct share_mode_entry)))) {
- DEBUG(0, ("parse_share_modes: buffer too short\n"));
- return False;
+ smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data),
@@ -463,20 +521,68 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
sizeof(struct share_mode_entry));
if (lck->share_modes == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return False;
+ smb_panic("talloc failed\n");
}
}
+ /* Get any delete token. */
+ if (data->u.s.delete_token_size) {
+ char *p = dbuf.dptr + sizeof(*data) +
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry));
+
+ if ((data->u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) ||
+ ((data->u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) {
+ DEBUG(0, ("parse_share_modes: invalid token size %d\n",
+ data->u.s.delete_token_size));
+ smb_panic("parse_share_modes: invalid token size\n");
+ }
+
+ lck->delete_token = TALLOC_P(lck, UNIX_USER_TOKEN);
+ if (!lck->delete_token) {
+ smb_panic("talloc failed\n");
+ }
+
+ /* Copy out the uid and gid. */
+ memcpy(&lck->delete_token->uid, p, sizeof(uid_t));
+ p += sizeof(uid_t);
+ memcpy(&lck->delete_token->gid, p, sizeof(gid_t));
+ p += sizeof(gid_t);
+
+ /* Any supplementary groups ? */
+ lck->delete_token->ngroups = (data->u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ?
+ ((data->u.s.delete_token_size -
+ (sizeof(uid_t) + sizeof(gid_t)))/sizeof(gid_t)) : 0;
+
+ if (lck->delete_token->ngroups) {
+ /* Make this a talloc child of lck->delete_token. */
+ lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t,
+ lck->delete_token->ngroups);
+ if (!lck->delete_token) {
+ smb_panic("talloc failed\n");
+ }
+
+ for (i = 0; i < lck->delete_token->ngroups; i++) {
+ memcpy(&lck->delete_token->groups[i], p, sizeof(gid_t));
+ p += sizeof(gid_t);
+ }
+ }
+
+ } else {
+ lck->delete_token = NULL;
+ }
+
/* Save off the associated service path and filename. */
lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
- (lck->num_share_modes *
- sizeof(struct share_mode_entry)));
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry)) +
+ data->u.s.delete_token_size );
lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
- (lck->num_share_modes *
- sizeof(struct share_mode_entry)) +
- strlen(lck->servicepath) + 1 );
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry)) +
+ data->u.s.delete_token_size +
+ strlen(lck->servicepath) + 1 );
/*
* Ensure that each entry has a real process attached.
@@ -505,6 +611,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
struct locking_data *data;
ssize_t offset;
ssize_t sp_len;
+ uint32 delete_token_size;
result.dptr = NULL;
result.dsize = 0;
@@ -520,9 +627,12 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
}
sp_len = strlen(lck->servicepath);
+ delete_token_size = (lck->delete_token ?
+ (sizeof(uid_t) + sizeof(gid_t) + (lck->delete_token->ngroups*sizeof(gid_t))) : 0);
result.dsize = sizeof(*data) +
lck->num_share_modes * sizeof(struct share_mode_entry) +
+ delete_token_size +
sp_len + 1 +
strlen(lck->filename) + 1;
result.dptr = talloc_size(lck, result.dsize);
@@ -535,13 +645,34 @@ 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;
- DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n",
- data->u.s.delete_on_close,
- data->u.s.num_share_mode_entries));
+ 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",
+ 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,
sizeof(struct share_mode_entry)*lck->num_share_modes);
offset = sizeof(*data) +
sizeof(struct share_mode_entry)*lck->num_share_modes;
+
+ /* Store any delete on close token. */
+ if (lck->delete_token) {
+ char *p = result.dptr + offset;
+
+ memcpy(p, &lck->delete_token->uid, sizeof(uid_t));
+ p += sizeof(uid_t);
+
+ memcpy(p, &lck->delete_token->gid, sizeof(gid_t));
+
+ for (i = 0; i < lck->delete_token->ngroups; i++) {
+ memcpy(p, &lck->delete_token->groups[i], sizeof(gid_t));
+ p += sizeof(gid_t);
+ }
+ offset = p - result.dptr;
+ }
+
safe_strcpy(result.dptr + offset, lck->servicepath,
result.dsize - offset - 1);
offset += sp_len + 1;
@@ -589,9 +720,9 @@ static int share_mode_lock_destructor(void *p)
}
struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
- SMB_DEV_T dev, SMB_INO_T ino,
+ SMB_DEV_T dev, SMB_INO_T ino,
const char *servicepath,
- const char *fname)
+ const char *fname)
{
struct share_mode_lock *lck;
TDB_DATA key = locking_key(dev, ino);
@@ -612,13 +743,15 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
lck->ino = ino;
lck->num_share_modes = 0;
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;
if (tdb_chainlock(tdb, key) != 0) {
DEBUG(3, ("Could not lock share entry\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
@@ -634,20 +767,20 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
if (lck->fresh) {
if (fname == NULL || servicepath == NULL) {
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
lck->filename = talloc_strdup(lck, fname);
lck->servicepath = talloc_strdup(lck, servicepath);
if (lck->filename == NULL || lck->servicepath == NULL) {
DEBUG(0, ("talloc failed\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
} else {
if (!parse_share_modes(data, lck)) {
DEBUG(0, ("Could not parse share modes\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
SAFE_FREE(data.dptr);
return NULL;
}
@@ -658,8 +791,92 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
return lck;
}
-BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode,
- const char *fname)
+/*******************************************************************
+ Sets the service name and filename for rename.
+ At this point we emit "file renamed" messages to all
+ process id's that have this file open.
+ Based on an initial code idea from SATOH Fumiyasu <fumiya@samba.gr.jp>
+********************************************************************/
+
+BOOL rename_share_filename(struct share_mode_lock *lck,
+ const char *servicepath,
+ const char *newname)
+{
+ size_t sp_len;
+ size_t fn_len;
+ size_t msg_len;
+ char *frm = NULL;
+ int i;
+
+ if (!lck) {
+ return False;
+ }
+
+ DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n",
+ servicepath, newname));
+
+ /*
+ * rename_internal_fsp() and rename_internals() add './' to
+ * head of newname if newname does not contain a '/'.
+ */
+ while (newname[0] && newname[1] && newname[0] == '.' && newname[1] == '/') {
+ newname += 2;
+ }
+
+ lck->servicepath = talloc_strdup(lck, servicepath);
+ lck->filename = talloc_strdup(lck, newname);
+ if (lck->filename == NULL || lck->servicepath == NULL) {
+ DEBUG(0, ("rename_share_filename: talloc failed\n"));
+ return False;
+ }
+ lck->modified = True;
+
+ sp_len = strlen(lck->servicepath);
+ fn_len = strlen(lck->filename);
+
+ msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1;
+
+ /* Set up the name changed message. */
+ frm = TALLOC(lck, msg_len);
+ if (!frm) {
+ return False;
+ }
+
+ SDEV_T_VAL(frm,0,lck->dev);
+ SINO_T_VAL(frm,8,lck->ino);
+
+ DEBUG(10,("rename_share_filename: msg_len = %d\n", msg_len ));
+
+ safe_strcpy(&frm[16], lck->servicepath, sp_len);
+ safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len);
+
+ /* Send the messages. */
+ for (i=0; i<lck->num_share_modes; i++) {
+ struct share_mode_entry *se = &lck->share_modes[i];
+ if (!is_valid_share_mode_entry(se)) {
+ continue;
+ }
+ /* But not to ourselves... */
+ if (procid_is_me(&se->pid)) {
+ continue;
+ }
+
+ DEBUG(10,("rename_share_filename: sending rename message to pid %u "
+ "dev %x, inode %.0f sharepath %s newname %s\n",
+ (unsigned int)procid_to_pid(&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;
+}
+
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
{
BOOL result;
struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL);
@@ -667,7 +884,7 @@ BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode,
return False;
}
result = lck->delete_on_close;
- talloc_free(lck);
+ TALLOC_FREE(lck);
return result;
}
@@ -835,7 +1052,7 @@ BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
{
struct share_mode_entry entry, *e;
- fill_share_mode_entry(&entry, fsp, 0, 0);
+ fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK);
e = find_share_mode_entry(lck, &entry);
if (e == NULL) {
@@ -871,7 +1088,7 @@ BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
{
struct share_mode_entry entry, *e;
- fill_share_mode_entry(&entry, fsp, 0, 0);
+ fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK);
e = find_share_mode_entry(lck, &entry);
if (e == NULL) {
@@ -892,7 +1109,7 @@ BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
{
struct share_mode_entry entry, *e;
- fill_share_mode_entry(&entry, fsp, 0, 0);
+ fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK);
e = find_share_mode_entry(lck, &entry);
if (e == NULL) {
@@ -955,6 +1172,55 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
return NT_STATUS_OK;
}
+/*************************************************************************
+ Return a talloced copy of a UNIX_USER_TOKEN. NULL on fail.
+ (Should this be in locking.c.... ?).
+*************************************************************************/
+
+static UNIX_USER_TOKEN *copy_unix_token(TALLOC_CTX *ctx, UNIX_USER_TOKEN *tok)
+{
+ UNIX_USER_TOKEN *cpy;
+
+ if (tok == NULL) {
+ return NULL;
+ }
+
+ cpy = TALLOC_P(ctx, UNIX_USER_TOKEN);
+ if (!cpy) {
+ return NULL;
+ }
+
+ cpy->uid = tok->uid;
+ cpy->gid = tok->gid;
+ cpy->ngroups = tok->ngroups;
+ if (tok->ngroups) {
+ /* Make this a talloc child of cpy. */
+ cpy->groups = TALLOC_ARRAY(cpy, gid_t, tok->ngroups);
+ if (!cpy->groups) {
+ return NULL;
+ }
+ memcpy(cpy->groups, tok->groups, tok->ngroups * sizeof(gid_t));
+ }
+ return cpy;
+}
+
+/****************************************************************************
+ Replace the delete on close token.
+****************************************************************************/
+
+void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok)
+{
+ /* Ensure there's no token. */
+ if (lck->delete_token) {
+ TALLOC_FREE(lck->delete_token); /* Also deletes groups... */
+ lck->delete_token = NULL;
+ }
+
+ /* Copy the new token (can be NULL). */
+ lck->delete_token = copy_unix_token(lck, tok);
+ lck->modified = True;
+}
+
/****************************************************************************
Sets the delete on close flag over all share modes on this file.
Modify the share mode entry for all files open
@@ -962,9 +1228,12 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
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.
****************************************************************************/
-BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
+BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok)
{
struct share_mode_lock *lck;
@@ -981,12 +1250,22 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
if (lck == NULL) {
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;
}
- talloc_free(lck);
+ if (lck->initial_delete_on_close) {
+ lck->initial_delete_on_close = False;
+ lck->modified = True;
+ }
+
+ TALLOC_FREE(lck);
return True;
}
@@ -1007,9 +1286,11 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
data = (struct locking_data *)dbuf.dptr;
shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data));
sharepath = dbuf.dptr + sizeof(*data) +
- data->u.s.num_share_mode_entries*sizeof(*shares);
+ data->u.s.num_share_mode_entries*sizeof(*shares) +
+ data->u.s.delete_token_size;
fname = dbuf.dptr + sizeof(*data) +
data->u.s.num_share_mode_entries*sizeof(*shares) +
+ data->u.s.delete_token_size +
strlen(sharepath) + 1;
for (i=0;i<data->u.s.num_share_mode_entries;i++) {
diff --git a/source/locking/posix.c b/source/locking/posix.c
index c63992adc59..e7075c57a64 100644
--- a/source/locking/posix.c
+++ b/source/locking/posix.c
@@ -99,20 +99,17 @@ static BOOL add_fd_to_close_entry(files_struct *fsp)
{
TDB_DATA kbuf = locking_key_fsp(fsp);
TDB_DATA dbuf;
- char *tp;
dbuf.dptr = NULL;
dbuf.dsize = 0;
dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
- tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
- if (!tp) {
+ dbuf.dptr = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
+ if (!dbuf.dptr) {
DEBUG(0,("add_fd_to_close_entry: Realloc fail !\n"));
- SAFE_FREE(dbuf.dptr);
return False;
- } else
- dbuf.dptr = tp;
+ }
memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
dbuf.dsize += sizeof(int);
@@ -358,7 +355,6 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
TDB_DATA kbuf = locking_key_fsp(fsp);
TDB_DATA dbuf;
struct posix_lock pl;
- char *tp;
dbuf.dptr = NULL;
dbuf.dsize = 0;
@@ -376,12 +372,11 @@ static BOOL add_posix_lock_entry(files_struct *fsp, SMB_OFF_T start, SMB_OFF_T s
pl.size = size;
pl.lock_type = lock_type;
- tp = SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(struct posix_lock));
- if (!tp) {
+ 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;
- } else
- dbuf.dptr = tp;
+ }
memcpy(dbuf.dptr + dbuf.dsize, &pl, sizeof(struct posix_lock));
dbuf.dsize += sizeof(struct posix_lock);
@@ -654,7 +649,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
- int ret;
+ BOOL ret;
DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
@@ -687,39 +682,97 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF
}
DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
+ return ret;
+}
+
+/****************************************************************************
+ Actual function that gets POSIX locks. Copes with 64 -> 32 bit cruft and
+ broken NFS implementations.
+****************************************************************************/
+
+static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
+{
+ pid_t pid;
+ BOOL ret;
+
+ DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
+ fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
+
+ ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+
+ if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) {
+
+ DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
+ (double)*poffset,(double)*pcount));
+ DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
+ DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
+
+ /*
+ * If the offset is > 0x7FFFFFFF then this will cause problems on
+ * 32 bit NFS mounted filesystems. Just ignore it.
+ */
+ if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
+ DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
+ return True;
+ }
+
+ if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
+ /* 32 bit NFS file system, retry with smaller offset */
+ DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
+ errno = 0;
+ *pcount &= 0x7fffffff;
+ ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
+ }
+ }
+
+ DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
return ret;
}
+
/****************************************************************************
POSIX function to see if a file region is locked. Returns True if the
region is locked, False otherwise.
****************************************************************************/
-BOOL is_posix_locked(files_struct *fsp, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
+BOOL is_posix_locked(files_struct *fsp,
+ SMB_BIG_UINT *pu_offset,
+ SMB_BIG_UINT *pu_count,
+ enum brl_type *plock_type,
+ enum brl_flavour lock_flav)
{
SMB_OFF_T offset;
SMB_OFF_T count;
- int posix_lock_type = map_posix_lock_type(fsp,lock_type);
+ int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
- fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
+ fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
/*
* If the requested lock won't fit in the POSIX range, we will
* never set it, so presume it is not locked.
*/
- if(!posix_lock_in_range(&offset, &count, u_offset, u_count))
+ if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
return False;
+ }
- /*
- * Note that most UNIX's can *test* for a write lock on
- * a read-only fd, just not *set* a write lock on a read-only
- * fd. So we don't need to use map_lock_type here.
- */
+ if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
+ return False;
+ }
+
+ if (posix_lock_type == F_UNLCK) {
+ return False;
+ }
- return posix_fcntl_lock(fsp,SMB_F_GETLK,offset,count,posix_lock_type);
+ if (lock_flav == POSIX_LOCK) {
+ /* Only POSIX lock queries need to know the details. */
+ *pu_offset = (SMB_BIG_UINT)offset;
+ *pu_count = (SMB_BIG_UINT)count;
+ *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
+ }
+ return True;
}
/*
@@ -959,9 +1012,14 @@ lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size,
/****************************************************************************
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, SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count, enum brl_type lock_type)
+BOOL set_posix_lock(files_struct *fsp,
+ SMB_BIG_UINT u_offset,
+ SMB_BIG_UINT u_count,
+ enum brl_type lock_type,
+ enum brl_flavour lock_flav)
{
SMB_OFF_T offset;
SMB_OFF_T count;
diff --git a/source/modules/vfs_fake_perms.c b/source/modules/vfs_fake_perms.c
index 4d10ea5f337..decbe01d3ca 100644
--- a/source/modules/vfs_fake_perms.c
+++ b/source/modules/vfs_fake_perms.c
@@ -40,8 +40,8 @@ static int fake_perms_stat(vfs_handle_struct *handle, connection_struct *conn, c
} else {
sbuf->st_mode = S_IRWXU;
}
- sbuf->st_uid = current_user.uid;
- sbuf->st_gid = current_user.gid;
+ sbuf->st_uid = current_user.ut.uid;
+ sbuf->st_gid = current_user.ut.gid;
}
return ret;
@@ -58,8 +58,8 @@ static int fake_perms_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd
} else {
sbuf->st_mode = S_IRWXU;
}
- sbuf->st_uid = current_user.uid;
- sbuf->st_gid = current_user.gid;
+ sbuf->st_uid = current_user.ut.uid;
+ sbuf->st_gid = current_user.ut.gid;
}
return ret;
}
diff --git a/source/modules/vfs_full_audit.c b/source/modules/vfs_full_audit.c
index 52e245a1763..309f6d15ae7 100644
--- a/source/modules/vfs_full_audit.c
+++ b/source/modules/vfs_full_audit.c
@@ -161,6 +161,8 @@ 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 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,
const char *oldpath, const char *newpath);
static int smb_full_audit_readlink(vfs_handle_struct *handle, connection_struct *conn,
@@ -399,6 +401,8 @@ 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_getlock), SMB_VFS_OP_GETLOCK,
+ SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_symlink), SMB_VFS_OP_SYMLINK,
SMB_VFS_LAYER_LOGGER},
{SMB_VFS_OP(smb_full_audit_readlink), SMB_VFS_OP_READLINK,
@@ -564,6 +568,7 @@ static struct {
{ SMB_VFS_OP_UTIME, "utime" },
{ SMB_VFS_OP_FTRUNCATE, "ftruncate" },
{ SMB_VFS_OP_LOCK, "lock" },
+ { SMB_VFS_OP_GETLOCK, "getlock" },
{ SMB_VFS_OP_SYMLINK, "symlink" },
{ SMB_VFS_OP_READLINK, "readlink" },
{ SMB_VFS_OP_LINK, "link" },
@@ -816,6 +821,10 @@ static int smb_full_audit_connect(vfs_handle_struct *handle, connection_struct *
const char *none[] = { NULL };
const char *all [] = { "all" };
+ if (!handle) {
+ return -1;
+ }
+
pd = SMB_MALLOC_P(struct vfs_full_audit_private_data);
if (!pd) {
return -1;
@@ -1309,6 +1318,18 @@ static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, in
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)
+{
+ BOOL result;
+
+ result = SMB_VFS_NEXT_GETLOCK(handle, fsp, fd, poffset, pcount, ptype, ppid);
+
+ do_log(SMB_VFS_OP_GETLOCK, (result >= 0), handle, "%s", fsp->fsp_name);
+
+ return result;
+}
+
static int smb_full_audit_symlink(vfs_handle_struct *handle, connection_struct *conn,
const char *oldpath, const char *newpath)
{
diff --git a/source/modules/vfs_shadow_copy.c b/source/modules/vfs_shadow_copy.c
index 8bb4598ea3d..db1c8d007dc 100644
--- a/source/modules/vfs_shadow_copy.c
+++ b/source/modules/vfs_shadow_copy.c
@@ -93,8 +93,6 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
while (True) {
SMB_STRUCT_DIRENT *d;
- SMB_STRUCT_DIRENT *r;
-
d = SMB_VFS_NEXT_READDIR(handle, conn, p);
if (d == NULL) {
@@ -108,13 +106,12 @@ static SMB_STRUCT_DIR *shadow_copy_opendir(vfs_handle_struct *handle, connection
DEBUG(10,("shadow_copy_opendir: not hide [%s]\n",d->d_name));
- r = SMB_REALLOC_ARRAY(dirp->dirs,SMB_STRUCT_DIRENT, dirp->num+1);
- if (!r) {
+ dirp->dirs = SMB_REALLOC_ARRAY(dirp->dirs,SMB_STRUCT_DIRENT, dirp->num+1);
+ if (!dirp->dirs) {
DEBUG(0,("shadow_copy_opendir: Out of memory\n"));
break;
}
- dirp->dirs = r;
dirp->dirs[dirp->num++] = *d;
}
diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c
index cf3d0fcc704..c8caa3fee29 100644
--- a/source/nmbd/asyncdns.c
+++ b/source/nmbd/asyncdns.c
@@ -285,8 +285,7 @@ void run_dns_queue(void)
queue a DNS query
****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
+BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
if (in_dns || fd_in == -1)
return False;
@@ -318,14 +317,13 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
we use this when we can't do async DNS lookups
****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
+BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question)
{
struct name_record *namerec = NULL;
struct in_addr dns_ip;
unstring qname;
- pull_ascii_nstring(qname, question->name);
+ pull_ascii_nstring(qname, sizeof(qname), question->name);
DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 56b113486d2..fca17d1ff7b 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -58,7 +58,7 @@ static void terminate(void)
DEBUG(0,("Got SIGTERM: going down...\n"));
/* Write out wins.dat file if samba is a WINS server */
- wins_write_database(False);
+ wins_write_database(0,False);
/* Remove all SELF registered names from WINS */
release_wins_names();
@@ -106,46 +106,6 @@ static void sig_hup(int sig)
sys_select_signal(SIGHUP);
}
-#if DUMP_CORE
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
- char *p;
- pstring dname;
- pstrcpy( dname, lp_logfile() );
- if ((p=strrchr_m(dname,'/')))
- *p=0;
- pstrcat( dname, "/corefiles" );
- mkdir( dname, 0700 );
- sys_chown( dname, getuid(), getgid() );
- chmod( dname, 0700 );
- if ( chdir(dname) )
- return( False );
- umask( ~(0700) );
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
- {
- struct rlimit rlp;
- getrlimit( RLIMIT_CORE, &rlp );
- rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
- setrlimit( RLIMIT_CORE, &rlp );
- getrlimit( RLIMIT_CORE, &rlp );
- DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
- }
-#endif
-#endif
-
-
- DEBUG(0,("Dumping core in %s\n",dname));
- abort();
- return( True );
-}
-#endif
-
/**************************************************************************** **
Possibly continue after a fault.
**************************************************************************** */
@@ -291,7 +251,7 @@ static BOOL reload_nmbd_services(BOOL test)
if ( test && !lp_file_list_changed() )
return(True);
- ret = lp_load( dyn_CONFIGFILE, True , False, False);
+ ret = lp_load( dyn_CONFIGFILE, True , False, False, True);
/* perhaps the config filename is now set */
if ( !test ) {
@@ -607,7 +567,7 @@ static void process(void)
return;
/* free up temp memory */
- lp_talloc_free();
+ lp_TALLOC_FREE();
}
}
@@ -658,11 +618,13 @@ static BOOL open_sockets(BOOL isdaemon, int port)
static BOOL opt_interactive;
poptContext pc;
static char *p_lmhosts = dyn_LMHOSTSFILE;
+ static BOOL no_process_group = False;
struct poptOption long_options[] = {
POPT_AUTOHELP
{"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
{"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
{"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
+ {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
{"hosts", 'H', POPT_ARG_STRING, &p_lmhosts, 'H', "Load a netbios hosts file"},
{"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
@@ -690,6 +652,7 @@ static BOOL open_sockets(BOOL isdaemon, int port)
}
fault_setup((void (*)(void *))fault_continue );
+ dump_core_setup("nmbd");
/* POSIX demands that signals are inherited. If the invoking process has
* these signals masked, we will have problems, as we won't receive them. */
@@ -749,7 +712,7 @@ static BOOL open_sockets(BOOL isdaemon, int port)
if (is_daemon && !opt_interactive) {
DEBUG( 2, ( "Becoming a daemon.\n" ) );
- become_daemon(Fork);
+ become_daemon(Fork, no_process_group);
}
#if HAVE_SETPGID
@@ -757,7 +720,7 @@ static BOOL open_sockets(BOOL isdaemon, int port)
* If we're interactive we want to set our own process group for
* signal management.
*/
- if (opt_interactive)
+ if (opt_interactive && !no_process_group)
setpgid( (pid_t)0, (pid_t)0 );
#endif
diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c
index e8797a99d51..e27e483702a 100644
--- a/source/nmbd/nmbd_browserdb.c
+++ b/source/nmbd/nmbd_browserdb.c
@@ -35,7 +35,7 @@
* lmb_browserlist - This is our local master browser list.
*/
-ubi_dlNewList( lmb_browserlist );
+struct browse_cache_record *lmb_browserlist;
/* -------------------------------------------------------------------------- **
* Functions...
@@ -52,7 +52,8 @@ ubi_dlNewList( lmb_browserlist );
*/
static void remove_lmb_browser_entry( struct browse_cache_record *browc )
{
- safe_free( ubi_dlRemThis( lmb_browserlist, browc ) );
+ DLIST_REMOVE(lmb_browserlist, browc);
+ SAFE_FREE(browc);
}
/* ************************************************************************** **
@@ -85,6 +86,7 @@ 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);
@@ -113,7 +115,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name,
browc->ip = ip;
- (void)ubi_dlAddTail( lmb_browserlist, browc );
+ DLIST_ADD_END(lmb_browserlist, browc, tmp_browc);
if( DEBUGLVL( 3 ) ) {
Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" );
@@ -138,12 +140,13 @@ struct browse_cache_record *find_browser_in_lmb_cache( const char *browser_name
{
struct browse_cache_record *browc;
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc; browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
- if( strequal( browser_name, browc->lmb_name ) )
+ for( browc = lmb_browserlist; browc; browc = browc->next ) {
+ if( strequal( browser_name, browc->lmb_name ) ) {
break;
+ }
+ }
- return( browc );
+ return browc;
}
/* ************************************************************************** **
@@ -160,9 +163,8 @@ void expire_lmb_browsers( time_t t )
struct browse_cache_record *browc;
struct browse_cache_record *nextbrowc;
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc; browc = nextbrowc ) {
- nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc );
+ for( browc = lmb_browserlist; browc; browc = nextbrowc) {
+ nextbrowc = browc->next;
if( browc->death_time < t ) {
if( DEBUGLVL( 3 ) ) {
diff --git a/source/nmbd/nmbd_browsesync.c b/source/nmbd/nmbd_browsesync.c
index 03234bb98fa..9535a3115a6 100644
--- a/source/nmbd/nmbd_browsesync.c
+++ b/source/nmbd/nmbd_browsesync.c
@@ -24,7 +24,7 @@
#include "includes.h"
/* This is our local master browser list database. */
-extern ubi_dlList lmb_browserlist[];
+extern struct browse_cache_record *lmb_browserlist;
/****************************************************************************
As a domain master browser, do a sync with a local master browser.
@@ -87,9 +87,7 @@ void dmb_expire_and_sync_browser_lists(time_t t)
expire_lmb_browsers(t);
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc;
- browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) {
+ for( browc = lmb_browserlist; browc; browc = browc->next ) {
if (browc->sync_time < t)
sync_with_lmb(browc);
}
diff --git a/source/nmbd/nmbd_incomingdgrams.c b/source/nmbd/nmbd_incomingdgrams.c
index 53b19471572..09eb7bfa86b 100644
--- a/source/nmbd/nmbd_incomingdgrams.c
+++ b/source/nmbd/nmbd_incomingdgrams.c
@@ -108,7 +108,6 @@ void process_host_announce(struct subnet_record *subrec, struct packet_struct *p
START_PROFILE(host_announce);
pull_ascii_fstring(comment, buf+31);
- comment[42] = 0;
pull_ascii_nstring(announce_name, sizeof(announce_name), buf+5);
pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
@@ -267,7 +266,6 @@ void process_local_master_announce(struct subnet_record *subrec, struct packet_s
pull_ascii_nstring(server_name,sizeof(server_name),buf+5);
pull_ascii_fstring(comment, buf+31);
- comment[42] = 0;
pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name);
pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name);
diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c
index 7fac8c25739..eaef7097b4a 100644
--- a/source/nmbd/nmbd_incomingrequests.c
+++ b/source/nmbd/nmbd_incomingrequests.c
@@ -339,7 +339,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
names_added = 0;
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
+ namerec = subrec->namelist;
while (buf < bufend) {
if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
@@ -389,7 +389,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
buf = buf0 + 18*names_added;
- namerec = (struct name_record *)ubi_trNext( namerec );
+ namerec = namerec->next;
if (!namerec) {
/* End of the subnet specific name list. Now
@@ -398,7 +398,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
if (uni_subrec != subrec) {
subrec = uni_subrec;
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
+ namerec = subrec->namelist;
}
}
if (!namerec)
diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c
index 07247d5495e..f34d98172c6 100644
--- a/source/nmbd/nmbd_mynames.c
+++ b/source/nmbd/nmbd_mynames.c
@@ -182,8 +182,8 @@ void release_wins_names(void)
struct subnet_record *subrec = unicast_subnet;
struct name_record *namerec, *nextnamerec;
- for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = nextnamerec) {
- nextnamerec = (struct name_record *)ubi_trNext( namerec );
+ for (namerec = subrec->namelist; namerec; namerec = nextnamerec) {
+ nextnamerec = namerec->next;
if( (namerec->data.source == SELF_NAME)
&& !NAME_IS_DEREGISTERING(namerec) )
release_name( subrec, namerec, standard_success_release,
@@ -202,9 +202,7 @@ void refresh_my_names(time_t t)
if (wins_srv_count() < 1)
return;
- for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist);
- namerec;
- namerec = (struct name_record *)ubi_trNext(namerec)) {
+ for (namerec = unicast_subnet->namelist; namerec; namerec = namerec->next) {
/* Each SELF name has an individual time to be refreshed. */
if ((namerec->data.source == SELF_NAME) &&
(namerec->data.refresh_time < t) &&
diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c
index 710fc400b64..60023a7ed5e 100644
--- a/source/nmbd/nmbd_namelistdb.c
+++ b/source/nmbd/nmbd_namelistdb.c
@@ -77,30 +77,19 @@ static void upcase_name( struct nmb_name *target, const struct nmb_name *source
Remove a name from the namelist.
***************************************************************************/
-static void update_name_in_namelist( struct subnet_record *subrec,
- struct name_record *namerec )
+void remove_name_from_namelist(struct subnet_record *subrec,
+ struct name_record *namerec )
{
- struct name_record *oldrec = NULL;
-
- ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec );
- if( oldrec ) {
- SAFE_FREE( oldrec->data.ip );
- SAFE_FREE( oldrec );
+ if (subrec == wins_server_subnet)
+ remove_name_from_wins_namelist(namerec);
+ else {
+ subrec->namelist_changed = True;
+ DLIST_REMOVE(subrec->namelist, namerec);
}
-}
-
-/**************************************************************************
- Remove a name from the namelist.
-***************************************************************************/
-void remove_name_from_namelist( struct subnet_record *subrec,
- struct name_record *namerec )
-{
- ubi_trRemove( subrec->namelist, namerec );
SAFE_FREE(namerec->data.ip);
ZERO_STRUCTP(namerec);
SAFE_FREE(namerec);
- subrec->namelist_changed = True;
}
/**************************************************************************
@@ -111,17 +100,27 @@ struct name_record *find_name_on_subnet(struct subnet_record *subrec,
const struct nmb_name *nmbname,
BOOL self_only)
{
- struct nmb_name uc_name[1];
+ struct nmb_name uc_name;
struct name_record *name_ret;
- upcase_name( uc_name, nmbname );
- name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name );
+ upcase_name( &uc_name, nmbname );
+
+ if (subrec == wins_server_subnet) {
+ return find_name_on_wins_subnet(&uc_name, self_only);
+ }
+
+ for( name_ret = subrec->namelist; name_ret; name_ret = name_ret->next) {
+ if (memcmp(&uc_name, &name_ret->name, sizeof(struct nmb_name)) == 0) {
+ break;
+ }
+ }
+
if( name_ret ) {
/* Self names only - these include permanent names. */
if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) {
DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
subrec->subnet_name, nmb_namestr(nmbname) ) );
- return( NULL );
+ return False;
}
DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
@@ -170,29 +169,34 @@ void update_name_ttl( struct name_record *namerec, int ttl )
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
- namerec->subnet->namelist_changed = True;
+ if (namerec->subnet == wins_server_subnet) {
+ wins_store_changed_namerec(namerec);
+ } else {
+ namerec->subnet->namelist_changed = True;
+ }
}
/**************************************************************************
Add an entry to a subnet name list.
***********************************************************************/
-struct name_record *add_name_to_subnet( struct subnet_record *subrec,
- const char *name,
- int type,
- uint16 nb_flags,
- int ttl,
- enum name_source source,
- int num_ips,
- struct in_addr *iplist)
+BOOL add_name_to_subnet( struct subnet_record *subrec,
+ const char *name,
+ int type,
+ uint16 nb_flags,
+ int ttl,
+ enum name_source source,
+ int num_ips,
+ struct in_addr *iplist)
{
+ BOOL ret = False;
struct name_record *namerec;
time_t time_now = time(NULL);
namerec = SMB_MALLOC_P(struct name_record);
if( NULL == namerec ) {
DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
- return( NULL );
+ return False;
}
memset( (char *)namerec, '\0', sizeof(*namerec) );
@@ -201,7 +205,7 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
ZERO_STRUCTP(namerec);
SAFE_FREE(namerec);
- return NULL;
+ return False;
}
namerec->subnet = subrec;
@@ -234,9 +238,6 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec,
namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
- /* Now add the record to the name list. */
- update_name_in_namelist( subrec, namerec );
-
DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
ttl=%d nb_flags=%2x to subnet %s\n",
nmb_namestr( &namerec->name ),
@@ -245,9 +246,20 @@ ttl=%d nb_flags=%2x to subnet %s\n",
(unsigned int)nb_flags,
subrec->subnet_name ) );
- subrec->namelist_changed = True;
+ /* Now add the record to the name list. */
+
+ if (subrec == wins_server_subnet) {
+ ret = add_name_to_wins_subnet(namerec);
+ /* Free namerec - it's stored in the tdb. */
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+ } else {
+ DLIST_ADD(subrec->namelist, namerec);
+ subrec->namelist_changed = True;
+ ret = True;
+ }
- return(namerec);
+ return ret;
}
/*******************************************************************
@@ -311,7 +323,11 @@ static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
}
namerec->data.num_ips--;
- namerec->subnet->namelist_changed = True;
+ if (namerec->subnet == wins_server_subnet) {
+ wins_store_changed_namerec(namerec);
+ } else {
+ namerec->subnet->namelist_changed = True;
+ }
}
/*******************************************************************
@@ -357,7 +373,11 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
namerec->data.ip = new_list;
namerec->data.num_ips += 1;
- namerec->subnet->namelist_changed = True;
+ if (namerec->subnet == wins_server_subnet) {
+ wins_store_changed_namerec(namerec);
+ } else {
+ namerec->subnet->namelist_changed = True;
+ }
}
/*******************************************************************
@@ -406,7 +426,7 @@ on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(
if( namerec->data.num_ips == orig_num ) {
DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) );
- }
+ }
}
if( namerec->data.num_ips == 0 ) {
@@ -415,16 +435,17 @@ on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet
}
/*******************************************************************
- Expires old names in a subnet namelist.
+ Expires old names in a subnet namelist.
+ NB. Does not touch the wins_subnet - no wins specific processing here.
******************************************************************/
-void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
+static void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
{
struct name_record *namerec;
struct name_record *next_namerec;
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) {
- next_namerec = (struct name_record *)ubi_trNext( namerec );
+ for( namerec = subrec->namelist; namerec; namerec = next_namerec ) {
+ next_namerec = namerec->next;
if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
if( namerec->data.source == SELF_NAME ) {
DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
@@ -443,7 +464,8 @@ name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) );
}
/*******************************************************************
- Expires old names in all subnet namelists.
+ Expires old names in all subnet namelists.
+ NB. Does not touch the wins_subnet.
******************************************************************/
void expire_names(time_t t)
@@ -505,67 +527,76 @@ void add_samba_names_to_subnet( struct subnet_record *subrec )
Dump a name_record struct.
**************************************************************************/
-static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
+void dump_name_record( struct name_record *namerec, XFILE *fp)
{
- struct name_record *namerec;
const char *src_type;
struct tm *tm;
int i;
- x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec;
- namerec = (struct name_record *)ubi_trNext( namerec ) ) {
-
- x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
- switch(namerec->data.source) {
- case LMHOSTS_NAME:
- src_type = "LMHOSTS_NAME";
- break;
- case WINS_PROXY_NAME:
- src_type = "WINS_PROXY_NAME";
- break;
- case REGISTER_NAME:
- src_type = "REGISTER_NAME";
- break;
- case SELF_NAME:
- src_type = "SELF_NAME";
- break;
- case DNS_NAME:
- src_type = "DNS_NAME";
- break;
- case DNSFAIL_NAME:
- src_type = "DNSFAIL_NAME";
- break;
- case PERMANENT_NAME:
- src_type = "PERMANENT_NAME";
- break;
- default:
- src_type = "unknown!";
- break;
- }
+ x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
+ switch(namerec->data.source) {
+ case LMHOSTS_NAME:
+ src_type = "LMHOSTS_NAME";
+ break;
+ case WINS_PROXY_NAME:
+ src_type = "WINS_PROXY_NAME";
+ break;
+ case REGISTER_NAME:
+ src_type = "REGISTER_NAME";
+ break;
+ case SELF_NAME:
+ src_type = "SELF_NAME";
+ break;
+ case DNS_NAME:
+ src_type = "DNS_NAME";
+ break;
+ case DNSFAIL_NAME:
+ src_type = "DNSFAIL_NAME";
+ break;
+ case PERMANENT_NAME:
+ src_type = "PERMANENT_NAME";
+ break;
+ default:
+ src_type = "unknown!";
+ break;
+ }
- x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
+ x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
- if(namerec->data.death_time != PERMANENT_TTL) {
- tm = localtime(&namerec->data.death_time);
- x_fprintf(fp, "death_time = %s\t", asctime(tm));
- } else {
- x_fprintf(fp, "death_time = PERMANENT\t");
- }
+ if(namerec->data.death_time != PERMANENT_TTL) {
+ tm = localtime(&namerec->data.death_time);
+ x_fprintf(fp, "death_time = %s\t", asctime(tm));
+ } else {
+ x_fprintf(fp, "death_time = PERMANENT\t");
+ }
- if(namerec->data.refresh_time != PERMANENT_TTL) {
- tm = localtime(&namerec->data.refresh_time);
- x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
- } else {
- x_fprintf(fp, "refresh_time = PERMANENT\n");
- }
+ if(namerec->data.refresh_time != PERMANENT_TTL) {
+ tm = localtime(&namerec->data.refresh_time);
+ x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
+ } else {
+ x_fprintf(fp, "refresh_time = PERMANENT\n");
+ }
- x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
+ x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
for(i = 0; i < namerec->data.num_ips; i++) {
- x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
+ x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
}
- x_fprintf(fp, "\n\n");
+ x_fprintf(fp, "\n\n");
+
+}
+
+/****************************************************************************
+ Dump the contents of the namelists on all the subnets (including unicast)
+ into a file. Initiated by SIGHUP - used to debug the state of the namelists.
+**************************************************************************/
+
+static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
+{
+ struct name_record *namerec;
+ x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
+ for( namerec = subrec->namelist; namerec; namerec = namerec->next) {
+ dump_name_record(namerec, fp);
}
}
@@ -587,16 +618,21 @@ void dump_all_namelists(void)
return;
}
- for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
+ for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) {
dump_subnet_namelist( subrec, fp );
+ }
- if( !we_are_a_wins_client() )
+ if (!we_are_a_wins_client()) {
dump_subnet_namelist( unicast_subnet, fp );
+ }
- if( remote_broadcast_subnet->namelist != NULL )
+ if (remote_broadcast_subnet->namelist != NULL) {
dump_subnet_namelist( remote_broadcast_subnet, fp );
+ }
+
+ if (wins_server_subnet != NULL) {
+ dump_wins_subnet_namelist(fp );
+ }
- if( wins_server_subnet != NULL )
- dump_subnet_namelist( wins_server_subnet, fp );
x_fclose( fp );
}
diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c
index c25473c4fba..89362392fe7 100644
--- a/source/nmbd/nmbd_packets.c
+++ b/source/nmbd/nmbd_packets.c
@@ -536,6 +536,8 @@ void queue_wins_refresh(struct nmb_name *nmbname,
userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
if (!userdata) {
+ p->locked = False;
+ free_packet(p);
DEBUG(0,("Failed to allocate userdata structure!\n"));
return;
}
@@ -1668,11 +1670,13 @@ static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_n
if((count*2) + 2 > FD_SETSIZE) {
DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
only use %d.\n", (count*2) + 2, FD_SETSIZE));
+ SAFE_FREE(pset);
return True;
}
if((sock_array = SMB_MALLOC_ARRAY(int, (count*2) + 2)) == NULL) {
DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
+ SAFE_FREE(pset);
return True;
}
diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c
index b53a6d7328f..b2e1178bebc 100644
--- a/source/nmbd/nmbd_subnetdb.c
+++ b/source/nmbd/nmbd_subnetdb.c
@@ -51,34 +51,6 @@ static void add_subnet(struct subnet_record *subrec)
DLIST_ADD(subnetlist, subrec);
}
-/* ************************************************************************** **
- * Comparison routine for ordering the splay-tree based namelists assoicated
- * with each subnet record.
- *
- * Input: Item - Pointer to the comparison key.
- * Node - Pointer to a node the splay tree.
- *
- * Output: The return value will be <0 , ==0, or >0 depending upon the
- * ordinal relationship of the two keys.
- *
- * ************************************************************************** **
- */
-static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
-{
- struct name_record *NR = (struct name_record *)Node;
-
- if( DEBUGLVL( 10 ) ) {
- struct nmb_name *Iname = (struct nmb_name *)Item;
-
- Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
- Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
- memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
- nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
- }
-
- return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
-}
-
/****************************************************************************
stop listening on a subnet
we don't free the record as we don't have proper reference counting for it
@@ -156,10 +128,7 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
return(NULL);
}
- memset( (char *)subrec, '\0', sizeof(*subrec) );
- (void)ubi_trInitTree( subrec->namelist,
- namelist_entry_compare,
- ubi_trOVERWRITE );
+ ZERO_STRUCTP(subrec);
if((subrec->subnet_name = SMB_STRDUP(name)) == NULL) {
DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c
index c01b1ce8bd6..7a28eba77d9 100644
--- a/source/nmbd/nmbd_winsproxy.c
+++ b/source/nmbd/nmbd_winsproxy.c
@@ -47,9 +47,14 @@ static void wins_proxy_name_query_request_success( struct subnet_record *subrec,
memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)],
sizeof(struct packet_struct *) );
- nb_flags = get_nb_flags( rrec->rdata );
+ if (rrec) {
+ nb_flags = get_nb_flags( rrec->rdata );
+ num_ips = rrec->rdlength / 6;
+ } else {
+ nb_flags = 0;
+ num_ips = 0;
+ }
- num_ips = rrec->rdlength / 6;
if(num_ips == 0) {
DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
returned for name %s.\n", nmb_namestr(nmbname) ));
@@ -66,12 +71,12 @@ returned for name %s.\n", nmb_namestr(nmbname) ));
for(i = 0; i < num_ips; i++) {
putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
- }
+ }
}
/* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
- if(rrec == PERMANENT_TTL) {
+ if(rrec->ttl == PERMANENT_TTL) {
ttl = lp_max_ttl();
}
@@ -80,6 +85,10 @@ returned for name %s.\n", nmb_namestr(nmbname) ));
nmbname->name_type, nb_flags, ttl,
WINS_PROXY_NAME, num_ips, iplist );
+ if(iplist != &ip) {
+ SAFE_FREE(iplist);
+ }
+
namerec = find_name_on_subnet(orig_broadcast_subnet, nmbname, FIND_ANY_NAME);
if (!namerec) {
DEBUG(0,("wins_proxy_name_query_request_success: failed to add "
@@ -89,10 +98,6 @@ returned for name %s.\n", nmb_namestr(nmbname) ));
return;
}
- if(iplist != &ip) {
- SAFE_FREE(iplist);
- }
-
/*
* Check that none of the IP addresses we are returning is on the
* same broadcast subnet as the original requesting packet. If it
diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c
index ab71e45bbf1..198d90f35a1 100644
--- a/source/nmbd/nmbd_winsserver.c
+++ b/source/nmbd/nmbd_winsserver.c
@@ -18,12 +18,318 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ Converted to store WINS data in a tdb. Dec 2005. JRA.
*/
#include "includes.h"
#define WINS_LIST "wins.dat"
#define WINS_VERSION 1
+#define WINSDB_VERSION 1
+
+/****************************************************************************
+ We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
+ name (65 bytes with the last byte being the name type).
+*****************************************************************************/
+
+TDB_CONTEXT *wins_tdb;
+
+/****************************************************************************
+ Convert a wins.tdb record to a struct name_record. Add in our global_scope().
+*****************************************************************************/
+
+static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
+{
+ struct name_record *namerec = NULL;
+ uint16 nb_flags;
+ unsigned char nr_src;
+ uint32 death_time, refresh_time;
+ uint32 id_low, id_high;
+ uint32 saddr;
+ uint32 wins_flags;
+ uint32 num_ips;
+ size_t len;
+ int i;
+
+ if (data.dptr == NULL || data.dsize == 0) {
+ return NULL;
+ }
+
+ /* Min size is "wbddddddd" + 1 ip address (4). */
+ if (data.dsize < 2 + 1 + (7*4) + 4) {
+ return NULL;
+ }
+
+ len = tdb_unpack(data.dptr, data.dsize,
+ "wbddddddd",
+ &nb_flags,
+ &nr_src,
+ &death_time,
+ &refresh_time,
+ &id_low,
+ &id_high,
+ &saddr,
+ &wins_flags,
+ &num_ips );
+
+ namerec = SMB_MALLOC_P(struct name_record);
+ if (!namerec) {
+ return NULL;
+ }
+
+ namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
+ if (!namerec->data.ip) {
+ SAFE_FREE(namerec);
+ return NULL;
+ }
+
+ namerec->subnet = wins_server_subnet;
+ push_ascii_nstring(namerec->name.name, key.dptr);
+ namerec->name.name_type = key.dptr[sizeof(unstring)];
+ /* Add the scope. */
+ push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
+
+ /* We're using a byte-by-byte compare, so we must be sure that
+ * unused space doesn't have garbage in it.
+ */
+
+ for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
+ namerec->name.name[i] = '\0';
+ }
+ for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
+ namerec->name.scope[i] = '\0';
+ }
+
+ namerec->data.nb_flags = nb_flags;
+ namerec->data.source = (enum name_source)nr_src;
+ namerec->data.death_time = (time_t)death_time;
+ namerec->data.refresh_time = (time_t)refresh_time;
+ namerec->data.id = id_low;
+#if defined(HAVE_LONGLONG)
+ namerec->data.id |= ((SMB_BIG_UINT)id_high << 32);
+#endif
+ namerec->data.wins_ip.s_addr = saddr;
+ namerec->data.wins_flags = wins_flags,
+ namerec->data.num_ips = num_ips;
+
+ for (i = 0; i < num_ips; i++) {
+ namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
+ }
+
+ return namerec;
+}
+
+/****************************************************************************
+ Convert a struct name_record to a wins.tdb record. Ignore the scope.
+*****************************************************************************/
+
+static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
+{
+ TDB_DATA data;
+ size_t len = 0;
+ int i;
+ uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
+#if defined(HAVE_LONGLONG)
+ uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
+#else
+ uint32 id_high = 0;
+#endif
+
+ ZERO_STRUCT(data);
+
+ len = (2 + 1 + (7*4)); /* "wbddddddd" */
+ len += (namerec->data.num_ips * 4);
+
+ data.dptr = SMB_MALLOC(len);
+ if (!data.dptr) {
+ return data;
+ }
+ data.dsize = len;
+
+ len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
+ namerec->data.nb_flags,
+ (unsigned char)namerec->data.source,
+ (uint32)namerec->data.death_time,
+ (uint32)namerec->data.refresh_time,
+ id_low,
+ id_high,
+ (uint32)namerec->data.wins_ip.s_addr,
+ (uint32)namerec->data.wins_flags,
+ (uint32)namerec->data.num_ips );
+
+ for (i = 0; i < namerec->data.num_ips; i++) {
+ SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
+ }
+
+ return data;
+}
+
+/****************************************************************************
+ Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
+*****************************************************************************/
+
+static TDB_DATA name_to_key(const struct nmb_name *nmbname)
+{
+ static char keydata[sizeof(unstring) + 1];
+ TDB_DATA key;
+
+ memset(keydata, '\0', sizeof(keydata));
+
+ pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
+ strupper_m(keydata);
+ keydata[sizeof(unstring)] = nmbname->name_type;
+ key.dptr = keydata;
+ key.dsize = sizeof(keydata);
+
+ return key;
+}
+
+/****************************************************************************
+ Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
+ on the linked list. We will free this later in XXXX().
+*****************************************************************************/
+
+struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only)
+{
+ TDB_DATA data, key;
+ struct name_record *nr = NULL;
+ struct name_record *namerec = NULL;
+
+ if (!wins_tdb) {
+ return NULL;
+ }
+
+ key = name_to_key(nmbname);
+ data = tdb_fetch(wins_tdb, key);
+
+ if (data.dsize == 0) {
+ return NULL;
+ }
+
+ namerec = wins_record_to_name_record(key, data);
+
+ /* done with the this */
+
+ SAFE_FREE( data.dptr );
+
+ if (!namerec) {
+ return NULL;
+ }
+
+ /* Search for this name record on the list. Replace it if found. */
+
+ for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
+ if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
+ /* Delete it. */
+ DLIST_REMOVE(wins_server_subnet->namelist, nr);
+ SAFE_FREE(nr->data.ip);
+ SAFE_FREE(nr);
+ break;
+ }
+ }
+
+ DLIST_ADD(wins_server_subnet->namelist, namerec);
+ return namerec;
+}
+
+/****************************************************************************
+ Overwrite or add a given name in the wins.tdb.
+*****************************************************************************/
+
+static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
+{
+ TDB_DATA key, data;
+ int ret;
+
+ if (!wins_tdb) {
+ return False;
+ }
+
+ key = name_to_key(&namerec->name);
+ data = name_record_to_wins_record(namerec);
+
+ if (data.dptr == NULL) {
+ return False;
+ }
+
+ ret = tdb_store(wins_tdb, key, data, tdb_flag);
+
+ SAFE_FREE(data.dptr);
+ return (ret == 0) ? True : False;
+}
+
+/****************************************************************************
+ Overwrite a given name in the wins.tdb.
+*****************************************************************************/
+
+BOOL wins_store_changed_namerec(const struct name_record *namerec)
+{
+ return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
+}
+
+/****************************************************************************
+ Primary interface into creating and overwriting records in the wins.tdb.
+*****************************************************************************/
+
+BOOL add_name_to_wins_subnet(const struct name_record *namerec)
+{
+ return store_or_replace_wins_namerec(namerec, TDB_INSERT);
+}
+
+/****************************************************************************
+ Delete a given name in the tdb and remove the temporary malloc'ed data struct
+ on the linked list.
+*****************************************************************************/
+
+BOOL remove_name_from_wins_namelist(struct name_record *namerec)
+{
+ TDB_DATA key;
+ int ret;
+
+ if (!wins_tdb) {
+ return False;
+ }
+
+ key = name_to_key(&namerec->name);
+ ret = tdb_delete(wins_tdb, key);
+
+ DLIST_REMOVE(wins_server_subnet->namelist, namerec);
+ SAFE_FREE(namerec->data.ip);
+
+ /* namerec must be freed by the caller */
+
+ return (ret == 0) ? True : False;
+}
+
+/****************************************************************************
+ Dump out the complete namelist.
+*****************************************************************************/
+
+static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ struct name_record *namerec = NULL;
+ XFILE *fp = (XFILE *)state;
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ dump_name_record(namerec, fp);
+
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+ return 0;
+}
+
+void dump_wins_subnet_namelist(XFILE *fp)
+{
+ tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
+}
/****************************************************************************
Change the wins owner address in the record.
@@ -31,8 +337,6 @@
static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
{
- if (namerec==NULL)
- return;
namerec->data.wins_ip=wins_ip;
}
@@ -42,9 +346,6 @@ static void update_wins_owner(struct name_record *namerec, struct in_addr wins_i
static void update_wins_flag(struct name_record *namerec, int flags)
{
- if (namerec==NULL)
- return;
-
namerec->data.wins_flags=0x0;
/* if it's a group, it can be a normal or a special one */
@@ -64,7 +365,7 @@ static void update_wins_flag(struct name_record *namerec, int flags)
namerec->data.wins_flags|=WINS_MHOMED;
} else {
namerec->data.wins_flags|=WINS_UNIQUE;
- }
+ }
}
/* the node type are the same bits */
@@ -106,6 +407,7 @@ static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
/****************************************************************************
Possibly call the WINS hook external program when a WINS change is made.
+ Also stores the changed record back in the wins_tdb.
*****************************************************************************/
static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
@@ -115,7 +417,11 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt
char *p, *namestr;
int i;
- if (!cmd || !*cmd) return;
+ wins_store_changed_namerec(namerec);
+
+ if (!cmd || !*cmd) {
+ return;
+ }
for (p=namerec->name.name; *p; p++) {
if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
@@ -147,7 +453,6 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt
smbrun(command, NULL);
}
-
/****************************************************************************
Determine if this packet should be allocated to the WINS server.
*****************************************************************************/
@@ -242,6 +547,16 @@ BOOL initialise_wins(void)
return True;
}
+ /* Open the wins.tdb. */
+ wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600);
+ if (!wins_tdb) {
+ DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
+ strerror(errno) ));
+ return False;
+ }
+
+ tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
+
add_samba_names_to_subnet(wins_server_subnet);
if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
@@ -330,6 +645,7 @@ BOOL initialise_wins(void)
/* Allocate the space for the ip_list. */
if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
DEBUG(0,("initialise_wins: Malloc fail !\n"));
+ x_fclose(fp);
return False;
}
@@ -563,7 +879,7 @@ void wins_process_name_refresh_request( struct subnet_record *subrec,
* names update the ttl and return success.
*/
if( (!group || (group && (question->name_type == 0x1c)))
- && find_ip_in_name_record(namerec, from_ip) ) {
+ && find_ip_in_name_record(namerec, from_ip) ) {
/*
* Update the ttl.
*/
@@ -931,25 +1247,24 @@ already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
if ( namerec != NULL ) {
pull_ascii_nstring(name, sizeof(name), namerec->name.name);
- } else {
- name[0] = '\0';
- }
-
- if( is_myname(name) ) {
- if(!ismyip(from_ip)) {
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
+ if( is_myname(name) ) {
+ if(!ismyip(from_ip)) {
+ DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- } else {
- /*
- * It's one of our names and one of our IP's - update the ttl.
- */
- update_name_ttl(namerec, ttl);
- wins_hook("refresh", namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
+ send_wins_name_registration_response(RFS_ERR, 0, p);
+ return;
+ } else {
+ /*
+ * It's one of our names and one of our IP's - update the ttl.
+ */
+ update_name_ttl(namerec, ttl);
+ wins_hook("refresh", namerec, ttl);
+ send_wins_name_registration_response(0, ttl, p);
+ return;
+ }
}
+ } else {
+ name[0] = '\0';
}
/*
@@ -1375,6 +1690,37 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio
}
/***********************************************************************
+ Fetch all *<1b> names from the WINS db and store on the namelist.
+***********************************************************************/
+
+static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ struct name_record *namerec = NULL;
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ /* Filter out all non-1b names. */
+ if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ DLIST_ADD(wins_server_subnet->namelist, namerec);
+ return 0;
+}
+
+void fetch_all_active_wins_1b_names(void)
+{
+ tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
+}
+
+/***********************************************************************
Deal with the special name query for *<1b>.
***********************************************************************/
@@ -1392,10 +1738,13 @@ static void process_wins_dmb_query_request(struct subnet_record *subrec,
*/
num_ips = 0;
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
- if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
+
+ fetch_all_active_wins_1b_names();
+
+ for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
+ if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
num_ips += namerec->data.num_ips;
+ }
}
if(num_ips == 0) {
@@ -1418,9 +1767,8 @@ static void process_wins_dmb_query_request(struct subnet_record *subrec,
*/
num_ips = 0;
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
- if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
+ for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
+ if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
int i;
for(i = 0; i < namerec->data.num_ips; i++) {
set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
@@ -1576,7 +1924,7 @@ void wins_process_name_query_request(struct subnet_record *subrec,
DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
nmb_namestr(question) ));
- queue_dns_query(p, question, &namerec);
+ queue_dns_query(p, question);
return;
}
@@ -1729,106 +2077,224 @@ release name %s as this record is not active anymore.\n", nmb_namestr(question)
WINS time dependent processing.
******************************************************************/
+static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ time_t t = *(time_t *)state;
+ BOOL store_record = False;
+ struct name_record *namerec = NULL;
+ struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
+ if( namerec->data.source == SELF_NAME ) {
+ DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
+ wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
+ namerec->data.death_time += 300;
+ store_record = True;
+ goto done;
+ } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
+ DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
+ nmb_namestr(&namerec->name)));
+ remove_name_from_wins_namelist(namerec );
+ goto done;
+ }
+
+ /* handle records, samba is the wins owner */
+ if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
+ switch (namerec->data.wins_flags | WINS_STATE_MASK) {
+ case WINS_ACTIVE:
+ namerec->data.wins_flags&=~WINS_STATE_MASK;
+ namerec->data.wins_flags|=WINS_RELEASED;
+ namerec->data.death_time = t + EXTINCTION_INTERVAL;
+ DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
+ nmb_namestr(&namerec->name)));
+ store_record = True;
+ goto done;
+ case WINS_RELEASED:
+ namerec->data.wins_flags&=~WINS_STATE_MASK;
+ namerec->data.wins_flags|=WINS_TOMBSTONED;
+ namerec->data.death_time = t + EXTINCTION_TIMEOUT;
+ get_global_id_and_update(&namerec->data.id, True);
+ DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
+ nmb_namestr(&namerec->name)));
+ store_record = True;
+ goto done;
+ case WINS_TOMBSTONED:
+ DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
+ nmb_namestr(&namerec->name)));
+ remove_name_from_wins_namelist(namerec );
+ goto done;
+ }
+ } else {
+ switch (namerec->data.wins_flags | WINS_STATE_MASK) {
+ case WINS_ACTIVE:
+ /* that's not as MS says it should be */
+ namerec->data.wins_flags&=~WINS_STATE_MASK;
+ namerec->data.wins_flags|=WINS_TOMBSTONED;
+ namerec->data.death_time = t + EXTINCTION_TIMEOUT;
+ DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
+ nmb_namestr(&namerec->name)));
+ store_record = True;
+ goto done;
+ case WINS_TOMBSTONED:
+ DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
+ nmb_namestr(&namerec->name)));
+ remove_name_from_wins_namelist(namerec );
+ goto done;
+ case WINS_RELEASED:
+ DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
+we are not the wins owner !\n", nmb_namestr(&namerec->name)));
+ goto done;
+ }
+ }
+ }
+
+ done:
+
+ if (store_record) {
+ wins_store_changed_namerec(namerec);
+ }
+
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+
+ return 0;
+}
+
+/*******************************************************************
+ Time dependent wins processing.
+******************************************************************/
+
void initiate_wins_processing(time_t t)
{
static time_t lasttime = 0;
- struct name_record *namerec;
- struct name_record *next_namerec;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
+ struct name_record *nr = NULL;
+ struct name_record *nrnext = NULL;
+
+ if (!lasttime) {
+ lasttime = t;
+ }
+ if (t - lasttime < 20) {
+ return;
+ }
- if (!lasttime)
+ if(!lp_we_are_a_wins_server()) {
lasttime = t;
- if (t - lasttime < 20)
return;
+ }
+
+ tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
+
+
+ /* Delete all temporary name records on the wins subnet linked list. */
+ for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
+ nrnext = nr->next;
+ DLIST_REMOVE(wins_server_subnet->namelist, nr);
+ SAFE_FREE(nr->data.ip);
+ SAFE_FREE(nr);
+ }
+
+ wins_write_database(t, True);
lasttime = t;
+}
- if(!lp_we_are_a_wins_server())
- return;
+/*******************************************************************
+ Write out one record.
+******************************************************************/
- for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
- namerec;
- namerec = next_namerec ) {
- next_namerec = (struct name_record *)ubi_trNext( namerec );
-
- if( (namerec->data.death_time != PERMANENT_TTL)
- && (namerec->data.death_time < t) ) {
-
- if( namerec->data.source == SELF_NAME ) {
- DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n",
- wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
- namerec->data.death_time += 300;
- namerec->subnet->namelist_changed = True;
- continue;
- } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
- DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n",
- nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- continue;
- }
+void wins_write_name_record(struct name_record *namerec, XFILE *fp)
+{
+ int i;
+ struct tm *tm;
- /* handle records, samba is the wins owner */
- if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
- switch (namerec->data.wins_flags | WINS_STATE_MASK) {
- case WINS_ACTIVE:
- namerec->data.wins_flags&=~WINS_STATE_MASK;
- namerec->data.wins_flags|=WINS_RELEASED;
- namerec->data.death_time = t + EXTINCTION_INTERVAL;
- DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
- break;
- case WINS_RELEASED:
- namerec->data.wins_flags&=~WINS_STATE_MASK;
- namerec->data.wins_flags|=WINS_TOMBSTONED;
- namerec->data.death_time = t + EXTINCTION_TIMEOUT;
- get_global_id_and_update(&namerec->data.id, True);
- DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
- break;
- case WINS_TOMBSTONED:
- DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- break;
- }
- } else {
- switch (namerec->data.wins_flags | WINS_STATE_MASK) {
- case WINS_ACTIVE:
- /* that's not as MS says it should be */
- namerec->data.wins_flags&=~WINS_STATE_MASK;
- namerec->data.wins_flags|=WINS_TOMBSTONED;
- namerec->data.death_time = t + EXTINCTION_TIMEOUT;
- DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
- case WINS_TOMBSTONED:
- DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- break;
- case WINS_RELEASED:
- DEBUG(0,("initiate_wins_processing: %s is in released state and\
-we are not the wins owner !\n", nmb_namestr(&namerec->name)));
- break;
- }
- }
+ DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
+ if( namerec->data.death_time != PERMANENT_TTL ) {
+ char *ts, *nl;
+
+ tm = localtime(&namerec->data.death_time);
+ ts = asctime(tm);
+ nl = strrchr( ts, '\n' );
+ if( NULL != nl ) {
+ *nl = '\0';
}
+ DEBUGADD(4,("TTL = %s ", ts ));
+ } else {
+ DEBUGADD(4,("TTL = PERMANENT "));
+ }
+
+ for (i = 0; i < namerec->data.num_ips; i++) {
+ DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
}
+ DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
- if(wins_server_subnet->namelist_changed)
- wins_write_database(True);
+ if( namerec->data.source == REGISTER_NAME ) {
+ unstring name;
+ pull_ascii_nstring(name, sizeof(name), namerec->name.name);
+ x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
+ (int)namerec->data.death_time);
- wins_server_subnet->namelist_changed = False;
+ for (i = 0; i < namerec->data.num_ips; i++)
+ x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
+ x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
+ }
}
/*******************************************************************
Write out the current WINS database.
******************************************************************/
-void wins_write_database(BOOL background)
+static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
+{
+ struct name_record *namerec = NULL;
+ XFILE *fp = (XFILE *)state;
+
+ if (kbuf.dsize != sizeof(unstring) + 1) {
+ return 0;
+ }
+
+ namerec = wins_record_to_name_record(kbuf, dbuf);
+ if (!namerec) {
+ return 0;
+ }
+
+ wins_write_name_record(namerec, fp);
+
+ SAFE_FREE(namerec->data.ip);
+ SAFE_FREE(namerec);
+ return 0;
+}
+
+
+void wins_write_database(time_t t, BOOL background)
{
- struct name_record *namerec;
+ static time_t last_write_time = 0;
pstring fname, fnamenew;
XFILE *fp;
- if(!lp_we_are_a_wins_server())
+ if (background) {
+ if (!last_write_time) {
+ last_write_time = t;
+ }
+ if (t - last_write_time < 120) {
+ return;
+ }
+
+ }
+
+ if(!lp_we_are_a_wins_server()) {
return;
+ }
/* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
if (background) {
@@ -1836,6 +2302,11 @@ void wins_write_database(BOOL background)
if (sys_fork()) {
return;
}
+ if (tdb_reopen(wins_tdb)) {
+ DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
+ strerror(errno)));
+ return;
+ }
}
slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
@@ -1854,43 +2325,8 @@ void wins_write_database(BOOL background)
x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
- for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
- int i;
- struct tm *tm;
-
- DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
-
- if( namerec->data.death_time != PERMANENT_TTL ) {
- char *ts, *nl;
+ tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
- tm = localtime(&namerec->data.death_time);
- ts = asctime(tm);
- nl = strrchr( ts, '\n' );
- if( NULL != nl ) {
- *nl = '\0';
- }
- DEBUGADD(4,("TTL = %s ", ts ));
- } else {
- DEBUGADD(4,("TTL = PERMANENT "));
- }
-
- for (i = 0; i < namerec->data.num_ips; i++) {
- DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
- }
- DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
-
- if( namerec->data.source == REGISTER_NAME ) {
- unstring name;
- pull_ascii_nstring(name, sizeof(name), namerec->name.name);
- x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
- (int)namerec->data.death_time);
-
- for (i = 0; i < namerec->data.num_ips; i++)
- x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
- x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
- }
- }
-
x_fclose(fp);
chmod(fnamenew,0644);
unlink(fname);
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 61c01daa165..b2c3a011643 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -3,6 +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
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>
@@ -27,14 +28,73 @@ static void _pam_log(int err, const char *format, ...)
closelog();
}
-static int _pam_parse(int argc, const char **argv)
+static void _pam_log_debug(int ctrl, int err, const char *format, ...)
{
- int ctrl;
+ va_list args;
+
+ if (!(ctrl & WINBIND_DEBUG_ARG)) {
+ return;
+ }
+
+ va_start(args, format);
+ openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
+ vsyslog(err, format, args);
+ va_end(args);
+ closelog();
+}
+
+static int _pam_parse(int argc, const char **argv, dictionary **d)
+{
+ int ctrl = 0;
+ const char *config_file = NULL;
+
+ if (d == NULL || *d == NULL) {
+ goto config_from_pam;
+ }
+
+ for (; argc-- > 0; ++argv) {
+ if (!strncasecmp(*argv, "config", strlen("config"))) {
+ ctrl |= WINBIND_CONFIG_FILE;
+ config_file = argv[argc];
+ break;
+ }
+ }
+
+ if (config_file == NULL) {
+ config_file = PAM_WINBIND_CONFIG_FILE;
+ }
+
+ *d = iniparser_load(CONST_DISCARD(char *, config_file));
+ if (*d == NULL) {
+ return -1;
+ }
+
+ if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:debug"), False)) {
+ ctrl |= WINBIND_DEBUG_ARG;
+ }
+
+ if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:cached_login"), False)) {
+ ctrl |= WINBIND_CACHED_LOGIN;
+ }
+
+ if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:krb5_auth"), False)) {
+ ctrl |= WINBIND_KRB5_AUTH;
+ }
+
+ if (iniparser_getstr(*d, CONST_DISCARD(char *,"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)) {
+ ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
+ }
+
+config_from_pam:
/* step through arguments */
- for (ctrl = 0; argc-- > 0; ++argv) {
+ for (; argc-- > 0; ++argv) {
/* generic options */
-
if (!strcmp(*argv,"debug"))
ctrl |= WINBIND_DEBUG_ARG;
else if (!strcasecmp(*argv, "use_authtok"))
@@ -49,19 +109,59 @@ static int _pam_parse(int argc, const char **argv)
ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of")))
ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
+ else if (!strcasecmp(*argv, "krb5_auth"))
+ ctrl |= WINBIND_KRB5_AUTH;
+ else if (!strncasecmp(*argv, "krb5_ccache_type", strlen("krb5_ccache_type")))
+ ctrl |= WINBIND_KRB5_CCACHE_TYPE;
+ else if (!strcasecmp(*argv, "cached_login"))
+ ctrl |= WINBIND_CACHED_LOGIN;
else {
_pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
}
+
}
-
return ctrl;
-}
+};
static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int 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_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"},
+ {"NT_STATUS_PASSWORD_EXPIRED", "Your password has expired"},
+ {"NT_STATUS_PASSWORD_MUST_CHANGE", "You need to change your password now"},
+ {"NT_STATUS_INVALID_WORKSTATION", "You are not allowed to logon from this workstation"},
+ {"NT_STATUS_INVALID_LOGON_HOURS", "You are not allowed to logon at this time"},
+ {"NT_STATUS_ACCOUNT_EXPIRED", "Your account has expired. Please contact your System administrator"}, /* SCNR */
+ {"NT_STATUS_ACCOUNT_DISABLED", "Your account is disabled. Please contact your System administrator"}, /* SCNR */
+ {"NT_STATUS_ACCOUNT_LOCKED_OUT", "Your account has been locked. Please contact your System administrator"}, /* SCNR */
+ {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", "Invalid Trust Account"},
+ {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", "Invalid Trust Account"},
+ {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", "Invalid Trust Account"},
+ {"NT_STATUS_ACCESS_DENIED", "Access is denied"},
+ {NULL, NULL}
+};
+
+const char *_get_ntstatus_error_string(const char *nt_status_string)
+{
+ int i;
+ for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
+ if (!strcasecmp(ntstatus_errors[i].ntstatus_string, nt_status_string)) {
+ return ntstatus_errors[i].error_string;
+ }
+ }
+ return NULL;
+}
+
/* --- authentication management functions --- */
/* Attempt a conversation */
@@ -70,16 +170,16 @@ static int converse(pam_handle_t *pamh, int nargs,
struct pam_message **message,
struct pam_response **response)
{
- int retval;
- struct pam_conv *conv;
-
- retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ;
- if (retval == PAM_SUCCESS) {
- retval = conv->conv(nargs, (const struct pam_message **)message,
- response, conv->appdata_ptr);
- }
+ int retval;
+ struct pam_conv *conv;
+
+ retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv );
+ if (retval == PAM_SUCCESS) {
+ retval = conv->conv(nargs, (const struct pam_message **)message,
+ response, conv->appdata_ptr);
+ }
- return retval; /* propagate error status */
+ return retval; /* propagate error status */
}
@@ -103,11 +203,23 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
return retval;
}
-static int pam_winbind_request(enum winbindd_cmd req_type,
+static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...)
+{
+ va_list args;
+ char *var;
+
+ va_start(args, format);
+ vasprintf(&var, format, args);
+ va_end(args);
+
+ return _make_remark(pamh, type, var);
+}
+
+static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
+ enum winbindd_cmd req_type,
struct winbindd_request *request,
struct winbindd_response *response)
{
-
/* Fill in request and send down pipe */
init_request(request, req_type);
@@ -140,19 +252,20 @@ static int pam_winbind_request(enum winbindd_cmd req_type,
return PAM_SERVICE_ERR;
}
}
-
+
return PAM_SUCCESS;
}
-static int pam_winbind_request_log(enum winbindd_cmd req_type,
- struct winbindd_request *request,
- struct winbindd_response *response,
+static int pam_winbind_request_log(pam_handle_t * pamh,
int ctrl,
+ enum winbindd_cmd req_type,
+ struct winbindd_request *request,
+ struct winbindd_response *response,
const char *user)
{
int retval;
- retval = pam_winbind_request(req_type, request, response);
+ retval = pam_winbind_request(pamh, ctrl, req_type, request, response);
switch (retval) {
case PAM_AUTH_ERR:
@@ -168,13 +281,12 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
_pam_log(LOG_WARNING, "user `%s' password expired", user);
return retval;
case PAM_NEW_AUTHTOK_REQD:
- /* password expired */
+ /* new password required */
_pam_log(LOG_WARNING, "user `%s' new password required", user);
return retval;
case PAM_USER_UNKNOWN:
/* the user does not exist */
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_NOTICE, "user `%s' not found",
+ _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found",
user);
if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
return PAM_IGNORE;
@@ -191,6 +303,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
/* Otherwise, the authentication looked good */
_pam_log(LOG_NOTICE, "user '%s' OK", user);
}
+
return retval;
default:
/* we don't know anything about this return value */
@@ -201,24 +314,67 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
}
/* talk to winbindd */
-static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl)
+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)
{
struct winbindd_request request;
struct winbindd_response response;
+ int ret;
ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
strncpy(request.data.auth.user, user,
- sizeof(request.data.auth.user)-1);
+ sizeof(request.data.auth.user)-1);
strncpy(request.data.auth.pass, pass,
- sizeof(request.data.auth.pass)-1);
+ sizeof(request.data.auth.pass)-1);
+
+ request.data.auth.krb5_cc_type[0] = '\0';
+ request.data.auth.uid = -1;
+
+ request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_GET_PWD_POLICY;
+
+ if (ctrl & WINBIND_KRB5_AUTH) {
+
+ struct passwd *pwd = NULL;
- if (member == NULL )
- return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+ _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;
+ }
+ request.data.auth.uid = pwd->pw_uid;
+ }
+
+ if (ctrl & WINBIND_CACHED_LOGIN) {
+ _pam_log_debug(ctrl, LOG_DEBUG, "enabling cached login flag\n");
+ request.flags |= WBFLAG_PAM_CACHED_LOGIN;
+ }
+
+ 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);
+ }
+
+ 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 (!strncmp("S-", member, 2) == 0) {
+ if ( (member != NULL) && (strncmp("S-", member, 2) != 0) ) {
struct winbindd_request sid_request;
struct winbindd_response sid_response;
@@ -226,55 +382,198 @@ static int winbind_auth_request(const char *user, const char *pass, const char *
ZERO_STRUCT(sid_request);
ZERO_STRUCT(sid_response);
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member);
+ _pam_log_debug(ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member);
/* fortunatly winbindd can handle non-separated names */
- strcpy(sid_request.data.name.name, member);
+ strncpy(sid_request.data.name.name, member,
+ sizeof(sid_request.data.name.name) - 1);
- if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &sid_request, &sid_response, ctrl, user)) {
+ 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);
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 ((ctrl & WINBIND_KRB5_AUTH) &&
+ response.data.auth.krb5ccname[0] != '\0') {
- strncpy(request.data.auth.require_membership_of_sid, member,
- sizeof(request.data.auth.require_membership_of_sid)-1);
+ 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);
- return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+ 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) {
+ 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");
+
+ }
+
+ /* 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 (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");
+ }
+
+ /* save the CIFS homedir for pam_cifs / pam_mount */
+ if (response.data.auth.info3.home_dir[0] != '\0') {
+ char *buf;
+
+ if (!asprintf(&buf, "%s", response.data.auth.info3.home_dir)) {
+ return PAM_BUF_ERR;
+ }
+
+ pam_set_data( pamh, PAM_WINBIND_HOMEDIR, (void *)buf, _pam_winbind_cleanup_func);
+ }
+
+ return ret;
}
/* talk to winbindd */
-static int winbind_chauthtok_request(const char *user, const char *oldpass,
- const char *newpass, int ctrl)
+static int winbind_chauthtok_request(pam_handle_t * pamh,
+ int ctrl,
+ const char *user,
+ const char *oldpass,
+ const char *newpass)
{
struct winbindd_request request;
struct winbindd_response response;
+ int ret;
ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
- if (request.data.chauthtok.user == NULL) return -2;
+ if (request.data.chauthtok.user == NULL) return -2;
strncpy(request.data.chauthtok.user, user,
- sizeof(request.data.chauthtok.user) - 1);
-
- if (oldpass != NULL) {
- strncpy(request.data.chauthtok.oldpass, oldpass,
- sizeof(request.data.chauthtok.oldpass) - 1);
- } else {
- request.data.chauthtok.oldpass[0] = '\0';
- }
-
- if (newpass != NULL) {
- strncpy(request.data.chauthtok.newpass, newpass,
- sizeof(request.data.chauthtok.newpass) - 1);
- } else {
- request.data.chauthtok.newpass[0] = '\0';
- }
+ sizeof(request.data.chauthtok.user) - 1);
+
+ if (oldpass != NULL) {
+ strncpy(request.data.chauthtok.oldpass, oldpass,
+ sizeof(request.data.chauthtok.oldpass) - 1);
+ } else {
+ request.data.chauthtok.oldpass[0] = '\0';
+ }
- return pam_winbind_request_log(WINBINDD_PAM_CHAUTHTOK, &request, &response, ctrl, user);
+ if (newpass != NULL) {
+ strncpy(request.data.chauthtok.newpass, newpass,
+ sizeof(request.data.chauthtok.newpass) - 1);
+ } else {
+ request.data.chauthtok.newpass[0] = '\0';
+ }
+
+ if (ctrl & WINBIND_KRB5_AUTH) {
+ request.flags = WBFLAG_PAM_KRB5;
+ }
+
+ ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user);
+
+ if (ret == PAM_SUCCESS) {
+ 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");
+
+ /* TODO: tell the min pwd length ? */
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_SHORT");
+
+ /* TODO: tell the minage ? */
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_RECENT");
+
+ /* TODO: tell the history length ? */
+ PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_HISTORY_CONFLICT");
+
+ if (!strcasecmp(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) {
+
+ /* FIXME: avoid to send multiple PAM messages after another */
+ switch (response.data.auth.reject_reason) {
+ case 0:
+ break;
+ case REJECT_REASON_TOO_SHORT:
+ PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT");
+ break;
+ case REJECT_REASON_IN_HISTORY:
+ PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_HISTORY_CONFLICT");
+ break;
+ case REJECT_REASON_NOT_COMPLEX:
+ _make_remark(pamh, PAM_ERROR_MSG, "Password does not meet complexity requirements");
+ break;
+ default:
+ _pam_log_debug(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" :
+ "");
+
+ }
+
+ return ret;
}
/*
@@ -285,29 +584,58 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass,
* 0 = OK
* -1 = System error
*/
-static int valid_user(const char *user)
+static int valid_user(const char *user, pam_handle_t *pamh, int ctrl)
{
- if (getpwnam(user)) return 0;
- return 1;
+ /* 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
+ * modules in the 'account' or 'password' facility. */
+
+ struct passwd *pwd = NULL;
+ struct winbindd_request request;
+ struct winbindd_response response;
+ int ret;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ pwd = getpwnam(user);
+ if (pwd == NULL) {
+ return 1;
+ }
+
+ strncpy(request.data.username, user,
+ sizeof(request.data.username) - 1);
+
+ ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_GETPWNAM, &request, &response, user);
+
+ switch (ret) {
+ case PAM_USER_UNKNOWN:
+ return 1;
+ case PAM_SUCCESS:
+ return 0;
+ default:
+ break;
+ }
+ return -1;
}
static char *_pam_delete(register char *xx)
{
- _pam_overwrite(xx);
- _pam_drop(xx);
- return NULL;
+ _pam_overwrite(xx);
+ _pam_drop(xx);
+ return NULL;
}
/*
* obtain a password from the user
*/
-static int _winbind_read_password(pam_handle_t * pamh
- ,unsigned int ctrl
- ,const char *comment
- ,const char *prompt1
- ,const char *prompt2
- ,const char **pass)
+static int _winbind_read_password(pam_handle_t * pamh,
+ unsigned int ctrl,
+ const char *comment,
+ const char *prompt1,
+ const char *prompt2,
+ const char **pass)
{
int authtok_flag;
int retval;
@@ -394,13 +722,12 @@ static int _winbind_read_password(pam_handle_t * pamh
token = x_strdup(resp[i - replies].resp);
if (token != NULL) {
if (replies == 2) {
-
/* verify that password entered correctly */
if (!resp[i - 1].resp
|| 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, PAM_ERROR_MSG, MISTYPED_PASS);
}
}
} else {
@@ -423,8 +750,7 @@ static int _winbind_read_password(pam_handle_t * pamh
}
if (retval != PAM_SUCCESS) {
- if (on(WINBIND_DEBUG_ARG, ctrl))
- _pam_log(LOG_DEBUG,
+ _pam_log_debug(ctrl, LOG_DEBUG,
"unable to obtain a password");
return retval;
}
@@ -434,10 +760,8 @@ 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) {
+ if (retval != PAM_SUCCESS ||
+ (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) {
_pam_log(LOG_CRIT, "error manipulating password");
return retval;
@@ -450,92 +774,166 @@ static int _winbind_read_password(pam_handle_t * pamh
return PAM_SUCCESS;
}
+const char *get_conf_item_string(int argc,
+ const char **argv,
+ int ctrl,
+ dictionary *d,
+ const char *item,
+ int flag)
+{
+ int i = 0;
+ char *parm = NULL;
+ const char *parm_opt = NULL;
+ char *key = NULL;
+
+ if (!(ctrl & flag)) {
+ goto out;
+ }
+
+ /* let the pam opt take precedence over the smb.conf option */
+
+ if (d != NULL) {
+
+ if (!asprintf(&key, "global:%s", item)) {
+ goto out;
+ }
+
+ parm_opt = iniparser_getstr(d, key);
+ SAFE_FREE(key);
+ }
+
+ for ( i=0; i<argc; i++ ) {
+
+ if ((strncmp(argv[i], item, strlen(item)) == 0)) {
+ char *p;
+
+ parm = strdup(argv[i]);
+
+ if ( (p = strchr( parm, '=' )) == NULL) {
+ _pam_log(LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item);
+ goto out;
+ }
+ SAFE_FREE(parm);
+ _pam_log_debug(ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1);
+ return p + 1;
+ }
+ }
+
+ _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt);
+out:
+ SAFE_FREE(parm);
+ return parm_opt;
+}
+
+const char *get_krb5_cc_type_from_config(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);
+}
+
+const char *get_member_from_config(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);
+ if (ret) {
+ return ret;
+ }
+ return get_conf_item_string(argc, argv, ctrl, d, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP);
+}
+
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
- const char *username;
- const char *password;
- const char *member = NULL;
- int retval = PAM_AUTH_ERR;
- int i;
-
- /* parse arguments */
- int ctrl = _pam_parse(argc, argv);
-
- /* Get the username */
- retval = pam_get_user(pamh, &username, NULL);
- if ((retval != PAM_SUCCESS) || (!username)) {
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_DEBUG,"can not get the username");
- return PAM_SERVICE_ERR;
- }
-
- retval = _winbind_read_password(pamh, ctrl, NULL,
- "Password: ", NULL,
- &password);
-
- if (retval != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "Could not retrieve user's password");
- return PAM_AUTHTOK_ERR;
- }
-
- if (ctrl & WINBIND_DEBUG_ARG) {
-
- /* Let's not give too much away in the log file */
+ const char *username;
+ const char *password;
+ const char *member = NULL;
+ const char *cctype = NULL;
+ int retval = PAM_AUTH_ERR;
+ dictionary *d;
+
+ /* parse arguments */
+ int ctrl = _pam_parse(argc, argv, &d);
+ if (ctrl == -1) {
+ retval = PAM_SYSTEM_ERR;
+ goto out;
+ }
+
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate");
+
+ /* 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");
+ retval = PAM_SERVICE_ERR;
+ goto out;
+ }
+
+ retval = _winbind_read_password(pamh, ctrl, NULL,
+ "Password: ", NULL,
+ &password);
+
+ if (retval != PAM_SUCCESS) {
+ _pam_log(LOG_ERR, "Could not retrieve user's password");
+ retval = PAM_AUTHTOK_ERR;
+ goto out;
+ }
+
+ /* Let's not give too much away in the log file */
#ifdef DEBUG_PASSWORD
- _pam_log(LOG_INFO, "Verify user `%s' with password `%s'",
- username, password);
+ _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s' with password `%s'",
+ username, password);
#else
- _pam_log(LOG_INFO, "Verify user `%s'", username);
+ _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s'", username);
#endif
- }
- if (ctrl & WINBIND_REQUIRED_MEMBERSHIP) {
-
- for ( i=0; i<argc; i++ ) {
+ member = get_member_from_config(argc, argv, ctrl, d);
- if ((strncmp(argv[i], "require_membership_of", strlen("require_membership_of")) == 0) ||
- (strncmp(argv[i], "require-membership-of", strlen("require-membership-of")) == 0)) {
+ cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d);
- char *p;
- char *parm = strdup(argv[i]);
+ /* Now use the username to look up password */
+ retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True);
- if ( (p = strchr( parm, '=' )) == NULL) {
- _pam_log(LOG_INFO, "no \"=\" delimiter for \"require_membership_of\" found\n");
- break;
- }
+ if (retval == PAM_NEW_AUTHTOK_REQD ||
+ retval == PAM_AUTHTOK_EXPIRED) {
- member = strdup(p+1);
- }
- }
- }
+ char *buf;
- /* Now use the username to look up password */
- retval = winbind_auth_request(username, password, member, ctrl);
- if (retval == PAM_NEW_AUTHTOK_REQD ||
- retval == PAM_AUTHTOK_EXPIRED) {
-
- char *buf;
-
- if (!asprintf(&buf, "%d", retval)) {
- return PAM_BUF_ERR;
- }
+ if (!asprintf(&buf, "%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, (void *)buf, _pam_winbind_cleanup_func);
- return PAM_SUCCESS;
- }
-
- return retval;
+ retval = PAM_SUCCESS;
+ goto out;
+ }
+
+out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+ return retval;
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
- return PAM_SUCCESS;
+ /* parse arguments */
+ int ctrl = _pam_parse(argc, argv, NULL);
+ if (ctrl == -1) {
+ return PAM_SYSTEM_ERR;
+ }
+
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred");
+
+ if (flags & PAM_DELETE_CRED) {
+ return pam_sm_close_session(pamh, flags, argc, argv);
+ }
+
+ return PAM_SUCCESS;
}
/*
@@ -546,109 +944,195 @@ PAM_EXTERN
int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
int argc, const char **argv)
{
- const char *username;
- void *tmp = NULL;
+ const char *username;
+ int retval = PAM_USER_UNKNOWN;
+ void *tmp = NULL;
+
+ /* parse arguments */
+ int ctrl = _pam_parse(argc, argv, NULL);
+ if (ctrl == -1) {
+ return PAM_SYSTEM_ERR;
+ }
- int retval = PAM_USER_UNKNOWN;
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt");
- /* parse arguments */
- int ctrl = _pam_parse(argc, argv);
- /* Get the username */
- retval = pam_get_user(pamh, &username, NULL);
- if ((retval != PAM_SUCCESS) || (!username)) {
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_DEBUG,"can not get the username");
- return PAM_SERVICE_ERR;
- }
+ /* 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;
+ }
- /* Verify the username */
- retval = valid_user(username);
- switch (retval) {
+ /* Verify the username */
+ retval = valid_user(username, pamh, ctrl);
+ switch (retval) {
case -1:
- /* some sort of system error. The log was already printed */
- return PAM_SERVICE_ERR;
+ /* some sort of system error. The log was already printed */
+ return PAM_SERVICE_ERR;
case 1:
- /* the user does not exist */
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_NOTICE, "user `%s' not found",
- username);
- if (ctrl & WINBIND_UNKNOWN_OK_ARG)
- return PAM_IGNORE;
- return PAM_USER_UNKNOWN;
+ /* the user does not exist */
+ _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", username);
+ if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
+ return PAM_IGNORE;
+ }
+ return PAM_USER_UNKNOWN;
case 0:
- pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp);
-
- if (tmp != NULL) {
- retval = atoi(tmp);
- switch (retval) {
- 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_WINBIND_NEW_AUTHTOK_REQD);
- _pam_log(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;
- default:
- _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success");
- _pam_log(LOG_NOTICE, "user '%s' granted access", username);
- return PAM_SUCCESS;
+ pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp);
+ if (tmp != NULL) {
+ retval = atoi(tmp);
+ switch (retval) {
+ 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_WINBIND_NEW_AUTHTOK_REQD);
+ _pam_log(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;
+ default:
+ _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success");
+ _pam_log(LOG_NOTICE, "user '%s' granted access", username);
+ return PAM_SUCCESS;
+ }
}
- }
- /* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted access", username);
- return PAM_SUCCESS;
+ /* Otherwise, the authentication looked good */
+ _pam_log(LOG_NOTICE, "user '%s' granted access", username);
+ return PAM_SUCCESS;
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;
- }
-
- /* should not be reached */
- return PAM_IGNORE;
+ /* 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;
+ }
+
+ /* should not be reached */
+ return PAM_IGNORE;
}
+
PAM_EXTERN
int pam_sm_open_session(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
+ int argc, const char **argv)
{
- /* parse arguments */
- int ctrl = _pam_parse(argc, argv);
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_open_session handler");
- return PAM_SUCCESS;
+ /* parse arguments */
+ int ctrl = _pam_parse(argc, argv, NULL);
+ if (ctrl == -1) {
+ return PAM_SYSTEM_ERR;
+ }
+
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler");
+
+ return PAM_SUCCESS;
}
+
PAM_EXTERN
int pam_sm_close_session(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
+ int argc, const char **argv)
{
- /* parse arguments */
- int ctrl = _pam_parse(argc, argv);
- if (ctrl & WINBIND_DEBUG_ARG)
- _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_close_session handler");
- return PAM_SUCCESS;
+ dictionary *d;
+ int retval = PAM_SUCCESS;
+
+ /* parse arguments */
+ int ctrl = _pam_parse(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");
+
+ if (!(flags & PAM_DELETE_CRED)) {
+ retval = PAM_SUCCESS;
+ goto out;
+ }
+
+ if (ctrl & WINBIND_KRB5_AUTH) {
+
+ /* destroy the ccache here */
+ struct winbindd_request request;
+ struct winbindd_response response;
+ const char *user;
+ const char *ccname = NULL;
+ struct passwd *pwd = NULL;
+
+ ZERO_STRUCT(request);
+ 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");
+ goto out;
+ }
+
+ ccname = pam_getenv(pamh, "KRB5CCNAME");
+ if (ccname == NULL) {
+ _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment");
+ retval = PAM_SUCCESS;
+ goto out;
+ }
+
+ strncpy(request.data.logoff.user, user,
+ sizeof(request.data.logoff.user) - 1);
+
+ strncpy(request.data.logoff.krb5ccname, ccname,
+ sizeof(request.data.logoff.krb5ccname) - 1);
+
+ pwd = getpwnam(user);
+ if (pwd == NULL) {
+ retval = PAM_USER_UNKNOWN;
+ goto out;
+ }
+ request.data.logoff.uid = pwd->pw_uid;
+
+ request.flags = WBFLAG_PAM_KRB5;
+
+ retval = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user);
+ }
+
+out:
+ if (d) {
+ iniparser_freedict(d);
+ }
+ return retval;
}
-PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
- int argc, const char **argv)
+PAM_EXTERN
+int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
+ int argc, const char **argv)
{
unsigned int lctrl;
int retval;
- unsigned int ctrl = _pam_parse(argc, argv);
+ unsigned int ctrl;
/* <DO NOT free() THESE> */
const char *user;
- const char *member = NULL;
char *pass_old, *pass_new;
/* </DO NOT free() THESE> */
char *Announce;
int retry = 0;
+ dictionary *d;
+
+ ctrl = _pam_parse(argc, argv, &d);
+ if (ctrl == -1) {
+ retval = PAM_SYSTEM_ERR;
+ goto out;
+ }
+
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok");
/*
* First get the name of a user
@@ -657,18 +1141,32 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (retval == PAM_SUCCESS) {
if (user == NULL) {
_pam_log(LOG_ERR, "username was NULL!");
- return PAM_USER_UNKNOWN;
+ retval = PAM_USER_UNKNOWN;
+ goto out;
}
- if (retval == PAM_SUCCESS && on(WINBIND_DEBUG_ARG, ctrl))
- _pam_log(LOG_DEBUG, "username [%s] obtained",
+ if (retval == PAM_SUCCESS) {
+ _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained",
user);
+ }
} else {
- if (on(WINBIND_DEBUG_ARG, ctrl))
- _pam_log(LOG_DEBUG,
- "password - could not identify user");
- return retval;
+ _pam_log_debug(ctrl, LOG_DEBUG,
+ "password - could not identify user");
+ goto out;
}
+ /* check if this is really a user in winbindd, not only in NSS */
+ retval = valid_user(user, pamh, ctrl);
+ switch (retval) {
+ case 1:
+ retval = PAM_USER_UNKNOWN;
+ goto out;
+ case -1:
+ retval = PAM_SYSTEM_ERR;
+ goto out;
+ default:
+ break;
+ }
+
/*
* obtain and verify the current password (OLDAUTHTOK) for
* the user.
@@ -680,44 +1178,40 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
#define greeting "Changing password for "
Announce = (char *) malloc(sizeof(greeting) + strlen(user));
if (Announce == NULL) {
- _pam_log(LOG_CRIT,
- "password - out of memory");
- return PAM_BUF_ERR;
+ _pam_log(LOG_CRIT, "password - out of memory");
+ retval = PAM_BUF_ERR;
+ goto out;
}
(void) strcpy(Announce, greeting);
(void) strcpy(Announce + sizeof(greeting) - 1, user);
#undef greeting
lctrl = ctrl | WINBIND__OLD_PASSWORD;
- retval = _winbind_read_password(pamh, lctrl
- ,Announce
- ,"(current) NT password: "
- ,NULL
- ,(const char **) &pass_old);
- free(Announce);
-
+ retval = _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");
- return retval;
+ _pam_log(LOG_NOTICE, "password - (old) token not obtained");
+ goto out;
}
/* verify that this is the password for this user */
- retval = winbind_auth_request(user, pass_old, member, ctrl);
-
+ retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False);
+
if (retval != PAM_ACCT_EXPIRED
&& retval != PAM_AUTHTOK_EXPIRED
&& retval != PAM_NEW_AUTHTOK_REQD
&& retval != PAM_SUCCESS) {
pass_old = NULL;
- return retval;
+ goto out;
}
retval = 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");
+ _pam_log(LOG_CRIT, "failed to set PAM_OLDAUTHTOK");
}
} else if (flags & PAM_UPDATE_AUTHTOK) {
@@ -729,12 +1223,12 @@ PAM_EXTERN 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);
+ retval = pam_get_item(pamh, PAM_OLDAUTHTOK,
+ (const void **) &pass_old);
if (retval != PAM_SUCCESS) {
_pam_log(LOG_NOTICE, "user not authenticated");
- return retval;
+ goto out;
}
lctrl = ctrl;
@@ -750,19 +1244,17 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* password -- needed for pluggable password strength checking
*/
- retval = _winbind_read_password(pamh, lctrl
- ,NULL
- ,"Enter new NT password: "
- ,"Retype new NT password: "
- ,(const char **) &pass_new);
+ retval = _winbind_read_password(pamh, lctrl,
+ NULL,
+ "Enter new NT password: ",
+ "Retype new NT password: ",
+ (const char **) &pass_new);
if (retval != PAM_SUCCESS) {
- if (on(WINBIND_DEBUG_ARG, ctrl)) {
- _pam_log(LOG_ALERT
- ,"password - new password not obtained");
- }
+ _pam_log_debug(ctrl, LOG_ALERT
+ ,"password - new password not obtained");
pass_old = NULL;/* tidy up */
- return retval;
+ goto out;
}
/*
@@ -781,14 +1273,34 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* rebuild the password database file.
*/
- retval = winbind_chauthtok_request(user, pass_old, pass_new, ctrl);
- _pam_overwrite(pass_new);
- _pam_overwrite(pass_old);
- pass_old = pass_new = NULL;
+ retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new);
+ if (retval) {
+ _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 (ctrl & WINBIND_KRB5_AUTH) {
+
+ 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);
+ _pam_overwrite(pass_new);
+ _pam_overwrite(pass_old);
+ pass_old = pass_new = NULL;
+ }
} else {
retval = PAM_SERVICE_ERR;
}
-
+
+out:
+ if (d) {
+ iniparser_freedict(d);
+ }
return retval;
}
@@ -797,13 +1309,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/* static module data */
struct pam_module _pam_winbind_modstruct = {
- MODULE_NAME,
- pam_sm_authenticate,
- pam_sm_setcred,
- pam_sm_acct_mgmt,
- pam_sm_open_session,
- pam_sm_close_session,
- pam_sm_chauthtok
+ MODULE_NAME,
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ pam_sm_acct_mgmt,
+ pam_sm_open_session,
+ pam_sm_close_session,
+ pam_sm_chauthtok
};
#endif
@@ -812,6 +1324,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) 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 86ba9772879..89553ebfc38 100644
--- a/source/nsswitch/pam_winbind.h
+++ b/source/nsswitch/pam_winbind.h
@@ -17,6 +17,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#include <time.h>
#include <config.h>
@@ -25,7 +26,13 @@
#define PAM_SM_ACCOUNT
#define PAM_SM_PASSWORD
-#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD)
+#ifndef PAM_WINBIND_CONFIG_FILE
+#define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf"
+#endif
+
+#include <iniparser.h>
+
+#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD) || defined(AIX)
/* Solaris always uses dynamic pam modules */
#define PAM_EXTERN extern
@@ -83,8 +90,10 @@ do { \
#define WINBIND_USE_FIRST_PASS_ARG (1<<4)
#define WINBIND__OLD_PASSWORD (1<<5)
#define WINBIND_REQUIRED_MEMBERSHIP (1<<6)
-
-#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
+#define WINBIND_KRB5_AUTH (1<<7)
+#define WINBIND_KRB5_CCACHE_TYPE (1<<8)
+#define WINBIND_CACHED_LOGIN (1<<9)
+#define WINBIND_CONFIG_FILE (1<<10)
/*
* here is the string to inform the user that the new passwords they
@@ -96,4 +105,68 @@ do { \
#define on(x, y) (x & y)
#define off(x, y) (!(x & y))
+#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
+#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR"
+
+#define SECONDS_PER_DAY 86400
+
+#define DAYS_TO_WARN_BEFORE_PWD_EXPIRES 5
+
#include "winbind_client.h"
+
+#define PAM_WB_REMARK_DIRECT(h,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);\
+ } else {\
+ _make_remark(h, PAM_ERROR_MSG, x);\
+ };\
+};
+
+#define PAM_WB_REMARK_DIRECT_RET(h,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);\
+ return ret;\
+ };\
+ _make_remark(h, PAM_ERROR_MSG, x);\
+ return ret;\
+};
+
+#define PAM_WB_REMARK_CHECK_RESPONSE_RET(h,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);\
+ return ret;\
+ };\
+ if (x.data.auth.error_string[0] != '\0') {\
+ _make_remark(h, PAM_ERROR_MSG, x.data.auth.error_string);\
+ return ret;\
+ };\
+ _make_remark(h, PAM_ERROR_MSG, y);\
+ return ret;\
+ };\
+};
+
+/* from include/rpc_samr.h */
+#define DOMAIN_PASSWORD_COMPLEX 0x00000001
+
+#define REJECT_REASON_OTHER 0x00000000
+#define REJECT_REASON_TOO_SHORT 0x00000001
+#define REJECT_REASON_IN_HISTORY 0x00000002
+#define REJECT_REASON_NOT_COMPLEX 0x00000005
+
+/* from include/smb.h */
+#define ACB_PWNOEXP 0x00000200
+
+/* from include/rpc_netlogon.h */
+#define LOGON_CACHED_ACCOUNT 0x00000004
+
diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c
index db56cf04441..de1edf054d1 100644
--- a/source/nsswitch/wb_client.c
+++ b/source/nsswitch/wb_client.c
@@ -64,39 +64,53 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
/* Call winbindd to convert sid to name */
-BOOL winbind_lookup_sid(const DOM_SID *sid,
- fstring dom_name, fstring name,
+BOOL winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ const char **domain, const char **name,
enum SID_NAME_USE *name_type)
{
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
- fstring sid_str;
/* Initialise request */
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- sid_to_string(sid_str, sid);
- fstrcpy(request.data.sid, sid_str);
+ fstrcpy(request.data.sid, sid_string_static(sid));
/* Make request */
- result = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response);
+ result = winbindd_request_response(WINBINDD_LOOKUPSID, &request,
+ &response);
- /* Copy out result */
+ if (result != NSS_STATUS_SUCCESS) {
+ return False;
+ }
- if (result == NSS_STATUS_SUCCESS) {
- fstrcpy(dom_name, response.data.name.dom_name);
- fstrcpy(name, response.data.name.name);
- *name_type = (enum SID_NAME_USE)response.data.name.type;
+ /* Copy out result */
- DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
- sid_str, dom_name, name));
+ if (domain != NULL) {
+ *domain = talloc_strdup(mem_ctx, response.data.name.dom_name);
+ if (*domain == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
+ }
+ if (name != NULL) {
+ *name = talloc_strdup(mem_ctx, response.data.name.name);
+ if (*name == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
}
- return (result == NSS_STATUS_SUCCESS);
+ *name_type = (enum SID_NAME_USE)response.data.name.type;
+
+ DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
+ sid_string_static(sid), response.data.name.dom_name,
+ response.data.name.name));
+ return True;
}
/* Call winbindd to convert SID to uid */
@@ -233,7 +247,7 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
return (result == NSS_STATUS_SUCCESS);
}
-BOOL winbind_allocate_rid(uint32 *rid)
+BOOL winbind_allocate_uid(uid_t *uid)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -246,18 +260,19 @@ BOOL winbind_allocate_rid(uint32 *rid)
/* Make request */
- result = winbindd_request_response(WINBINDD_ALLOCATE_RID, &request, &response);
+ result = winbindd_request_response(WINBINDD_ALLOCATE_UID,
+ &request, &response);
if (result != NSS_STATUS_SUCCESS)
return False;
/* Copy out result */
- *rid = response.data.rid;
+ *uid = response.data.uid;
return True;
}
-BOOL winbind_allocate_rid_and_gid(uint32 *rid, gid_t *gid)
+BOOL winbind_allocate_gid(gid_t *gid)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -270,15 +285,14 @@ BOOL winbind_allocate_rid_and_gid(uint32 *rid, gid_t *gid)
/* Make request */
- result = winbindd_request_response(WINBINDD_ALLOCATE_RID_AND_GID, &request,
- &response);
+ result = winbindd_request_response(WINBINDD_ALLOCATE_GID,
+ &request, &response);
if (result != NSS_STATUS_SUCCESS)
return False;
/* Copy out result */
- *rid = response.data.rid_and_gid.rid;
- *gid = response.data.rid_and_gid.gid;
+ *gid = response.data.gid;
return True;
}
@@ -306,7 +320,7 @@ static int wb_getgroups(const char *user, gid_t **groups)
/* Return group list. Don't forget to free the group list
when finished. */
- *groups = (gid_t *)response.extra_data;
+ *groups = (gid_t *)response.extra_data.data;
return response.data.num_entries;
}
@@ -321,7 +335,7 @@ static int wb_getgroups(const char *user, gid_t **groups)
int winbind_initgroups(char *user, gid_t gid)
{
- gid_t *tgr, *groups = NULL;
+ gid_t *groups = NULL;
int result;
/* Call normal initgroups if we are a local user */
@@ -350,14 +364,12 @@ int winbind_initgroups(char *user, gid_t gid)
/* Add group to list if necessary */
if (!is_member) {
- tgr = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
-
- if (!tgr) {
+ groups = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
+ if (!groups) {
errno = ENOMEM;
result = -1;
goto done;
}
- else groups = tgr;
groups[ngroups] = gid;
ngroups++;
diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c
index 0e209279411..91ebdbd5844 100644
--- a/source/nsswitch/wb_common.c
+++ b/source/nsswitch/wb_common.c
@@ -37,7 +37,7 @@ void free_response(struct winbindd_response *response)
/* Free any allocated extra_data */
if (response)
- SAFE_FREE(response->extra_data);
+ SAFE_FREE(response->extra_data.data);
}
/* Initialise a request structure */
@@ -324,13 +324,13 @@ 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)) != -1) {
+ if ((fd = winbind_named_pipe_sock(response.extra_data.data)) != -1) {
close(winbindd_fd);
winbindd_fd = fd;
}
}
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return winbindd_fd;
#else
@@ -411,6 +411,10 @@ static int read_sock(void *buffer, int count)
int result = 0, nread = 0;
int total_time = 0, selret;
+ if (winbindd_fd == -1) {
+ return -1;
+ }
+
/* Read data from socket */
while(nread < count) {
struct timeval tv;
@@ -488,7 +492,7 @@ int read_reply(struct winbindd_response *response)
the server. This has no meaning in the client's address space
so we clear it out. */
- response->extra_data = NULL;
+ response->extra_data.data = NULL;
/* Read variable length response */
@@ -498,11 +502,11 @@ int read_reply(struct winbindd_response *response)
/* Mallocate memory for extra data */
- if (!(response->extra_data = malloc(extra_data_len))) {
+ if (!(response->extra_data.data = malloc(extra_data_len))) {
return -1;
}
- if ((result2 = read_sock(response->extra_data, extra_data_len))
+ if ((result2 = read_sock(response->extra_data.data, extra_data_len))
== -1) {
free_response(response);
return -1;
@@ -546,7 +550,7 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
}
if ((request->extra_len != 0) &&
- (write_sock(request->extra_data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) {
+ (write_sock(request->extra_data.data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) {
return NSS_STATUS_UNAVAIL;
}
@@ -627,3 +631,4 @@ BOOL winbind_on( void )
return putenv(s) != -1;
}
+
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 3a7a9e4b4f9..ad5ef715230 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -141,9 +141,9 @@ static BOOL wbinfo_get_usergroups(char *user)
return False;
for (i = 0; i < response.data.num_entries; i++)
- d_printf("%d\n", (int)((gid_t *)response.extra_data)[i]);
+ d_printf("%d\n", (int)((gid_t *)response.extra_data.data)[i]);
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return True;
}
@@ -169,13 +169,13 @@ static BOOL wbinfo_get_usersids(char *user_sid)
if (result != NSS_STATUS_SUCCESS)
return False;
- s = response.extra_data;
+ s = response.extra_data.data;
for (i = 0; i < response.data.num_entries; i++) {
d_printf("%s\n", s);
s += strlen(s) + 1;
}
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return True;
}
@@ -199,9 +199,9 @@ static BOOL wbinfo_get_userdomgroups(const char *user_sid)
return False;
if (response.data.num_entries != 0)
- d_printf("%s", (char *)response.extra_data);
+ printf("%s", (char *)response.extra_data.data);
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return True;
}
@@ -260,22 +260,26 @@ static BOOL wbinfo_wins_byip(char *ip)
/* List trusted domains */
-static BOOL wbinfo_list_domains(void)
+static BOOL wbinfo_list_domains(BOOL list_all_domains)
{
+ struct winbindd_request request;
struct winbindd_response response;
+ ZERO_STRUCT(request);
ZERO_STRUCT(response);
/* Send request */
- if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, NULL, &response) !=
+ request.data.list_all_domains = list_all_domains;
+
+ if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) !=
NSS_STATUS_SUCCESS)
return False;
/* Display response */
- if (response.extra_data) {
- const char *extra_data = (char *)response.extra_data;
+ if (response.extra_data.data) {
+ const char *extra_data = (char *)response.extra_data.data;
fstring name;
char *p;
@@ -290,7 +294,7 @@ static BOOL wbinfo_list_domains(void)
d_printf("%s\n", name);
}
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
}
return True;
@@ -317,10 +321,10 @@ static BOOL wbinfo_show_sequence(const char *domain)
/* Display response */
- if (response.extra_data) {
- char *extra_data = (char *)response.extra_data;
+ if (response.extra_data.data) {
+ char *extra_data = (char *)response.extra_data.data;
d_printf("%s", extra_data);
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
}
return True;
@@ -510,14 +514,26 @@ static BOOL wbinfo_sid_to_gid(char *sid)
return True;
}
-static BOOL wbinfo_allocate_rid(void)
+static BOOL wbinfo_allocate_uid(void)
{
- uint32 rid;
+ uid_t uid;
- if (!winbind_allocate_rid(&rid))
+ if (!winbind_allocate_uid(&uid))
return False;
- d_printf("New rid: %d\n", rid);
+ d_printf("New uid: %d\n", uid);
+
+ return True;
+}
+
+static BOOL wbinfo_allocate_gid(void)
+{
+ gid_t gid;
+
+ if (!winbind_allocate_gid(&gid))
+ return False;
+
+ d_printf("New gid: %d\n", gid);
return True;
}
@@ -577,6 +593,67 @@ static BOOL wbinfo_lookupname(char *name)
/* Authenticate a user with a plaintext password */
+static BOOL wbinfo_auth_krb5(char *username, const char *cctype, uint32 flags)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+ char *p;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ p = strchr(username, '%');
+
+ if (p) {
+ *p = 0;
+ fstrcpy(request.data.auth.user, username);
+ fstrcpy(request.data.auth.pass, p + 1);
+ *p = '%';
+ } else
+ fstrcpy(request.data.auth.user, username);
+
+ request.flags = flags;
+
+ fstrcpy(request.data.auth.krb5_cc_type, cctype);
+
+ request.data.auth.uid = geteuid();
+
+ result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
+
+ /* Display response */
+
+ d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n",
+ username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
+
+ if (response.data.auth.nt_status)
+ d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status,
+ response.data.auth.error_string);
+
+ if (result == NSS_STATUS_SUCCESS) {
+
+ if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
+ if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
+ d_printf("user_flgs: LOGON_CACHED_ACCOUNT\n");
+ }
+ }
+
+ if (response.data.auth.krb5ccname[0] != '\0') {
+ d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
+ } else {
+ d_printf("no credentials cached\n");
+ }
+ }
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
+/* Authenticate a user with a plaintext password */
+
static BOOL wbinfo_auth(char *username)
{
struct winbindd_request request;
@@ -759,12 +836,12 @@ static BOOL wbinfo_klog(char *username)
if (result != NSS_STATUS_SUCCESS)
return False;
- if (response.extra_data == NULL) {
+ if (response.extra_data.data == NULL) {
d_fprintf(stderr, "Did not get token data\n");
return False;
}
- if (!afs_settoken_str((char *)response.extra_data)) {
+ if (!afs_settoken_str((char *)response.extra_data.data)) {
d_fprintf(stderr, "Could not set token\n");
return False;
}
@@ -801,15 +878,15 @@ static BOOL print_domain_users(const char *domain)
/* Look through extra data */
- if (!response.extra_data)
+ if (!response.extra_data.data)
return False;
- extra_data = (const char *)response.extra_data;
+ extra_data = (const char *)response.extra_data.data;
while(next_token(&extra_data, name, ",", sizeof(fstring)))
d_printf("%s\n", name);
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return True;
}
@@ -839,15 +916,15 @@ static BOOL print_domain_groups(const char *domain)
/* Look through extra data */
- if (!response.extra_data)
+ if (!response.extra_data.data)
return False;
- extra_data = (const char *)response.extra_data;
+ extra_data = (const char *)response.extra_data.data;
while(next_token(&extra_data, name, ",", sizeof(fstring)))
d_printf("%s\n", name);
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return True;
}
@@ -968,7 +1045,10 @@ enum {
OPT_GETDCNAME,
OPT_USERDOMGROUPS,
OPT_USERSIDS,
- OPT_SEPARATOR
+ OPT_ALLOCATE_UID,
+ OPT_ALLOCATE_GID,
+ OPT_SEPARATOR,
+ OPT_LIST_ALL_DOMAINS
};
int main(int argc, char **argv)
@@ -997,9 +1077,13 @@ int main(int argc, char **argv)
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
- { "allocate-rid", 'A', POPT_ARG_NONE, 0, 'A', "Get a new RID out of idmap" },
+ { "allocate-uid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_UID,
+ "Get a new UID out of idmap" },
+ { "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID,
+ "Get a new GID out of idmap" },
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
+ { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
{ "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-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
@@ -1016,6 +1100,11 @@ int main(int argc, char **argv)
#ifdef WITH_FAKE_KASERVER
{ "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
#endif
+#ifdef HAVE_KRB5
+ { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
+ /* destroys wbinfo --help output */
+ /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
+#endif
{ "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
POPT_COMMON_VERSION
POPT_TABLEEND
@@ -1024,7 +1113,7 @@ int main(int argc, char **argv)
/* Samba client initialisation */
load_case_tables();
- if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
+ if (!lp_load(dyn_CONFIGFILE, True, False, False, True)) {
d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
dyn_CONFIGFILE, strerror(errno));
exit(1);
@@ -1120,9 +1209,15 @@ int main(int argc, char **argv)
goto done;
}
break;
- case 'A':
- if (!wbinfo_allocate_rid()) {
- d_fprintf(stderr, "Could not allocate a RID\n");
+ case OPT_ALLOCATE_UID:
+ if (!wbinfo_allocate_uid()) {
+ d_fprintf(stderr, "Could not allocate a uid\n");
+ goto done;
+ }
+ break;
+ case OPT_ALLOCATE_GID:
+ if (!wbinfo_allocate_gid()) {
+ d_fprintf(stderr, "Could not allocate a gid\n");
goto done;
}
break;
@@ -1133,7 +1228,7 @@ int main(int argc, char **argv)
}
break;
case 'm':
- if (!wbinfo_list_domains()) {
+ if (!wbinfo_list_domains(False)) {
d_fprintf(stderr, "Could not list trusted domains\n");
goto done;
}
@@ -1190,6 +1285,40 @@ int main(int argc, char **argv)
goto done;
break;
}
+ case 'K': {
+ BOOL got_error = False;
+ uint32 flags = WBFLAG_PAM_KRB5 |
+ WBFLAG_PAM_CACHED_LOGIN |
+ WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
+ WBFLAG_PAM_INFO3_TEXT;
+ fstring tok;
+ int i;
+ const char *arg[] = { NULL, NULL };
+ const char *cctypes[] = { "FILE",
+ "KCM",
+ "KCM:0",
+ "Garbage",
+ NULL,
+ "0"};
+
+ arg[0] = string_arg;
+
+ while (next_token(arg, tok, LIST_SEP, sizeof(tok))) {
+
+ for (i=0; i < ARRAY_SIZE(cctypes); i++) {
+ if (!wbinfo_auth_krb5(tok, cctypes[i], flags)) {
+ d_fprintf(stderr, "Could not authenticate user [%s] with "
+ "Kerberos (ccache: %s)\n", tok, cctypes[i]);
+ got_error = True;
+ }
+ }
+ }
+
+ if (got_error)
+ goto done;
+
+ break;
+ }
case 'k':
if (!wbinfo_klog(string_arg)) {
d_fprintf(stderr, "Could not klog user\n");
@@ -1198,7 +1327,7 @@ int main(int argc, char **argv)
break;
case 'p':
if (!wbinfo_ping()) {
- d_fprintf(stderr, "Could not ping winbindd!\n");
+ d_fprintf(stderr, "could not ping winbindd!\n");
goto done;
}
break;
@@ -1223,6 +1352,10 @@ int main(int argc, char **argv)
d_printf("%c\n", sep);
break;
}
+ case OPT_LIST_ALL_DOMAINS:
+ if (!wbinfo_list_domains(True)) {
+ goto done;
+ }
/* generic configuration options */
case OPT_DOMAIN_NAME:
break;
diff --git a/source/nsswitch/winbind_nss_aix.c b/source/nsswitch/winbind_nss_aix.c
index 0a8bef736ca..b898e3c3af2 100644
--- a/source/nsswitch/winbind_nss_aix.c
+++ b/source/nsswitch/winbind_nss_aix.c
@@ -284,7 +284,7 @@ static struct group *wb_aix_getgrgid(gid_t gid)
HANDLE_ERRORS(ret);
- grp = fill_grent(&response.data.gr, response.extra_data);
+ grp = fill_grent(&response.data.gr, response.extra_data.data);
free_response(&response);
@@ -314,7 +314,7 @@ static struct group *wb_aix_getgrnam(const char *name)
HANDLE_ERRORS(ret);
- grp = fill_grent(&response.data.gr, response.extra_data);
+ grp = fill_grent(&response.data.gr, response.extra_data.data);
free_response(&response);
@@ -371,7 +371,7 @@ static char *wb_aix_getgrset(char *user)
HANDLE_ERRORS(ret);
num_gids = response.data.num_entries;
- gid_list = (gid_t *)response.extra_data;
+ gid_list = (gid_t *)response.extra_data.data;
/* allocate a space large enough to contruct the string */
tmpbuf = malloc(num_gids*12);
@@ -477,7 +477,7 @@ static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
return -1;
}
- len = strlen(response.extra_data);
+ len = strlen(response.extra_data.data);
s = malloc(len+2);
if (!s) {
@@ -486,7 +486,7 @@ static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size)
return -1;
}
- memcpy(s, response.extra_data, len+1);
+ memcpy(s, response.extra_data.data, len+1);
replace_commas(s);
@@ -525,7 +525,7 @@ static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
return -1;
}
- len = strlen(response.extra_data);
+ len = strlen(response.extra_data.data);
s = malloc(len+2);
if (!s) {
@@ -534,7 +534,7 @@ static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size)
return -1;
}
- memcpy(s, response.extra_data, len+1);
+ memcpy(s, response.extra_data.data, len+1);
replace_commas(s);
diff --git a/source/nsswitch/winbind_nss_config.h b/source/nsswitch/winbind_nss_config.h
index a3243b99e30..0400b2fb36d 100644
--- a/source/nsswitch/winbind_nss_config.h
+++ b/source/nsswitch/winbind_nss_config.h
@@ -24,6 +24,12 @@
#ifndef _WINBIND_NSS_CONFIG_H
#define _WINBIND_NSS_CONFIG_H
+/* shutup the compiler warnings due to krb5.h on i
+ 64-bit sles9 */
+#ifdef SIZEOF_LONG
+#undef SIZEOF_LONG
+#endif
+
/* Include header files from data in config.h file */
#ifndef NO_CONFIG_H
@@ -119,6 +125,19 @@ typedef int BOOL;
#define uint8 unsigned char
#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
+
+
/* zero a structure */
#ifndef ZERO_STRUCT
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
diff --git a/source/nsswitch/winbind_nss_irix.c b/source/nsswitch/winbind_nss_irix.c
index 73f3b4f33a0..05085ba1f39 100644
--- a/source/nsswitch/winbind_nss_irix.c
+++ b/source/nsswitch/winbind_nss_irix.c
@@ -216,8 +216,8 @@ winbind_callback(nsd_file_t **rqp, int fd)
break;
case WINBINDD_GETGRNAM:
case WINBINDD_GETGRGID:
- if (gr->num_gr_mem && response.extra_data)
- members = response.extra_data;
+ if (gr->num_gr_mem && response.extra_data.data)
+ members = response.extra_data.data;
else
members = "";
snprintf(result,maxlen,"%s:%s:%d:%s\n",
@@ -234,13 +234,13 @@ winbind_callback(nsd_file_t **rqp, int fd)
"callback (winbind) - %d GETGRENT responses\n",
response.data.num_entries);
if (response.data.num_entries) {
- gr = (struct winbindd_gr *)response.extra_data;
+ gr = (struct winbindd_gr *)response.extra_data.data;
if (! gr ) {
- nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
+ nsd_logprintf(NSD_LOG_MIN, " no extra_data.data\n");
free_response(&response);
return NSD_ERROR;
}
- members = (char *)response.extra_data +
+ members = (char *)response.extra_data.data +
(response.data.num_entries * sizeof(struct winbindd_gr));
for (i = 0; i < response.data.num_entries; i++) {
snprintf(result,maxlen,"%s:%s:%d:%s\n",
@@ -262,7 +262,7 @@ winbind_callback(nsd_file_t **rqp, int fd)
"callback (winbind) - %d GETPWENT responses\n",
response.data.num_entries);
if (response.data.num_entries) {
- pw = (struct winbindd_pw *)response.extra_data;
+ pw = (struct winbindd_pw *)response.extra_data.data;
if (! pw ) {
nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
free_response(&response);
@@ -335,11 +335,11 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
switch (rq->f_index) {
case LOOKUP:
timeout = nsd_attr_fetch_long(rq->f_attrs,
- "lookup_timeout", 10, 10 * 1000);
+ "lookup_timeout", 10, 10);
break;
case LIST:
timeout = nsd_attr_fetch_long(rq->f_attrs,
- "list_timeout", 10, 10 * 1000);
+ "list_timeout", 10, 10);
break;
default:
nsd_logprintf(NSD_LOG_OPER,
@@ -366,9 +366,11 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
/*
* Set up callback and timeouts
*/
- nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",winbindd_fd);
- nsd_callback_new(winbindd_fd,winbind_callback,NSD_READ);
- nsd_timeout_new(rq,timeout,winbind_timeout,(void *)0);
+ nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",
+ winbindd_fd);
+
+ nsd_callback_new(winbindd_fd, winbind_callback, NSD_READ);
+ nsd_timeout_new(rq, timeout * 1000, winbind_timeout, NULL);
return NSD_CONTINUE;
}
diff --git a/source/nsswitch/winbind_nss_irix.h b/source/nsswitch/winbind_nss_irix.h
index 7878abb981a..339e316ff92 100644
--- a/source/nsswitch/winbind_nss_irix.h
+++ b/source/nsswitch/winbind_nss_irix.h
@@ -41,8 +41,4 @@ typedef enum
NSS_STATUS_TRYAGAIN=NS_TRYAGAIN
} NSS_STATUS;
-#define NSD_MEM_STATIC 0
-#define NSD_MEM_VOLATILE 1
-#define NSD_MEM_DYNAMIC 2
-
#endif /* _WINBIND_NSS_IRIX_H */
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index c0b8bf3a75d..78a39f28731 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -370,7 +370,7 @@ _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
return_result:
- pw_cache = getpwent_response.extra_data;
+ pw_cache = getpwent_response.extra_data.data;
/* Check data is valid */
@@ -613,7 +613,7 @@ winbind_getgrent(enum winbindd_cmd cmd,
return_result:
- gr_cache = getgrent_response.extra_data;
+ gr_cache = getgrent_response.extra_data.data;
/* Check data is valid */
@@ -629,7 +629,7 @@ winbind_getgrent(enum winbindd_cmd cmd,
num_gr_cache * sizeof(struct winbindd_gr);
ret = fill_grent(result, &gr_cache[ndx_gr_cache],
- ((char *)getgrent_response.extra_data)+mem_ofs,
+ ((char *)getgrent_response.extra_data.data)+mem_ofs,
&buffer, &buflen);
/* Out of memory - try again */
@@ -704,7 +704,7 @@ _nss_winbind_getgrnam_r(const char *name,
if (ret == NSS_STATUS_SUCCESS) {
ret = fill_grent(result, &response.data.gr,
- response.extra_data,
+ response.extra_data.data,
&buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
@@ -719,7 +719,7 @@ _nss_winbind_getgrnam_r(const char *name,
/* We've been called again */
ret = fill_grent(result, &response.data.gr,
- response.extra_data, &buffer, &buflen);
+ response.extra_data.data, &buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
@@ -767,7 +767,7 @@ _nss_winbind_getgrgid_r(gid_t gid,
if (ret == NSS_STATUS_SUCCESS) {
ret = fill_grent(result, &response.data.gr,
- response.extra_data,
+ response.extra_data.data,
&buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
@@ -782,7 +782,7 @@ _nss_winbind_getgrgid_r(gid_t gid,
/* We've been called again */
ret = fill_grent(result, &response.data.gr,
- response.extra_data, &buffer, &buflen);
+ response.extra_data.data, &buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = True;
@@ -825,7 +825,7 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
if (ret == NSS_STATUS_SUCCESS) {
int num_gids = response.data.num_entries;
- gid_t *gid_list = (gid_t *)response.extra_data;
+ gid_t *gid_list = (gid_t *)response.extra_data.data;
/* Copy group list to client */
@@ -911,7 +911,7 @@ _nss_winbind_getusersids(const char *user_sid, char **group_sids,
*num_groups = response.data.num_entries;
*group_sids = buffer;
- memcpy(buffer, response.extra_data, response.length - sizeof(response));
+ memcpy(buffer, response.extra_data.data, response.length - sizeof(response));
errno = *errnop = 0;
done:
diff --git a/source/nsswitch/winbind_nss_solaris.c b/source/nsswitch/winbind_nss_solaris.c
index b94b444fb4c..04f464a7983 100644
--- a/source/nsswitch/winbind_nss_solaris.c
+++ b/source/nsswitch/winbind_nss_solaris.c
@@ -185,7 +185,7 @@ _nss_winbind_passwd_constr (const char* db_name,
{
nss_backend_t *be;
- if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) )
+ if(!(be = SMB_MALLOC_P(nss_backend_t)) )
return NULL;
be->ops = passwd_ops;
@@ -329,7 +329,7 @@ _nss_winbind_group_constr (const char* db_name,
{
nss_backend_t* be;
- if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) )
+ if(!(be = SMB_MALLOC_P(nss_backend_t)) )
return NULL;
be->ops = group_ops;
@@ -580,7 +580,7 @@ _nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops)
{
nss_backend_t* be;
- if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) )
+ if(!(be = SMB_MALLOC_P(nss_backend_t)) )
return NULL;
be->ops = ops;
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index e9b9ed42c4f..997991a8c62 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -47,7 +47,7 @@ static BOOL reload_services_file(void)
}
reopen_logs();
- ret = lp_load(dyn_CONFIGFILE,False,False,True);
+ ret = lp_load(dyn_CONFIGFILE,False,False,True,True);
reopen_logs();
load_interfaces();
@@ -56,46 +56,6 @@ static BOOL reload_services_file(void)
}
-#if DUMP_CORE
-
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
- char *p;
- pstring dname;
- pstrcpy( dname, lp_logfile() );
- if ((p=strrchr(dname,'/')))
- *p=0;
- pstrcat( dname, "/corefiles" );
- mkdir( dname, 0700 );
- sys_chown( dname, getuid(), getgid() );
- chmod( dname, 0700 );
- if ( chdir(dname) )
- return( False );
- umask( ~(0700) );
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
- {
- struct rlimit rlp;
- getrlimit( RLIMIT_CORE, &rlp );
- rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
- setrlimit( RLIMIT_CORE, &rlp );
- getrlimit( RLIMIT_CORE, &rlp );
- DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
- }
-#endif
-#endif
-
- DEBUG(0,("Dumping core in %s\n",dname));
- abort();
- return( True );
-} /* dump_core */
-#endif
-
/**************************************************************************** **
Handle a fault..
**************************************************************************** */
@@ -120,7 +80,7 @@ static void winbindd_status(void)
if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
DEBUG(2, ("\tclient list:\n"));
for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
- DEBUG(2, ("\t\tpid %lu, sock %d\n",
+ DEBUGADD(2, ("\t\tpid %lu, sock %d\n",
(unsigned long)tmp->pid, tmp->sock));
}
}
@@ -250,6 +210,7 @@ static struct winbindd_dispatch_table {
{ WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" },
{ 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" },
/* Enumeration functions */
@@ -270,9 +231,8 @@ 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_ALLOCATE_RID, winbindd_allocate_rid, "ALLOCATE_RID" },
- { WINBINDD_ALLOCATE_RID_AND_GID, winbindd_allocate_rid_and_gid,
- "ALLOCATE_RID_AND_GID" },
+ { WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" },
+ { WINBINDD_ALLOCATE_GID, winbindd_allocate_uid, "ALLOCATE_GID" },
/* Miscellaneous */
@@ -305,7 +265,7 @@ static void process_request(struct winbindd_cli_state *state)
/* Free response data - we may be interrupted and receive another
command before being able to send this data off. */
- SAFE_FREE(state->response.extra_data);
+ SAFE_FREE(state->response.extra_data.data);
ZERO_STRUCT(state->response);
@@ -475,8 +435,8 @@ static void response_extra_sent(void *private_data, BOOL success)
return;
}
- SAFE_FREE(state->request.extra_data);
- SAFE_FREE(state->response.extra_data);
+ SAFE_FREE(state->request.extra_data.data);
+ SAFE_FREE(state->response.extra_data.data);
setup_async_read(&state->fd_event, &state->request, sizeof(uint32),
request_len_recv, state);
@@ -503,7 +463,7 @@ static void response_main_sent(void *private_data, BOOL success)
return;
}
- setup_async_write(&state->fd_event, state->response.extra_data,
+ setup_async_write(&state->fd_event, state->response.extra_data.data,
state->response.length - sizeof(state->response),
response_extra_sent, state);
}
@@ -572,7 +532,7 @@ static void request_main_recv(void *private_data, BOOL success)
}
if (state->request.extra_len == 0) {
- state->request.extra_data = NULL;
+ state->request.extra_data.data = NULL;
request_recv(state, True);
return;
}
@@ -581,24 +541,24 @@ static void request_main_recv(void *private_data, BOOL success)
(state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) {
DEBUG(3, ("Got request with %d bytes extra data on "
"unprivileged socket\n", (int)state->request.extra_len));
- state->request.extra_data = NULL;
+ state->request.extra_data.data = NULL;
state->finished = True;
return;
}
- state->request.extra_data =
+ state->request.extra_data.data =
SMB_MALLOC_ARRAY(char, state->request.extra_len + 1);
- if (state->request.extra_data == NULL) {
+ if (state->request.extra_data.data == NULL) {
DEBUG(0, ("malloc failed\n"));
state->finished = True;
return;
}
/* Ensure null termination */
- state->request.extra_data[state->request.extra_len] = '\0';
+ state->request.extra_data.data[state->request.extra_len] = '\0';
- setup_async_read(&state->fd_event, state->request.extra_data,
+ setup_async_read(&state->fd_event, state->request.extra_data.data,
state->request.extra_len, request_recv, state);
}
@@ -680,7 +640,7 @@ static void remove_client(struct winbindd_cli_state *state)
/* We may have some extra data that was not freed if the
client was killed unexpectedly */
- SAFE_FREE(state->response.extra_data);
+ SAFE_FREE(state->response.extra_data.data);
if (state->mem_ctx != NULL) {
talloc_destroy(state->mem_ctx);
@@ -692,7 +652,7 @@ static void remove_client(struct winbindd_cli_state *state)
/* Remove from list and free */
winbindd_remove_client(state);
- talloc_free(state);
+ TALLOC_FREE(state);
}
}
@@ -751,8 +711,8 @@ static void process_loop(void)
/* Free up temporary memory */
- lp_talloc_free();
- main_loop_talloc_free();
+ lp_TALLOC_FREE();
+ main_loop_TALLOC_FREE();
/* Initialise fd lists for select() */
@@ -912,10 +872,12 @@ int main(int argc, char **argv)
pstring logfile;
static BOOL Fork = True;
static BOOL log_stdout = False;
+ static BOOL no_process_group = False;
struct poptOption long_options[] = {
POPT_AUTOHELP
{ "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
{ "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" },
+ { "no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
{ "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" },
{ "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, True, "Disable caching" },
POPT_COMMON_SAMBA
@@ -931,6 +893,7 @@ int main(int argc, char **argv)
CatchSignal(SIGUSR2, SIG_IGN);
fault_setup((void (*)(void *))fault_quit );
+ dump_core_setup("winbindd");
load_case_tables();
@@ -943,7 +906,10 @@ int main(int argc, char **argv)
/* Set environment variable so we don't recursively call ourselves.
This may also be useful interactively. */
- setenv(WINBINDD_DONT_ENV, "1", 1);
+ if ( !winbind_off() ) {
+ DEBUG(0,("Failed to disable recusive winbindd calls. Exiting.\n"));
+ exit(1);
+ }
/* Initialise samba/rpc client stuff */
@@ -1036,7 +1002,7 @@ int main(int argc, char **argv)
CatchSignal(SIGHUP, sighup_handler);
if (!interactive)
- become_daemon(Fork);
+ become_daemon(Fork, no_process_group);
pidfile_create("winbindd");
@@ -1045,7 +1011,7 @@ int main(int argc, char **argv)
* If we're interactive we want to set our own process group for
* signal management.
*/
- if (interactive)
+ if (interactive && !no_process_group)
setpgid( (pid_t)0, (pid_t)0);
#endif
@@ -1054,7 +1020,7 @@ int main(int argc, char **argv)
/* Initialise messaging system */
if (!message_init()) {
- DEBUG(0, ("unable to initialise messaging system\n"));
+ DEBUG(0, ("unable to initialize messaging system\n"));
exit(1);
}
@@ -1062,15 +1028,24 @@ int main(int argc, char **argv)
as to SIGHUP signal */
message_register(MSG_SMB_CONF_UPDATED, msg_reload_services);
message_register(MSG_SHUTDOWN, msg_shutdown);
-
+
+ /* Handle online/offline messages. */
+ message_register(MSG_WINBIND_OFFLINE,winbind_msg_offline);
+ message_register(MSG_WINBIND_ONLINE,winbind_msg_online);
+
poptFreeContext(pc);
netsamlogon_cache_init(); /* Non-critical */
- init_domain_list();
+ if (!init_domain_list()) {
+ DEBUG(0,("unable to initalize domain list\n"));
+ exit(1);
+ }
init_idmap_child();
+ winbindd_flush_nscd_cache();
+
/* Loop waiting for requests */
while (1)
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 00a02330559..e5f1c9699ca 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -29,6 +29,10 @@
#include "winbindd_nss.h"
+#ifdef HAVE_LIBNSCD
+#include "libnscd.h"
+#endif
+
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
@@ -143,7 +147,9 @@ 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;
};
@@ -157,7 +163,8 @@ struct winbindd_domain {
BOOL native_mode; /* is this a win2k domain in native mode ? */
BOOL active_directory; /* is this a win2k active directory ? */
BOOL primary; /* is this our primary domain ? */
- BOOL internal; /* BUILTIN and member SAM */
+ BOOL internal; /* BUILTIN and member SAM */
+ BOOL online; /* is this domain available ? */
/* Lookup methods for this domain (LDAP or RPC) */
struct winbindd_methods *methods;
@@ -268,6 +275,16 @@ struct winbindd_methods {
/* return the current global sequence number */
NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq);
+ /* return the lockout policy */
+ NTSTATUS (*lockout_policy)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_12 *lockout_policy);
+
+ /* return the lockout policy */
+ NTSTATUS (*password_policy)(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_1 *password_policy);
+
/* enumerate trusted domains */
NTSTATUS (*trusted_domains)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -305,7 +322,7 @@ struct winbindd_idmap_methods {
#define WINBINDD_ESTABLISH_LOOP 30
#define WINBINDD_RESCAN_FREQ 300
-
+#define WINBINDD_PAM_AUTH_KRB5_RENEW_TIME 2592000 /* one month */
#define DOM_SEQUENCE_NONE ((uint32)-1)
#endif /* _WINBINDD_H */
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index 96137733e24..5e0d4cfe8e0 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -102,6 +102,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
ads->auth.realm = SMB_STRDUP( lp_realm() );
}
+ ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;
+
status = ads_connect(ads);
if (!ADS_ERR_OK(status) || !ads->config.realm) {
extern struct winbindd_methods msrpc_methods, cache_methods;
@@ -889,8 +891,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
struct ds_domain_trust *domains = NULL;
int count = 0;
int i;
- /* i think we only need our forest and downlevel trusted domains */
- uint32 flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND;
+ uint32 flags = DS_DOMAIN_DIRECT_OUTBOUND;
struct rpc_pipe_client *cli;
DEBUG(3,("ads: trusted_domains\n"));
@@ -963,6 +964,8 @@ struct winbindd_methods ads_methods = {
msrpc_lookup_useraliases,
lookup_groupmem,
sequence_number,
+ msrpc_lockout_policy,
+ msrpc_password_policy,
trusted_domains,
};
diff --git a/source/nsswitch/winbindd_async.c b/source/nsswitch/winbindd_async.c
index 180fd651f57..7f282df929d 100644
--- a/source/nsswitch/winbindd_async.c
+++ b/source/nsswitch/winbindd_async.c
@@ -4,6 +4,7 @@
Async helpers for blocking functions
Copyright (C) Volker Lendecke 2005
+ Copyright (C) Volker Lendecke 2006
The helpers always consist of three functions:
@@ -364,6 +365,10 @@ void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
ZERO_STRUCT(request);
request.cmd = WINBINDD_DUAL_SID2GID;
sid_to_string(request.data.dual_sid2id.sid, sid);
+
+ 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);
@@ -391,6 +396,15 @@ enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
state->request.data.dual_sid2id.alloc ?
0 : ID_QUERY_ONLY);
+ /* 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;
+ }
+ }
+
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
@@ -819,7 +833,7 @@ static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
- aliases_str = response->extra_data;
+ aliases_str = response->extra_data.data;
if (aliases_str == NULL) {
DEBUG(10, ("getsidaliases return 0 SIDs\n"));
@@ -833,7 +847,7 @@ static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
- SAFE_FREE(response->extra_data);
+ SAFE_FREE(response->extra_data.data);
cont(private_data, True, sids, num_sids);
}
@@ -864,7 +878,7 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain,
ZERO_STRUCT(request);
request.cmd = WINBINDD_DUAL_GETSIDALIASES;
request.extra_len = len;
- request.extra_data = sidstr;
+ request.extra_data.data = sidstr;
do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
cont, private_data);
@@ -884,7 +898,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
- sidstr = state->request.extra_data;
+ sidstr = state->request.extra_data.data;
if (sidstr == NULL)
sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
@@ -924,14 +938,14 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
}
if (!print_sidlist(NULL, sids, num_sids,
- (char **)&state->response.extra_data, &len)) {
+ (char **)&state->response.extra_data.data, &len)) {
DEBUG(0, ("Could not print_sidlist\n"));
return WINBINDD_ERROR;
}
- if (state->response.extra_data != NULL) {
+ if (state->response.extra_data.data != NULL) {
DEBUG(10, ("aliases_list: %s\n",
- (char *)state->response.extra_data));
+ (char *)state->response.extra_data.data));
state->response.length += len+1;
}
@@ -942,6 +956,7 @@ struct gettoken_state {
TALLOC_CTX *mem_ctx;
DOM_SID user_sid;
struct winbindd_domain *alias_domain;
+ struct winbindd_domain *local_alias_domain;
struct winbindd_domain *builtin_domain;
DOM_SID *sids;
size_t num_sids;
@@ -976,6 +991,7 @@ void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
state->mem_ctx = mem_ctx;
sid_copy(&state->user_sid, user_sid);
state->alias_domain = find_our_domain();
+ state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
state->builtin_domain = find_builtin_domain();
state->cont = cont;
state->private_data = private_data;
@@ -1010,12 +1026,17 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
return;
}
- sids_str = response->extra_data;
+ sids_str = response->extra_data.data;
if (sids_str == NULL) {
- DEBUG(10, ("Received no domain groups\n"));
- state->cont(state->private_data, True, NULL, 0);
- return;
+ /* This could be normal if we are dealing with a
+ local user and local groups */
+
+ if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
+ DEBUG(10, ("Received no domain groups\n"));
+ state->cont(state->private_data, True, NULL, 0);
+ return;
+ }
}
state->sids = NULL;
@@ -1024,14 +1045,14 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
&state->num_sids);
- if (!parse_sidlist(mem_ctx, sids_str, &state->sids,
+ if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
&state->num_sids)) {
DEBUG(0, ("Could not parse sids\n"));
state->cont(state->private_data, False, NULL, 0);
return;
}
- SAFE_FREE(response->extra_data);
+ SAFE_FREE(response->extra_data.data);
if (state->alias_domain == NULL) {
DEBUG(10, ("Don't expand domain local groups\n"));
@@ -1062,9 +1083,19 @@ static void gettoken_recvaliases(void *private_data, BOOL success,
add_sid_to_array(state->mem_ctx, &aliases[i],
&state->sids, &state->num_sids);
+ if (state->local_alias_domain != NULL) {
+ struct winbindd_domain *local_domain = state->local_alias_domain;
+ DEBUG(10, ("Expanding our own local groups\n"));
+ state->local_alias_domain = NULL;
+ winbindd_getsidaliases_async(local_domain, state->mem_ctx,
+ state->sids, state->num_sids,
+ gettoken_recvaliases, state);
+ return;
+ }
+
if (state->builtin_domain != NULL) {
struct winbindd_domain *builtin_domain = state->builtin_domain;
- DEBUG(10, ("Expanding our own local groups\n"));
+ DEBUG(10, ("Expanding our own BUILTIN groups\n"));
state->builtin_domain = NULL;
winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
state->sids, state->num_sids,
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index 1d047b8356f..76e49ee96a0 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -6,7 +6,7 @@
Copyright (C) Andrew Tridgell 2001
Copyright (C) Gerald Carter 2003
Copyright (C) Volker Lendecke 2005
-
+ 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
@@ -29,6 +29,12 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+/* 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. */
+
+static BOOL global_winbindd_offline_state;
+
struct winbind_cache {
TDB_CONTEXT *tdb;
};
@@ -44,29 +50,6 @@ struct cache_entry {
static struct winbind_cache *wcache;
-/* flush the cache */
-void wcache_flush_cache(void)
-{
- extern BOOL opt_nocache;
-
- if (!wcache)
- return;
- if (wcache->tdb) {
- tdb_close(wcache->tdb);
- wcache->tdb = NULL;
- }
- if (opt_nocache)
- return;
-
- wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
- TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
-
- if (!wcache->tdb) {
- DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
- }
- DEBUG(10,("wcache_flush_cache success\n"));
-}
-
void winbindd_check_cache_size(time_t t)
{
static time_t last_check_time;
@@ -100,7 +83,9 @@ void winbindd_check_cache_size(time_t t)
static struct winbind_cache *get_cache(struct winbindd_domain *domain)
{
struct winbind_cache *ret = wcache;
+#ifdef HAVE_ADS
struct winbindd_domain *our_domain = domain;
+#endif
/* we have to know what type of domain we are dealing with first */
@@ -188,6 +173,22 @@ static uint32 centry_uint32(struct cache_entry *centry)
}
/*
+ pull a uint16 from a cache entry
+*/
+static uint16 centry_uint16(struct cache_entry *centry)
+{
+ uint16 ret;
+ if (centry->len - centry->ofs < 2) {
+ DEBUG(0,("centry corruption? needed 2 bytes, have %d\n",
+ centry->len - centry->ofs));
+ smb_panic("centry_uint16");
+ }
+ ret = CVAL(centry->data, centry->ofs);
+ centry->ofs += 2;
+ return ret;
+}
+
+/*
pull a uint8 from a cache entry
*/
static uint8 centry_uint8(struct cache_entry *centry)
@@ -203,6 +204,40 @@ static uint8 centry_uint8(struct cache_entry *centry)
return ret;
}
+/*
+ pull a NTTIME from a cache entry
+*/
+static NTTIME centry_nttime(struct cache_entry *centry)
+{
+ NTTIME ret;
+ if (centry->len - centry->ofs < 8) {
+ DEBUG(0,("centry corruption? needed 8 bytes, have %d\n",
+ centry->len - centry->ofs));
+ smb_panic("centry_nttime");
+ }
+ ret.low = IVAL(centry->data, centry->ofs);
+ centry->ofs += 4;
+ ret.high = IVAL(centry->data, centry->ofs);
+ centry->ofs += 4;
+ return ret;
+}
+
+/*
+ pull a time_t from a cache entry
+*/
+static time_t centry_time(struct cache_entry *centry)
+{
+ time_t ret;
+ if (centry->len - centry->ofs < sizeof(time_t)) {
+ DEBUG(0,("centry corruption? needed %d bytes, have %d\n",
+ sizeof(time_t), centry->len - centry->ofs));
+ smb_panic("centry_time");
+ }
+ ret = IVAL(centry->data, centry->ofs); /* FIXME: correct ? */
+ centry->ofs += sizeof(time_t);
+ return ret;
+}
+
/* pull a string from a cache entry, using the supplied
talloc context
*/
@@ -224,10 +259,7 @@ static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
smb_panic("centry_string");
}
- if (mem_ctx != NULL)
- ret = TALLOC(mem_ctx, len+1);
- else
- ret = SMB_MALLOC(len+1);
+ ret = TALLOC(mem_ctx, len+1);
if (!ret) {
smb_panic("centry_string out of memory\n");
}
@@ -240,14 +272,13 @@ static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx)
/* pull a string from a cache entry, using the supplied
talloc context
*/
-static BOOL centry_sid(struct cache_entry *centry, DOM_SID *sid)
+static BOOL centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx, DOM_SID *sid)
{
char *sid_string;
- sid_string = centry_string(centry, NULL);
+ sid_string = centry_string(centry, mem_ctx);
if (!string_to_sid(sid, sid_string)) {
return False;
}
- SAFE_FREE(sid_string);
return True;
}
@@ -403,10 +434,28 @@ done:
*/
static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry)
{
+ /* If we've been told to be offline - stay in that state... */
+ if (lp_winbind_offline_logon() && global_winbindd_offline_state) {
+ DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n",
+ keystr, domain->name ));
+ 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.
+ * This deals with transient offline states... */
+
+ if (!domain->online &&
+ !NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, domain->dcname))) {
+ DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n",
+ keystr, domain->name ));
+ return False;
+ }
+
/* if the server is OK and our cache entry came from when it was down then
the entry is invalid */
- if (domain->sequence_number != DOM_SEQUENCE_NONE &&
- centry->sequence_number == DOM_SEQUENCE_NONE) {
+ if ((domain->sequence_number != DOM_SEQUENCE_NONE) &&
+ (centry->sequence_number == DOM_SEQUENCE_NONE)) {
DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n",
keystr, domain->name ));
return True;
@@ -428,35 +477,17 @@ static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, s
return True;
}
-/*
- fetch an entry from the cache, with a varargs key. auto-fetch the sequence
- number and return status
-*/
-static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
- struct winbindd_domain *domain,
- const char *format, ...) PRINTF_ATTRIBUTE(3,4);
-static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
- struct winbindd_domain *domain,
- const char *format, ...)
+static struct cache_entry *wcache_fetch_raw(char *kstr)
{
- va_list ap;
- char *kstr;
TDB_DATA data;
struct cache_entry *centry;
TDB_DATA key;
- refresh_sequence_number(domain, False);
-
- va_start(ap, format);
- smb_xvasprintf(&kstr, format, ap);
- va_end(ap);
-
key.dptr = kstr;
key.dsize = strlen(kstr);
data = tdb_fetch(wcache->tdb, key);
if (!data.dptr) {
/* a cache miss */
- free(kstr);
return NULL;
}
@@ -467,16 +498,44 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
if (centry->len < 8) {
/* huh? corrupt cache? */
- DEBUG(10,("wcache_fetch: Corrupt cache for key %s domain %s (len < 8) ?\n",
- kstr, domain->name ));
+ DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s (len < 8) ?\n", kstr));
centry_free(centry);
- free(kstr);
return NULL;
}
centry->status = NT_STATUS(centry_uint32(centry));
centry->sequence_number = centry_uint32(centry);
+ return centry;
+}
+
+/*
+ fetch an entry from the cache, with a varargs key. auto-fetch the sequence
+ number and return status
+*/
+static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
+ struct winbindd_domain *domain,
+ const char *format, ...) PRINTF_ATTRIBUTE(3,4);
+static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
+ struct winbindd_domain *domain,
+ const char *format, ...)
+{
+ va_list ap;
+ char *kstr;
+ struct cache_entry *centry;
+
+ refresh_sequence_number(domain, False);
+
+ va_start(ap, format);
+ smb_xvasprintf(&kstr, format, ap);
+ va_end(ap);
+
+ centry = wcache_fetch_raw(kstr);
+ if (centry == NULL) {
+ free(kstr);
+ return NULL;
+ }
+
if (centry_expired(domain, kstr, centry)) {
DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n",
@@ -499,16 +558,14 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
*/
static void centry_expand(struct cache_entry *centry, uint32 len)
{
- uint8 *p;
if (centry->len - centry->ofs >= len)
return;
centry->len *= 2;
- p = SMB_REALLOC(centry->data, centry->len);
- if (!p) {
+ centry->data = SMB_REALLOC(centry->data, 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");
}
- centry->data = p;
}
/*
@@ -522,6 +579,16 @@ static void centry_put_uint32(struct cache_entry *centry, uint32 v)
}
/*
+ push a uint16 into a centry
+*/
+static void centry_put_uint16(struct cache_entry *centry, uint16 v)
+{
+ centry_expand(centry, 2);
+ SIVAL(centry->data, centry->ofs, v);
+ centry->ofs += 2;
+}
+
+/*
push a uint8 into a centry
*/
static void centry_put_uint8(struct cache_entry *centry, uint8 v)
@@ -563,6 +630,28 @@ static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid)
}
/*
+ push a NTTIME into a centry
+*/
+static void centry_put_nttime(struct cache_entry *centry, NTTIME nt)
+{
+ centry_expand(centry, 8);
+ SIVAL(centry->data, centry->ofs, nt.low);
+ centry->ofs += 4;
+ SIVAL(centry->data, centry->ofs, nt.high);
+ centry->ofs += 4;
+}
+
+/*
+ push a time_t into a centry
+*/
+static void centry_put_time(struct cache_entry *centry, time_t t)
+{
+ centry_expand(centry, sizeof(time_t));
+ SIVAL(centry->data, centry->ofs, t); /* FIXME: is this correct ?? */
+ centry->ofs += sizeof(time_t);
+}
+
+/*
start a centry for output. When finished, call centry_end()
*/
struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status)
@@ -666,6 +755,159 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI
centry_free(centry);
}
+static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_12 *lockout_policy)
+{
+ struct cache_entry *centry;
+
+ centry = centry_start(domain, status);
+ if (!centry)
+ return;
+
+ centry_put_nttime(centry, lockout_policy->duration);
+ centry_put_nttime(centry, lockout_policy->reset_count);
+ centry_put_uint16(centry, lockout_policy->bad_attempt_lockout);
+
+ centry_end(centry, "LOC_POL/%s", domain->name);
+
+ DEBUG(10,("wcache_save_lockout_policy: %s\n", domain->name));
+
+ centry_free(centry);
+}
+
+static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *policy)
+{
+ struct cache_entry *centry;
+
+ centry = centry_start(domain, status);
+ if (!centry)
+ return;
+
+ centry_put_uint16(centry, policy->min_length_password);
+ centry_put_uint16(centry, policy->password_history);
+ centry_put_uint32(centry, policy->password_properties);
+ centry_put_nttime(centry, policy->expire);
+ centry_put_nttime(centry, policy->min_passwordage);
+
+ centry_end(centry, "PWD_POL/%s", domain->name);
+
+ DEBUG(10,("wcache_save_password_policy: %s\n", domain->name));
+
+ centry_free(centry);
+}
+
+NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ TDB_DATA data;
+ fstring key_str;
+ uint32 rid;
+
+ if (!cache->tdb) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ if (is_null_sid(sid)) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ if (!(sid_peek_rid(sid, &rid)) || (rid == 0)) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid));
+
+ data = tdb_fetch(cache->tdb, make_tdb_data(key_str, strlen(key_str)));
+ if (!data.dptr) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/* Lookup creds for a SID */
+NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ const uint8 **cached_nt_pass)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ time_t t;
+ uint32 rid;
+
+ if (!cache->tdb) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ if (is_null_sid(sid)) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ if (!(sid_peek_rid(sid, &rid)) || (rid == 0)) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ 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)));
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ t = centry_time(centry);
+ *cached_nt_pass = (const uint8 *)centry_string(centry, mem_ctx);
+
+#if DEBUG_PASSWORD
+ dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
+#endif
+ status = centry->status;
+
+ DEBUG(10,("wcache_get_creds: [Cached] - cached creds for user %s status %s\n",
+ sid_string_static(sid), get_friendly_nt_error_msg(status) ));
+
+ centry_free(centry);
+ return status;
+}
+
+NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ const uint8 nt_pass[NT_HASH_LEN])
+{
+ struct cache_entry *centry;
+ fstring sid_string;
+ uint32 rid;
+
+ if (is_null_sid(sid)) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ if (!(sid_peek_rid(sid, &rid)) || (rid == 0)) {
+ return NT_STATUS_INVALID_SID;
+ }
+
+ centry = centry_start(domain, NT_STATUS_OK);
+ if (!centry) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+#if DEBUG_PASSWORD
+ dump_data(100, (const char *)nt_pass, NT_HASH_LEN);
+#endif
+
+ centry_put_time(centry, time(NULL));
+ centry_put_string(centry, (const char *)nt_pass);
+ centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid));
+
+ DEBUG(10,("wcache_save_creds: %s\n", sid_string));
+
+ centry_free(centry);
+
+ return NT_STATUS_OK;
+}
+
/* Query display info. This is the basic user list fn */
static NTSTATUS query_user_list(struct winbindd_domain *domain,
@@ -698,8 +940,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
(*info)[i].full_name = centry_string(centry, mem_ctx);
(*info)[i].homedir = centry_string(centry, mem_ctx);
(*info)[i].shell = centry_string(centry, mem_ctx);
- centry_sid(centry, &(*info)[i].user_sid);
- centry_sid(centry, &(*info)[i].group_sid);
+ centry_sid(centry, mem_ctx, &(*info)[i].user_sid);
+ centry_sid(centry, mem_ctx, &(*info)[i].group_sid);
}
do_cached:
@@ -960,8 +1202,10 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
if (!centry)
goto do_query;
*type = (enum SID_NAME_USE)centry_uint32(centry);
- centry_sid(centry, sid);
status = centry->status;
+ if (NT_STATUS_IS_OK(status)) {
+ centry_sid(centry, mem_ctx, sid);
+ }
DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status %s\n",
domain->name, get_friendly_nt_error_msg(status) ));
@@ -989,7 +1233,9 @@ do_query:
status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
/* and save it */
- wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
+ if (domain->online || !is_null_sid(sid)) {
+ wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
+ }
if (NT_STATUS_IS_OK(status)) {
strupper_m(CONST_DISCARD(char *,domain_name));
@@ -1097,8 +1343,8 @@ 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);
- centry_sid(centry, &info->user_sid);
- centry_sid(centry, &info->group_sid);
+ centry_sid(centry, mem_ctx, &info->user_sid);
+ centry_sid(centry, mem_ctx, &info->group_sid);
status = centry->status;
DEBUG(10,("query_user: [Cached] - cached info for domain %s status %s\n",
@@ -1169,7 +1415,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
if (! (*user_gids))
smb_panic("lookup_usergroups out of memory");
for (i=0; i<(*num_groups); i++) {
- centry_sid(centry, &(*user_gids)[i]);
+ centry_sid(centry, mem_ctx, &(*user_gids)[i]);
}
do_cached:
@@ -1251,8 +1497,10 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
(*alias_rids) = TALLOC_ARRAY(mem_ctx, uint32, *num_aliases);
- if ((*num_aliases != 0) && ((*alias_rids) == NULL))
+ if ((*num_aliases != 0) && ((*alias_rids) == NULL)) {
+ centry_free(centry);
return NT_STATUS_NO_MEMORY;
+ }
for (i=0; i<(*num_aliases); i++)
(*alias_rids)[i] = centry_uint32(centry);
@@ -1329,7 +1577,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
}
for (i=0; i<(*num_names); i++) {
- centry_sid(centry, &(*sid_mem)[i]);
+ centry_sid(centry, mem_ctx, &(*sid_mem)[i]);
(*names)[i] = centry_string(centry, mem_ctx);
(*name_types)[i] = centry_uint32(centry);
}
@@ -1388,7 +1636,9 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
return NT_STATUS_OK;
}
-/* enumerate trusted domains */
+/* enumerate trusted domains
+ * (we need to have the list of trustdoms in the cache when we go offline) -
+ * Guenther */
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
@@ -1396,16 +1646,192 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
char ***alt_names,
DOM_SID **dom_sids)
{
- get_cache(domain);
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ int i;
+
+ if (!cache->tdb)
+ goto do_query;
+
+ centry = wcache_fetch(cache, domain, "TRUSTDOMS/%s", domain->name);
+
+ if (!centry) {
+ goto do_query;
+ }
+
+ *num_domains = centry_uint32(centry);
+
+ (*names) = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+ (*alt_names) = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+ (*dom_sids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
+
+ if (! (*dom_sids) || ! (*names) || ! (*alt_names)) {
+ smb_panic("trusted_domains out of memory");
+ }
+
+ for (i=0; i<(*num_domains); i++) {
+ (*names)[i] = centry_string(centry, mem_ctx);
+ (*alt_names)[i] = centry_string(centry, mem_ctx);
+ centry_sid(centry, mem_ctx, &(*dom_sids)[i]);
+ }
+
+ status = centry->status;
+
+ DEBUG(10,("trusted_domains: [Cached] - cached info for domain %s (%d trusts) status %s\n",
+ domain->name, *num_domains, get_friendly_nt_error_msg(status) ));
+
+ centry_free(centry);
+ return status;
+
+do_query:
+ (*num_domains) = 0;
+ (*dom_sids) = NULL;
+ (*names) = NULL;
+ (*alt_names) = NULL;
+
+ /* Return status value returned by seq number check */
+ if (!NT_STATUS_IS_OK(domain->last_status))
+ return domain->last_status;
+
DEBUG(10,("trusted_domains: [Cached] - doing backend query for info for domain %s\n",
domain->name ));
+
+ status = domain->backend->trusted_domains(domain, mem_ctx, num_domains,
+ names, alt_names, dom_sids);
+
+ /* no trusts gives NT_STATUS_NO_MORE_ENTRIES resetting to NT_STATUS_OK
+ * so that the generic centry handling still applies correctly -
+ * Guenther*/
+
+ if (!NT_STATUS_IS_ERR(status)) {
+ status = NT_STATUS_OK;
+ }
+
+ /* and save it */
+ refresh_sequence_number(domain, False);
+
+ centry = centry_start(domain, status);
+ if (!centry)
+ goto skip_save;
+
+ centry_put_uint32(centry, *num_domains);
+
+ for (i=0; i<(*num_domains); i++) {
+ centry_put_string(centry, (*names)[i]);
+ centry_put_string(centry, (*alt_names)[i]);
+ centry_put_sid(centry, &(*dom_sids)[i]);
+ }
+
+ centry_end(centry, "TRUSTDOMS/%s", domain->name);
+
+ centry_free(centry);
+
+skip_save:
+ return status;
+}
+
+/* get lockout policy */
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_12 *policy){
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+
+ if (!cache->tdb)
+ goto do_query;
+
+ centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name);
+
+ if (!centry)
+ goto do_query;
+
+ policy->duration = centry_nttime(centry);
+ policy->reset_count = centry_nttime(centry);
+ policy->bad_attempt_lockout = centry_uint16(centry);
+
+ status = centry->status;
+
+ DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status %s\n",
+ domain->name, get_friendly_nt_error_msg(status) ));
+
+ centry_free(centry);
+ return status;
+
+do_query:
+ ZERO_STRUCTP(policy);
+
+ /* Return status value returned by seq number check */
+
+ if (!NT_STATUS_IS_OK(domain->last_status))
+ return domain->last_status;
+
+ DEBUG(10,("lockout_policy: [Cached] - doing backend query for info for domain %s\n",
+ domain->name ));
+
+ status = domain->backend->lockout_policy(domain, mem_ctx, policy);
+
+ /* and save it */
+ refresh_sequence_number(domain, False);
+ wcache_save_lockout_policy(domain, status, policy);
+
+ return status;
+}
+
+/* get password policy */
+static NTSTATUS password_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_1 *policy)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
- /* we don't cache this call */
- return domain->backend->trusted_domains(domain, mem_ctx, num_domains,
- names, alt_names, dom_sids);
+ if (!cache->tdb)
+ goto do_query;
+
+ centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name);
+
+ if (!centry)
+ goto do_query;
+
+ policy->min_length_password = centry_uint16(centry);
+ policy->password_history = centry_uint16(centry);
+ policy->password_properties = centry_uint32(centry);
+ policy->expire = centry_nttime(centry);
+ policy->min_passwordage = centry_nttime(centry);
+
+ status = centry->status;
+
+ DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status %s\n",
+ domain->name, get_friendly_nt_error_msg(status) ));
+
+ centry_free(centry);
+ return status;
+
+do_query:
+ ZERO_STRUCTP(policy);
+
+ /* Return status value returned by seq number check */
+
+ if (!NT_STATUS_IS_OK(domain->last_status))
+ return domain->last_status;
+
+ DEBUG(10,("password_policy: [Cached] - doing backend query for info for domain %s\n",
+ domain->name ));
+
+ status = domain->backend->password_policy(domain, mem_ctx, policy);
+
+ /* and save it */
+ refresh_sequence_number(domain, False);
+ wcache_save_password_policy(domain, status, policy);
+
+ return status;
}
+
/* Invalidate cached user and group lists coherently */
static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
@@ -1446,22 +1872,6 @@ void wcache_invalidate_cache(void)
}
}
-/* the ADS backend methods are exposed via this structure */
-struct winbindd_methods cache_methods = {
- True,
- query_user_list,
- enum_dom_groups,
- enum_local_groups,
- name_to_sid,
- sid_to_name,
- query_user,
- lookup_usergroups,
- lookup_useraliases,
- lookup_groupmem,
- sequence_number,
- trusted_domains,
-};
-
static BOOL init_wcache(void)
{
if (wcache == NULL) {
@@ -1472,8 +1882,10 @@ static BOOL init_wcache(void)
if (wcache->tdb != NULL)
return True;
- wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
- TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
+ /* when working offline we must not clear the cache on restart */
+ wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+ TDB_DEFAULT /*TDB_CLEAR_IF_FIRST*/, O_RDWR|O_CREAT, 0600);
if (wcache->tdb == NULL) {
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
@@ -1509,7 +1921,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,
+ make_tdb_data(response->extra_data.data,
response->length - sizeof(*response)),
TDB_REPLACE) == 0)
return;
@@ -1546,7 +1958,7 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
SAFE_FREE(data.dptr);
if (response->length == sizeof(*response)) {
- response->extra_data = NULL;
+ response->extra_data.data = NULL;
return True;
}
@@ -1571,10 +1983,27 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
dump_data(11, data.dptr, data.dsize);
- response->extra_data = data.dptr;
+ response->extra_data.data = data.dptr;
return True;
}
+void cache_cleanup_response(pid_t pid)
+{
+ fstring key_str;
+
+ if (!init_wcache())
+ return;
+
+ fstr_sprintf(key_str, "DR/%d", pid);
+ tdb_delete(wcache->tdb, string_tdb_data(key_str));
+
+ fstr_sprintf(key_str, "DE/%d", pid);
+ tdb_delete(wcache->tdb, string_tdb_data(key_str));
+
+ return;
+}
+
+
BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
const char **domain_name, const char **name,
enum SID_NAME_USE *type)
@@ -1611,10 +2040,331 @@ BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
return NT_STATUS_IS_OK(status);
}
-void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
+BOOL lookup_cached_name(TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ const char *name,
+ DOM_SID *sid,
+ enum SID_NAME_USE *type)
+{
+ struct winbindd_domain *domain;
+ struct winbind_cache *cache;
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ fstring uname;
+
+ domain = find_lookup_domain_from_name(domain_name);
+ if (domain == NULL) {
+ return False;
+ }
+
+ cache = get_cache(domain);
+
+ if (cache->tdb == NULL) {
+ return False;
+ }
+
+ fstrcpy(uname, name);
+ strupper_m(uname);
+
+ centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
+ if (centry == NULL) {
+ return False;
+ }
+
+ if (NT_STATUS_IS_OK(centry->status)) {
+ *type = (enum SID_NAME_USE)centry_uint32(centry);
+ centry_sid(centry, mem_ctx, sid);
+ }
+
+ status = centry->status;
+ centry_free(centry);
+
+ return NT_STATUS_IS_OK(status);
+}
+
+void cache_name2sid(struct winbindd_domain *domain,
const char *domain_name, const char *name,
- enum SID_NAME_USE type)
+ enum SID_NAME_USE type, const DOM_SID *sid)
{
- wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name,
- name, type);
+ wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
+ sid, type);
+}
+
+/* delete all centries that don't have NT_STATUS_OK set */
+static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
+ TDB_DATA dbuf, void *state)
+{
+ struct cache_entry *centry;
+ char buf[1024];
+
+ if (!snprintf(buf, kbuf.dsize + 1, "%s", kbuf.dptr)) {
+ return 1;
+ }
+
+ centry = wcache_fetch_raw(buf);
+ if (!centry) {
+ return 0;
+ }
+
+ if (!NT_STATUS_IS_OK(centry->status)) {
+ DEBUG(10,("deleting centry %s\n", buf));
+ tdb_delete(the_tdb, kbuf);
+ }
+
+ centry_free(centry);
+ return 0;
}
+
+/* flush the cache */
+void wcache_flush_cache(void)
+{
+ extern BOOL opt_nocache;
+
+ if (!wcache)
+ return;
+ if (wcache->tdb) {
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
+ }
+ if (opt_nocache)
+ return;
+
+ /* when working offline we must not clear the cache on restart */
+ wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+ TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
+
+ if (!wcache->tdb) {
+ DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
+ }
+
+ tdb_traverse(wcache->tdb, traverse_fn_cleanup, NULL);
+
+ DEBUG(10,("wcache_flush_cache success\n"));
+}
+
+/* Count cached creds */
+
+static int traverse_fn_cached_creds(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *state)
+{
+ int *cred_count = (int*)state;
+
+ if (strncmp(kbuf.dptr, "CRED/", 5) == 0) {
+ (*cred_count)++;
+ }
+ return 0;
+}
+
+NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count)
+{
+ struct winbind_cache *cache = get_cache(domain);
+
+ *count = 0;
+
+ if (!cache->tdb) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ tdb_traverse(cache->tdb, traverse_fn_cached_creds, (void *)count);
+
+ return NT_STATUS_OK;
+}
+
+struct cred_list {
+ struct cred_list *prev, *next;
+ TDB_DATA key;
+ fstring name;
+ time_t created;
+};
+static struct cred_list *wcache_cred_list;
+
+static int traverse_fn_get_credlist(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *state)
+{
+ struct cred_list *cred;
+
+ if (strncmp(kbuf.dptr, "CRED/", 5) == 0) {
+
+ cred = SMB_MALLOC_P(struct cred_list);
+ if (cred == NULL) {
+ DEBUG(0,("traverse_fn_remove_first_creds: failed to malloc new entry for list\n"));
+ return -1;
+ }
+
+ ZERO_STRUCTP(cred);
+
+ /* save a copy of the key */
+
+ fstrcpy(cred->name, kbuf.dptr);
+ DLIST_ADD(wcache_cred_list, cred);
+ }
+
+ return 0;
+}
+
+NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid)
+{
+ struct winbind_cache *cache = get_cache(domain);
+ NTSTATUS status;
+ int ret;
+ struct cred_list *cred, *oldest = NULL;
+
+ if (!cache->tdb) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* we possibly already have an entry */
+ if (sid && NT_STATUS_IS_OK(wcache_cached_creds_exist(domain, sid))) {
+
+ fstring key_str;
+
+ DEBUG(11,("we already have an entry, deleting that\n"));
+
+ fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid));
+
+ tdb_delete(cache->tdb, string_tdb_data(key_str));
+
+ return NT_STATUS_OK;
+ }
+
+ ret = tdb_traverse(cache->tdb, traverse_fn_get_credlist, NULL);
+ if (ret == 0) {
+ return NT_STATUS_OK;
+ } else if (ret == -1) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ ZERO_STRUCTP(oldest);
+
+ for (cred = wcache_cred_list; cred; cred = cred->next) {
+
+ TDB_DATA data;
+ time_t t;
+
+ data = tdb_fetch(cache->tdb, make_tdb_data(cred->name, strlen(cred->name)));
+ if (!data.dptr) {
+ DEBUG(10,("wcache_remove_oldest_cached_creds: entry for [%s] not found\n",
+ cred->name));
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ goto done;
+ }
+
+ t = IVAL(data.dptr, 0);
+ SAFE_FREE(data.dptr);
+
+ if (!oldest) {
+ oldest = SMB_MALLOC_P(struct cred_list);
+ if (oldest == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ fstrcpy(oldest->name, cred->name);
+ oldest->created = t;
+ continue;
+ }
+
+ if (t < oldest->created) {
+ fstrcpy(oldest->name, cred->name);
+ oldest->created = t;
+ }
+ }
+
+ if (tdb_delete(cache->tdb, string_tdb_data(oldest->name)) == 0) {
+ status = NT_STATUS_OK;
+ } else {
+ status = NT_STATUS_UNSUCCESSFUL;
+ }
+done:
+ SAFE_FREE(wcache_cred_list);
+ SAFE_FREE(oldest);
+
+ return status;
+}
+
+/* Change the global online/offline state. */
+BOOL set_global_winbindd_state_offline(void)
+{
+ TDB_DATA data;
+ int err;
+
+ DEBUG(10,("set_global_winbindd_state_offline: offline requested.\n"));
+
+ /* Only go offline if someone has created
+ the key "WINBINDD_OFFLINE" in the cache tdb. */
+
+ if (wcache == NULL || wcache->tdb == NULL) {
+ DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n"));
+ return False;
+ }
+
+ if (!lp_winbind_offline_logon()) {
+ DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n"));
+ return False;
+ }
+
+ if (global_winbindd_offline_state) {
+ /* Already offline. */
+ 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) {
+ DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n"));
+ return False;
+ } else {
+ DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n"));
+ global_winbindd_offline_state = True;
+ return True;
+ }
+}
+
+void set_global_winbindd_state_online(void)
+{
+ DEBUG(10,("set_global_winbindd_state_online: online requested.\n"));
+
+ if (!lp_winbind_offline_logon()) {
+ DEBUG(10,("set_global_winbindd_state_online: rejecting.\n"));
+ return;
+ }
+
+ if (!global_winbindd_offline_state) {
+ /* Already online. */
+ return;
+ }
+ global_winbindd_offline_state = False;
+
+ if (!wcache->tdb) {
+ return;
+ }
+
+ /* Ensure there is no key "WINBINDD_OFFLINE" in the cache tdb. */
+ tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE");
+}
+
+/* the cache backend methods are exposed via this structure */
+struct winbindd_methods cache_methods = {
+ True,
+ query_user_list,
+ enum_dom_groups,
+ enum_local_groups,
+ name_to_sid,
+ sid_to_name,
+ query_user,
+ lookup_usergroups,
+ lookup_useraliases,
+ lookup_groupmem,
+ sequence_number,
+ lockout_policy,
+ password_policy,
+ trusted_domains
+};
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index acca6fcb938..9e450d9de74 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -358,6 +358,10 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
session_setup_done:
+ /* cache the server name for later connections */
+
+ saf_store( domain->name, (*cli)->desthost );
+
if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {
result = cli_nt_error(*cli);
@@ -577,6 +581,10 @@ static BOOL receive_getdc_response(struct in_addr dc_ip,
static void dcip_to_name( const char *domainname, const char *realm,
const DOM_SID *sid, struct in_addr ip, fstring name )
{
+ struct ip_service ip_list;
+
+ ip_list.ip = ip;
+ ip_list.port = 0;
/* try GETDC requests first */
@@ -584,16 +592,20 @@ static void dcip_to_name( const char *domainname, const char *realm,
int i;
smb_msleep(100);
for (i=0; i<5; i++) {
- if (receive_getdc_response(ip, domainname, name))
+ if (receive_getdc_response(ip, domainname, name)) {
+ namecache_store(name, 0x20, 1, &ip_list);
return;
+ }
smb_msleep(500);
}
}
/* try node status request */
- if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
+ if ( name_status_find(domainname, 0x1c, 0x20, ip, name) ) {
+ namecache_store(name, 0x20, 1, &ip_list);
return;
+ }
/* backup in case the netbios stuff fails */
@@ -623,6 +635,7 @@ static void dcip_to_name( const char *domainname, const char *realm,
}
fstrcpy(name, ads->config.ldap_server_name);
+ namecache_store(name, 0x20, 1, &ip_list);
ads_destroy( &ads );
}
@@ -658,14 +671,6 @@ static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
return True;
}
- if ( is_our_domain
- && must_use_pdc(domain->name)
- && get_pdc_ip(domain->name, &ip))
- {
- if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
- return True;
- }
-
/* try standard netbios queries first */
get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
@@ -752,12 +757,35 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
{
TALLOC_CTX *mem_ctx;
NTSTATUS result;
-
+ char *saf_servername = saf_fetch( domain->name );
int retries;
if ((mem_ctx = talloc_init("cm_open_connection")) == NULL)
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 )
+ {
+ /* convert an ip address to a name */
+ if ( is_ipaddress( saf_servername ) )
+ {
+ fstring saf_name;
+ struct in_addr ip;
+
+ ip = *interpret_addr2( saf_servername );
+ dcip_to_name( domain->name, domain->alt_name, &domain->sid, ip, saf_name );
+ fstrcpy( domain->dcname, saf_name );
+ }
+ else
+ {
+ fstrcpy( domain->dcname, saf_servername );
+ }
+
+ SAFE_FREE( saf_servername );
+ }
+
for (retries = 0; retries < 3; retries++) {
int fd = -1;
@@ -765,27 +793,34 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- if ((strlen(domain->dcname) > 0) &&
- NT_STATUS_IS_OK(check_negative_conn_cache(
- domain->name, domain->dcname)) &&
- (resolve_name(domain->dcname, &domain->dcaddr.sin_addr,
- 0x20))) {
- int dummy;
- struct sockaddr_in addrs[2];
- addrs[0] = domain->dcaddr;
- addrs[0].sin_port = htons(445);
- addrs[1] = domain->dcaddr;
- addrs[1].sin_port = htons(139);
- if (!open_any_socket_out(addrs, 2, 10000,
- &dummy, &fd)) {
+ if ((strlen(domain->dcname) > 0)
+ && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
+ && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
+ {
+ struct sockaddr_in *addrs = NULL;
+ 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 (!open_any_socket_out(addrs, num_addrs, 10000, &dummy, &fd)) {
+ domain->online = False;
fd = -1;
}
}
- if ((fd == -1) &&
- !find_new_dc(mem_ctx, domain, domain->dcname,
- &domain->dcaddr, &fd))
+ if ((fd == -1)
+ && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
+ {
+ /* This is the one place where we will
+ set the global winbindd offline state
+ to true, if a "WINBINDD_OFFLINE" entry
+ is found in the winbindd cache. */
+ set_global_winbindd_state_offline();
+ domain->online = False;
break;
+ }
new_conn->cli = NULL;
@@ -796,11 +831,19 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
break;
}
+ if (NT_STATUS_IS_OK(result)) {
+ if (domain->online == False) {
+ /* We're changing state from offline to online. */
+ set_global_winbindd_state_online();
+ }
+ domain->online = True;
+ }
+
talloc_destroy(mem_ctx);
return result;
}
-/* Return true if a connection is still alive */
+/* Close down all open pipes on a connection. */
void invalidate_cm_connection(struct winbindd_cm_conn *conn)
{
@@ -1239,7 +1282,7 @@ 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)) {
- DEBUG(10, ("cm_connect_sam: Could not get schannel auth info "
+ DEBUG(10, ("cm_connect_lsa: Could not get schannel auth info "
"for domain %s, trying anon\n", conn->cli->domain));
goto anonymous;
}
@@ -1404,7 +1447,9 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
if (conn->netlogon_pipe == NULL) {
DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error "
"was %s\n", nt_errstr(result)));
- return result;
+
+ /* make sure we return something besides OK */
+ return !NT_STATUS_IS_OK(result) ? result : NT_STATUS_PIPE_NOT_AVAILABLE;
}
*cli = conn->netlogon_pipe;
diff --git a/source/nsswitch/winbindd_cred_cache.c b/source/nsswitch/winbindd_cred_cache.c
new file mode 100644
index 00000000000..4c539b9b23a
--- /dev/null
+++ b/source/nsswitch/winbindd_cred_cache.c
@@ -0,0 +1,268 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Winbind daemon - krb5 credential cache funcions
+
+ 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"
+#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+#define MAX_CCACHES 100
+
+static struct WINBINDD_CCACHE_ENTRY *ccache_list;
+
+static TALLOC_CTX *mem_ctx;
+
+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)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry;
+
+ for (entry = ccache_list; entry; entry = entry->next) {
+ if (strequal(entry->username, username)) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+static int ccache_entry_count(void)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry;
+ int i = 0;
+
+ for (entry = ccache_list; entry; entry = entry->next) {
+ i++;
+ }
+ return i;
+}
+
+NTSTATUS remove_ccache_by_ccname(const char *ccname)
+{
+ struct WINBINDD_CCACHE_ENTRY *entry;
+
+ for (entry = ccache_list; entry; entry = entry->next) {
+ if (strequal(entry->ccname, ccname)) {
+ DLIST_REMOVE(ccache_list, entry);
+ TALLOC_FREE(entry->event); /* unregisters events */
+ TALLOC_FREE(entry);
+ return NT_STATUS_OK;
+ }
+ }
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+static void krb5_ticket_refresh_handler(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);
+ int ret;
+ time_t new_start;
+ struct timeval t;
+
+
+ DEBUG(10,("krb5_ticket_refresh_handler called\n"));
+ DEBUGADD(10,("event called for: %s, %s\n", entry->ccname, entry->username));
+
+ TALLOC_FREE(entry->event);
+
+#ifdef HAVE_KRB5
+
+ /* 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)) {
+
+ seteuid(entry->uid);
+
+ ret = kerberos_kinit_password_ext(entry->principal_name,
+ entry->pass,
+ 0, /* hm, can we do time correction here ? */
+ &entry->refresh_time,
+ &entry->renew_until,
+ entry->ccname,
+ False, /* no PAC required anymore */
+ WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
+ seteuid(0);
+
+ if (ret) {
+ DEBUG(3,("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",
+ entry->principal_name, entry->ccname));
+
+ new_start = entry->refresh_time;
+
+ goto done;
+ }
+
+ seteuid(entry->uid);
+
+ ret = smb_krb5_renew_ticket(entry->ccname,
+ entry->principal_name,
+ entry->service,
+ &new_start);
+ seteuid(0);
+
+ if (ret) {
+ DEBUG(3,("could not renew tickets: %s\n", error_message(ret)));
+ /* maybe we are beyond the renewing window */
+ return;
+ }
+
+done:
+
+ t = timeval_set(new_start, 0);
+
+ entry->event = add_timed_event(mem_ctx,
+ t,
+ "krb5_ticket_refresh_handler",
+ krb5_ticket_refresh_handler,
+ entry);
+
+#endif
+}
+
+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,
+ uid_t uid,
+ time_t create_time,
+ time_t ticket_end,
+ time_t renew_until,
+ BOOL schedule_refresh_event)
+{
+ struct WINBINDD_CCACHE_ENTRY *new_entry = NULL;
+ NTSTATUS status;
+
+ if ((username == NULL && sid_string == NULL && princ_name == NULL) ||
+ ccname == NULL) {
+ 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;
+ }
+
+ new_entry = TALLOC_P(mem_ctx, struct WINBINDD_CCACHE_ENTRY);
+ if (new_entry == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCTP(new_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);
+ }
+ if (princ_name) {
+ new_entry->principal_name = talloc_strdup(mem_ctx, princ_name);
+ NT_STATUS_HAVE_NO_MEMORY(new_entry->principal_name);
+ }
+ if (service) {
+ new_entry->service = talloc_strdup(mem_ctx, service);
+ NT_STATUS_HAVE_NO_MEMORY(new_entry->service);
+ }
+ if (pass) {
+ new_entry->pass = talloc_strdup(mem_ctx, pass);
+ NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
+ }
+
+ 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;
+ }
+ new_entry->uid = uid;
+
+
+ if (schedule_refresh_event && renew_until > 0) {
+
+ struct timeval t = timeval_set((ticket_end -1 ), 0);
+
+ new_entry->event = add_timed_event(mem_ctx,
+ t,
+ "krb5_ticket_refresh_handler",
+ krb5_ticket_refresh_handler,
+ new_entry);
+ }
+
+ DLIST_ADD(ccache_list, new_entry);
+
+ DEBUG(10,("add_ccache_to_list: added ccache [%s] for user [%s] to the list\n", ccname, username));
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS destroy_ccache_list(void)
+{
+ return talloc_destroy(mem_ctx) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS init_ccache_list(void)
+{
+ if (ccache_list) {
+ return NT_STATUS_OK;
+ }
+
+ mem_ctx = talloc_init("winbindd_ccache_krb5_handling");
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCTP(ccache_list);
+
+ return NT_STATUS_OK;
+}
diff --git a/source/nsswitch/winbindd_creds.c b/source/nsswitch/winbindd_creds.c
new file mode 100644
index 00000000000..414dd24af9e
--- /dev/null
+++ b/source/nsswitch/winbindd_creds.c
@@ -0,0 +1,164 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Winbind daemon - cached credentials funcions
+
+ 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"
+#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+#define MAX_CACHED_LOGINS 10
+
+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])
+{
+ NET_USER_INFO_3 *info;
+ NTSTATUS status;
+
+ status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ info = netsamlogon_cache_get(mem_ctx, sid);
+ if (info == NULL) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ *info3 = info;
+
+ return NT_STATUS_OK;
+}
+
+
+NTSTATUS winbindd_store_creds(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user,
+ const char *pass,
+ NET_USER_INFO_3 *info3,
+ const DOM_SID *user_sid)
+{
+ NTSTATUS status;
+ uchar nt_pass[NT_HASH_LEN];
+ DOM_SID cred_sid;
+
+ if (info3 != NULL) {
+
+ DOM_SID sid;
+ sid_copy(&sid, &(info3->dom_sid.sid));
+ sid_append_rid(&sid, info3->user_rid);
+ sid_copy(&cred_sid, &sid);
+ info3->user_flgs |= LOGON_CACHED_ACCOUNT;
+
+ } else if (user_sid != NULL) {
+
+ sid_copy(&cred_sid, user_sid);
+
+ } else if (user != NULL) {
+
+ /* do lookup ourself */
+
+ enum SID_NAME_USE type;
+
+ if (!lookup_cached_name(mem_ctx,
+ domain->name,
+ user,
+ &cred_sid,
+ &type)) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+ } else {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (pass) {
+
+ int count = 0;
+
+ status = wcache_count_cached_creds(domain, &count);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ DEBUG(11,("we have %d cached creds\n", count));
+
+ if (count + 1 > MAX_CACHED_LOGINS) {
+
+ DEBUG(10,("need to delete the oldest cached login\n"));
+
+ status = wcache_remove_oldest_cached_creds(domain, &cred_sid);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("failed to remove oldest cached cred: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+ }
+
+ E_md4hash(pass, nt_pass);
+
+#if DEBUG_PASSWORD
+ dump_data(100, (const char *)nt_pass, NT_HASH_LEN);
+#endif
+
+ status = wcache_save_creds(domain, mem_ctx, &cred_sid, nt_pass);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ if (info3 != NULL && user != NULL) {
+ if (!netsamlogon_cache_store(user, info3)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS winbindd_update_creds_by_info3(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user,
+ const char *pass,
+ NET_USER_INFO_3 *info3)
+{
+ return winbindd_store_creds(domain, mem_ctx, user, pass, info3, NULL);
+}
+
+NTSTATUS winbindd_update_creds_by_sid(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ const char *pass)
+{
+ return winbindd_store_creds(domain, mem_ctx, NULL, pass, NULL, sid);
+}
+
+NTSTATUS winbindd_update_creds_by_name(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user,
+ const char *pass)
+{
+ return winbindd_store_creds(domain, mem_ctx, user, pass, NULL, NULL);
+}
+
+
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index 38030ee9ac8..c5d24f98c1b 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -52,25 +52,25 @@ static void child_read_request(struct winbindd_cli_state *state)
}
if (state->request.extra_len == 0) {
- state->request.extra_data = NULL;
+ state->request.extra_data.data = NULL;
return;
}
DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len));
- state->request.extra_data =
+ state->request.extra_data.data =
SMB_MALLOC_ARRAY(char, state->request.extra_len + 1);
- if (state->request.extra_data == NULL) {
+ if (state->request.extra_data.data == NULL) {
DEBUG(0, ("malloc failed\n"));
state->finished = True;
return;
}
/* Ensure null termination */
- state->request.extra_data[state->request.extra_len] = '\0';
+ state->request.extra_data.data[state->request.extra_len] = '\0';
- len = read_data(state->sock, state->request.extra_data,
+ len = read_data(state->sock, state->request.extra_data.data,
state->request.extra_len);
if (len != state->request.extra_len) {
@@ -153,7 +153,7 @@ static void async_main_request_sent(void *private_data, BOOL success)
return;
}
- setup_async_write(&state->child->event, state->request->extra_data,
+ setup_async_write(&state->child->event, state->request->extra_data.data,
state->request->extra_len,
async_request_sent, state);
}
@@ -197,6 +197,8 @@ static void async_reply_recv(void *private_data, BOOL success)
SMB_ASSERT(cache_retrieve_response(child->pid,
state->response));
+ cache_cleanup_response(child->pid);
+
DLIST_REMOVE(child->requests, state);
schedule_async_request(child);
@@ -233,6 +235,8 @@ static void schedule_async_request(struct winbindd_child *child)
setup_async_write(&child->event, request->request,
sizeof(*request->request),
async_main_request_sent, request);
+
+ talloc_destroy(child->mem_ctx);
return;
}
@@ -347,6 +351,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
{ WINBINDD_SHOW_SEQUENCE, winbindd_dual_show_sequence, "SHOW_SEQUENCE" },
{ 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_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" },
@@ -356,8 +361,8 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
{ WINBINDD_DUAL_NAME2GID, winbindd_dual_name2gid, "DUAL_NAME2GID" },
{ WINBINDD_DUAL_IDMAPSET, winbindd_dual_idmapset, "DUAL_IDMAPSET" },
{ WINBINDD_DUAL_USERINFO, winbindd_dual_userinfo, "DUAL_USERINFO" },
- { WINBINDD_ALLOCATE_RID, winbindd_dual_allocate_rid, "ALLOCATE_RID" },
- { WINBINDD_ALLOCATE_RID_AND_GID, winbindd_dual_allocate_rid_and_gid, "ALLOCATE_RID_AND_GID" },
+ { 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" },
/* End of list */
@@ -444,6 +449,139 @@ 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)
+{
+ struct winbindd_child *child;
+
+ DEBUG(10,("winbind_msg_offline: got offline message.\n"));
+
+ if (!lp_winbind_offline_logon()) {
+ DEBUG(10,("winbind_msg_offline: rejecting offline message.\n"));
+ return;
+ }
+
+ /* Set our global state as offline. */
+ if (!set_global_winbindd_state_offline()) {
+ DEBUG(10,("winbind_msg_offline: offline request failed.\n"));
+ return;
+ }
+
+ 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);
+ }
+}
+
+/* Forward the online/offline messages to our children. */
+void winbind_msg_online(int msg_type, struct process_id src, void *buf, size_t len)
+{
+ struct winbindd_child *child;
+
+ DEBUG(10,("winbind_msg_online: got online message.\n"));
+
+ if (!lp_winbind_offline_logon()) {
+ DEBUG(10,("winbind_msg_online: rejecting online message.\n"));
+ return;
+ }
+
+ /* Set our global state as online. */
+ set_global_winbindd_state_online();
+
+ 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);
+ }
+}
+
+static void account_lockout_policy_handler(struct timed_event *te,
+ const struct timeval *now,
+ void *private_data)
+{
+ struct winbindd_child *child = private_data;
+
+ struct winbindd_methods *methods;
+ SAM_UNK_INFO_12 lockout_policy;
+ NTSTATUS result;
+
+ DEBUG(10,("account_lockout_policy_handler called\n"));
+
+ if (child->lockout_policy_event) {
+ TALLOC_FREE(child->lockout_policy_event);
+ }
+
+ methods = child->domain->methods;
+
+ result = methods->lockout_policy(child->domain, child->mem_ctx, &lockout_policy);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("account_lockout_policy_handler: failed to call lockout_policy\n"));
+ return;
+ }
+
+ child->lockout_policy_event = add_timed_event(child->mem_ctx,
+ timeval_current_ofs(3600, 0),
+ "account_lockout_policy_handler",
+ account_lockout_policy_handler,
+ child);
+}
+
+/* Deal with a request to go offline. */
+
+static void child_msg_offline(int msg_type, struct process_id src, void *buf, size_t len)
+{
+ struct winbindd_domain *domain;
+
+ DEBUG(5,("child_msg_offline received.\n"));
+
+ if (!lp_winbind_offline_logon()) {
+ DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
+ return;
+ }
+
+ /* Set our global state as offline. */
+ if (!set_global_winbindd_state_offline()) {
+ DEBUG(10,("child_msg_offline: offline request failed.\n"));
+ return;
+ }
+
+ /* Mark all our domains as offline. */
+
+ for (domain = domain_list(); domain; domain = domain->next) {
+ DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
+ domain->online = False;
+ }
+}
+
+/* Deal with a request to go online. */
+
+static void child_msg_online(int msg_type, struct process_id src, void *buf, size_t len)
+{
+ struct winbindd_domain *domain;
+
+ DEBUG(5,("child_msg_online received.\n"));
+
+ if (!lp_winbind_offline_logon()) {
+ DEBUG(10,("child_msg_online: rejecting online message.\n"));
+ return;
+ }
+
+ /* Set our global state as online. */
+ set_global_winbindd_state_online();
+
+ winbindd_flush_nscd_cache();
+
+ /* Mark everything online - delete any negative cache entries
+ to force an immediate reconnect. */
+
+ 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);
+ }
+}
+
static BOOL fork_domain_child(struct winbindd_child *child)
{
int fdpair[2];
@@ -459,10 +597,15 @@ static BOOL fork_domain_child(struct winbindd_child *child)
ZERO_STRUCT(state);
state.pid = getpid();
+ /* Ensure we don't process messages whilst we're
+ changing the disposition for the child. */
+ message_block();
+
child->pid = sys_fork();
if (child->pid == -1) {
DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
+ message_unblock();
return False;
}
@@ -475,6 +618,8 @@ static BOOL fork_domain_child(struct winbindd_child *child)
child->event.flags = 0;
child->requests = NULL;
add_fd_event(&child->event);
+ /* We're ok with online/offline messages now. */
+ message_unblock();
return True;
}
@@ -484,7 +629,7 @@ static BOOL fork_domain_child(struct winbindd_child *child)
close(fdpair[1]);
/* tdb needs special fork handling */
- if (tdb_reopen_all() == -1) {
+ if (tdb_reopen_all(1) == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
_exit(0);
}
@@ -495,11 +640,80 @@ static BOOL fork_domain_child(struct winbindd_child *child)
lp_set_logfile(child->logfilename);
reopen_logs();
}
-
+
+ /* Don't handle the same messages as our parent. */
+ message_deregister(MSG_SMB_CONF_UPDATED);
+ message_deregister(MSG_SHUTDOWN);
+ message_deregister(MSG_WINBIND_OFFLINE);
+ message_deregister(MSG_WINBIND_ONLINE);
+
+ /* 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;
+ }
+
+ if (child->domain != NULL) {
+ /* We might be in the idmap child...*/
+ child->lockout_policy_event = add_timed_event(
+ child->mem_ctx, 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);
+
while (1) {
+
+ int ret;
+ fd_set read_fds;
+ struct timeval t;
+ struct timeval *tp;
+ struct timeval now;
+
/* free up any talloc memory */
- lp_talloc_free();
- main_loop_talloc_free();
+ lp_TALLOC_FREE();
+ main_loop_TALLOC_FREE();
+
+ run_events();
+
+ GetTimeOfDay(&now);
+
+ tp = get_timed_events_timeout(&t);
+ if (tp) {
+ DEBUG(11,("select will use timeout of %u.%u seconds\n",
+ (unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
+ }
+
+ /* Handle messages */
+
+ message_dispatch();
+
+ FD_ZERO(&read_fds);
+ FD_SET(state.sock, &read_fds);
+
+ ret = sys_select(state.sock + 1, &read_fds, NULL, NULL, tp);
+
+ if (ret == 0) {
+ DEBUG(11,("nothing is ready yet, continue\n"));
+ continue;
+ }
+
+ if (ret == -1 && errno == EINTR) {
+ /* We got a signal - continue. */
+ continue;
+ }
+
+ if (ret == -1 && errno != EINTR) {
+ DEBUG(0,("select error occured\n"));
+ perror("select");
+ return False;
+ }
/* fetch a request from the main daemon */
child_read_request(&state);
@@ -515,11 +729,11 @@ static BOOL fork_domain_child(struct winbindd_child *child)
state.request.null_term = '\0';
child_process_request(child->domain, &state);
- SAFE_FREE(state.request.extra_data);
+ SAFE_FREE(state.request.extra_data.data);
cache_store_response(sys_getpid(), &state.response);
- SAFE_FREE(state.response.extra_data);
+ SAFE_FREE(state.response.extra_data.data);
/* We just send the result code back, the result
* structure needs to be fetched via the
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index ff2d19f5fc8..7219292724b 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -41,8 +41,8 @@ static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name,
const char *gr_name, gid_t unix_gid)
{
fstring full_group_name;
- /* Fill in uid/gid */
- fill_domain_username(full_group_name, dom_name, gr_name);
+
+ fill_domain_username( full_group_name, dom_name, gr_name, False);
gr->gr_gid = unix_gid;
@@ -140,13 +140,13 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
/* make sure to allow machine accounts */
if (name_types[i] != SID_NAME_USER && name_types[i] != SID_NAME_COMPUTER) {
- DEBUG(3, ("name %s isn't a domain user\n", the_name));
+ DEBUG(3, ("name %s isn't a domain user (%s)\n", the_name, sid_type_lookup(name_types[i])));
continue;
}
/* Append domain name */
- fill_domain_username(name, domain->name, the_name);
+ fill_domain_username(name, domain->name, the_name, False);
len = strlen(name);
@@ -201,13 +201,17 @@ done:
void winbindd_getgrnam(struct winbindd_cli_state *state)
{
- DOM_SID group_sid;
+ DOM_SID group_sid, tmp_sid;
+ uint32 grp_rid;
struct winbindd_domain *domain;
enum SID_NAME_USE name_type;
fstring name_domain, name_group;
char *tmp, *gr_mem;
size_t gr_mem_len;
+ size_t num_gr_mem;
gid_t gid;
+ union unid_t id;
+ NTSTATUS status;
/* Ensure null termination */
state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0';
@@ -241,8 +245,8 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
/* should we deal with users for our domain? */
if ( lp_winbind_trusted_domains_only() && domain->primary) {
- DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n",
- name_domain, name_group));
+ DEBUG(7,("winbindd_getgrnam: My domain -- rejecting "
+ "getgrnam() for %s\\%s.\n", name_domain, name_group));
request_error(state);
return;
}
@@ -262,33 +266,66 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
((name_type==SID_NAME_ALIAS) && domain->internal) ||
((name_type==SID_NAME_WKN_GRP) && domain->internal)) )
{
- DEBUG(1, ("name '%s' is not a local, domain or builtin group: %d\n",
- name_group, name_type));
+ DEBUG(1, ("name '%s' is not a local, domain or builtin "
+ "group: %d\n", name_group, name_type));
request_error(state);
return;
}
- if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid, 0))) {
- DEBUG(1, ("error converting unix gid to sid\n"));
+ /* Make sure that the group SID is within the domain of the
+ original domain */
+
+ sid_copy( &tmp_sid, &group_sid );
+ sid_split_rid( &tmp_sid, &grp_rid );
+ if ( !sid_equal( &tmp_sid, &domain->sid ) ) {
+ DEBUG(3,("winbindd_getgrnam: group %s resolves to a SID in the wrong domain [%s]\n",
+ state->request.data.groupname, sid_string_static(&group_sid)));
request_error(state);
return;
}
+
+
+ /* Try to get the GID */
+
+ status = idmap_sid_to_gid(&group_sid, &gid, 0);
+
+ if (NT_STATUS_IS_OK(status)) {
+ goto got_gid;
+ }
+
+ /* Maybe it's one of our aliases in passdb */
+
+ if (pdb_sid_to_id(&group_sid, &id, &name_type) &&
+ ((name_type == SID_NAME_ALIAS) ||
+ (name_type == SID_NAME_WKN_GRP))) {
+ gid = id.gid;
+ goto got_gid;
+ }
+
+ DEBUG(1, ("error converting unix gid to sid\n"));
+ request_error(state);
+ return;
+
+ got_gid:
+
if (!fill_grent(&state->response.data.gr, name_domain,
name_group, gid) ||
!fill_grent_mem(domain, &group_sid, name_type,
- &state->response.data.gr.num_gr_mem,
+ &num_gr_mem,
&gr_mem, &gr_mem_len)) {
request_error(state);
return;
}
+ state->response.data.gr.num_gr_mem = (uint32)num_gr_mem;
+
/* Group membership lives at start of extra data */
state->response.data.gr.gr_mem_ofs = 0;
state->response.length += gr_mem_len;
- state->response.extra_data = gr_mem;
+ state->response.extra_data.data = gr_mem;
request_ok(state);
}
@@ -302,7 +339,9 @@ void winbindd_getgrgid(struct winbindd_cli_state *state)
fstring dom_name;
fstring group_name;
size_t gr_mem_len;
+ size_t num_gr_mem;
char *gr_mem;
+ NTSTATUS status;
DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid,
(unsigned long)state->request.data.gid));
@@ -315,14 +354,29 @@ void winbindd_getgrgid(struct winbindd_cli_state *state)
return;
}
- /* Get rid from gid */
- if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid, 0))) {
- DEBUG(1, ("could not convert gid %lu to rid\n",
- (unsigned long)state->request.data.gid));
- request_error(state);
- return;
+ /* Get sid from gid */
+
+ status = idmap_gid_to_sid(&group_sid, state->request.data.gid, 0);
+ if (NT_STATUS_IS_OK(status)) {
+ /* This is a remote one */
+ goto got_sid;
}
+ /* Ok, this might be "ours", i.e. an alias */
+
+ if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
+ lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
+ (name_type == SID_NAME_ALIAS)) {
+ /* Hey, got an alias */
+ goto got_sid;
+ }
+
+ DEBUG(1, ("could not convert gid %lu to sid\n",
+ (unsigned long)state->request.data.gid));
+ request_error(state);
+ return;
+
+ got_sid:
/* Get name from sid */
if (!winbindd_lookup_name_by_sid(state->mem_ctx, &group_sid, dom_name,
@@ -355,18 +409,20 @@ void winbindd_getgrgid(struct winbindd_cli_state *state)
if (!fill_grent(&state->response.data.gr, dom_name, group_name,
state->request.data.gid) ||
!fill_grent_mem(domain, &group_sid, name_type,
- &state->response.data.gr.num_gr_mem,
+ &num_gr_mem,
&gr_mem, &gr_mem_len)) {
request_error(state);
return;
}
+ state->response.data.gr.num_gr_mem = (uint32)num_gr_mem;
+
/* Group membership lives at start of extra data */
state->response.data.gr.gr_mem_ofs = 0;
state->response.length += gr_mem_len;
- state->response.extra_data = gr_mem;
+ state->response.extra_data.data = gr_mem;
request_ok(state);
}
@@ -459,7 +515,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
{
NTSTATUS status;
uint32 num_entries;
- struct acct_info *name_list = NULL, *tmp_name_list = NULL;
+ struct acct_info *name_list = NULL;
TALLOC_CTX *mem_ctx;
BOOL result = False;
struct acct_info *sam_grp_entries = NULL;
@@ -534,17 +590,14 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
/* Copy entries into return buffer */
if ( num_entries ) {
- if ( !(tmp_name_list = SMB_REALLOC_ARRAY( name_list, struct acct_info, ent->num_sam_entries+num_entries)) )
+ if ( !(name_list = SMB_REALLOC_ARRAY( name_list, struct acct_info, ent->num_sam_entries+num_entries)) )
{
DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n",
num_entries));
result = False;
- SAFE_FREE( name_list );
goto done;
}
- name_list = tmp_name_list;
-
memcpy( &name_list[ent->num_sam_entries], sam_grp_entries,
num_entries * sizeof(struct acct_info) );
}
@@ -575,7 +628,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
struct getent_state *ent;
struct winbindd_gr *group_list = NULL;
int num_groups, group_list_ndx = 0, i, gr_mem_list_len = 0;
- char *new_extra_data, *gr_mem_list = NULL;
+ char *gr_mem_list = NULL;
DEBUG(3, ("[%5lu]: getgrent\n", (unsigned long)state->pid));
@@ -588,17 +641,17 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries);
- if ((state->response.extra_data = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups)) == NULL) {
+ if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_gr, num_groups)) == NULL) {
request_error(state);
return;
}
- memset(state->response.extra_data, '\0',
+ memset(state->response.extra_data.data, '\0',
num_groups * sizeof(struct winbindd_gr) );
state->response.data.num_entries = 0;
- group_list = (struct winbindd_gr *)state->response.extra_data;
+ group_list = (struct winbindd_gr *)state->response.extra_data.data;
if (!state->getgrent_initialized)
winbindd_setgrent_internal(state);
@@ -616,7 +669,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
uint32 result;
gid_t group_gid;
size_t gr_mem_len;
- char *gr_mem, *new_gr_mem_list;
+ char *gr_mem;
DOM_SID group_sid;
struct winbindd_domain *domain;
@@ -665,13 +718,32 @@ 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))) {
-
- DEBUG(1, ("could not look up gid for group %s\n",
- name_list[ent->sam_entry_index].acct_name));
-
- ent->sam_entry_index++;
- goto tryagain;
+ if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid,
+ &group_gid, 0))) {
+ union unid_t id;
+ enum SID_NAME_USE type;
+
+ DEBUG(10, ("SID %s not in idmap\n",
+ sid_string_static(&group_sid)));
+
+ if (!pdb_sid_to_id(&group_sid, &id, &type)) {
+ DEBUG(1, ("could not look up gid for group "
+ "%s\n",
+ name_list[ent->sam_entry_index].acct_name));
+ ent->sam_entry_index++;
+ goto tryagain;
+ }
+
+ if ((type != SID_NAME_DOM_GRP) &&
+ (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP)) {
+ DEBUG(1, ("Group %s is a %s, not a group\n",
+ sid_type_lookup(type),
+ name_list[ent->sam_entry_index].acct_name));
+ ent->sam_entry_index++;
+ goto tryagain;
+ }
+ group_gid = id.gid;
}
DEBUG(10, ("got gid %lu for group %lu\n", (unsigned long)group_gid,
@@ -680,7 +752,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group entry */
fill_domain_username(domain_group_name, ent->domain_name,
- name_list[ent->sam_entry_index].acct_name);
+ name_list[ent->sam_entry_index].acct_name, False);
result = fill_grent(&group_list[group_list_ndx],
ent->domain_name,
@@ -690,6 +762,7 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
/* Fill in group membership entry */
if (result) {
+ size_t num_gr_mem = 0;
DOM_SID member_sid;
group_list[group_list_ndx].num_gr_mem = 0;
gr_mem = NULL;
@@ -705,18 +778,19 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
domain,
&member_sid,
SID_NAME_DOM_GRP,
- &group_list[group_list_ndx].num_gr_mem,
+ &num_gr_mem,
&gr_mem, &gr_mem_len);
+
+ group_list[group_list_ndx].num_gr_mem = (uint32)num_gr_mem;
}
}
if (result) {
/* Append to group membership list */
- new_gr_mem_list = SMB_REALLOC( gr_mem_list, gr_mem_list_len + gr_mem_len);
+ gr_mem_list = SMB_REALLOC( gr_mem_list, gr_mem_list_len + gr_mem_len);
- if (!new_gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) {
+ if (!gr_mem_list) {
DEBUG(0, ("out of memory\n"));
- SAFE_FREE(gr_mem_list);
gr_mem_list_len = 0;
break;
}
@@ -724,8 +798,6 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
DEBUG(10, ("list_len = %d, mem_len = %d\n",
gr_mem_list_len, gr_mem_len));
- gr_mem_list = new_gr_mem_list;
-
memcpy(&gr_mem_list[gr_mem_list_len], gr_mem,
gr_mem_len);
@@ -763,27 +835,22 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
if (group_list_ndx == 0)
goto done;
- new_extra_data = SMB_REALLOC(
- state->response.extra_data,
+ state->response.extra_data.data = SMB_REALLOC(
+ state->response.extra_data.data,
group_list_ndx * sizeof(struct winbindd_gr) + gr_mem_list_len);
- if (!new_extra_data) {
+ if (!state->response.extra_data.data) {
DEBUG(0, ("out of memory\n"));
group_list_ndx = 0;
- SAFE_FREE(state->response.extra_data);
SAFE_FREE(gr_mem_list);
request_error(state);
return;
}
- state->response.extra_data = new_extra_data;
-
- memcpy(&((char *)state->response.extra_data)
+ memcpy(&((char *)state->response.extra_data.data)
[group_list_ndx * sizeof(struct winbindd_gr)],
gr_mem_list, gr_mem_list_len);
- SAFE_FREE(gr_mem_list);
-
state->response.length += gr_mem_list_len;
DEBUG(10, ("returning %d groups, length = %d\n",
@@ -793,6 +860,8 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
done:
+ SAFE_FREE(gr_mem_list);
+
if (group_list_ndx > 0)
request_ok(state);
else
@@ -807,7 +876,6 @@ void winbindd_list_groups(struct winbindd_cli_state *state)
struct winbindd_domain *domain;
const char *which_domain;
char *extra_data = NULL;
- char *ted = NULL;
unsigned int extra_data_len = 0, i;
DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid));
@@ -847,15 +915,13 @@ 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. */
- ted = SMB_REALLOC(extra_data, sizeof(fstring) * total_entries);
+ extra_data = SMB_REALLOC(extra_data, sizeof(fstring) * total_entries);
- if (!ted) {
+ if (!extra_data) {
DEBUG(0,("failed to enlarge buffer!\n"));
- SAFE_FREE(extra_data);
request_error(state);
return;
- } else
- extra_data = ted;
+ }
/* Pack group list into extra data fields */
for (i = 0; i < groups.num_sam_entries; i++) {
@@ -863,7 +929,7 @@ void winbindd_list_groups(struct winbindd_cli_state *state)
groups.sam_entries)[i].acct_name;
fstring name;
- fill_domain_username(name, domain->name, group_name);
+ fill_domain_username(name, domain->name, group_name, False);
/* Append to extra data */
memcpy(&extra_data[extra_data_len], name,
strlen(name));
@@ -877,7 +943,7 @@ void winbindd_list_groups(struct winbindd_cli_state *state)
/* Assign extra_data fields in response structure */
if (extra_data) {
extra_data[extra_data_len - 1] = '\0';
- state->response.extra_data = extra_data;
+ state->response.extra_data.data = extra_data;
state->response.length += extra_data_len;
}
@@ -938,10 +1004,18 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
if (!parse_domain_user_talloc(state->mem_ctx,
state->request.data.username,
&s->domname, &s->username)) {
- DEBUG(0, ("Could not parse domain user: %s\n",
+ DEBUG(5, ("Could not parse domain user: %s\n",
state->request.data.username));
- request_error(state);
- return;
+
+ /* error out if we do not have nested group support */
+
+ if ( !lp_winbind_nested_groups() ) {
+ request_error(state);
+ return;
+ }
+
+ s->domname = talloc_strdup( state->mem_ctx, get_global_sam_name() );
+ s->username = talloc_strdup( state->mem_ctx, state->request.data.username );
}
/* Get info for the domain */
@@ -1033,7 +1107,7 @@ 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 = s->token_gids;
+ s->state->response.extra_data.data = s->token_gids;
s->state->response.length += s->num_token_gids * sizeof(gid_t);
request_ok(s->state);
}
@@ -1113,7 +1187,7 @@ static void getusersids_recv(void *private_data, BOOL success, DOM_SID *sids,
/* Send data back to client */
state->response.data.num_entries = num_sids;
- state->response.extra_data = ret;
+ state->response.extra_data.data = ret;
state->response.length += ret_size;
request_ok(state);
}
@@ -1172,7 +1246,7 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
if (num_groups == 0) {
state->response.data.num_entries = 0;
- state->response.extra_data = NULL;
+ state->response.extra_data.data = NULL;
return WINBINDD_OK;
}
@@ -1181,10 +1255,9 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
return WINBINDD_ERROR;
}
- state->response.extra_data = sidstring;
+ state->response.extra_data.data = sidstring;
state->response.length += len+1;
state->response.data.num_entries = num_groups;
return WINBINDD_OK;
}
-
diff --git a/source/nsswitch/winbindd_ldap.c b/source/nsswitch/winbindd_ldap.c
deleted file mode 100644
index 736d852a74e..00000000000
--- a/source/nsswitch/winbindd_ldap.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- winbind ldap proxy code
-
- Copyright (C) Volker Lendecke
-
- This 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"
-
-/* This rw-buf api is made to avoid memcpy. For now do that like mad... The
- idea is to write into a circular list of buffers where the ideal case is
- that a read(2) holds a complete request that is then thrown away
- completely. */
-
-struct ldap_message_queue {
- struct ldap_message_queue *prev, *next;
- struct ldap_message *msg;
-};
-
-struct rw_buffer {
- uint8 *data;
- size_t ofs, length;
-};
-
-struct winbind_ldap_client {
- struct winbind_ldap_client *next, *prev;
- int sock;
- BOOL finished;
- struct rw_buffer in_buffer, out_buffer;
-};
-
-static struct winbind_ldap_client *ldap_clients;
-
-struct winbind_ldap_server {
- struct winbind_ldap_server *next, *prev;
- int sock;
- BOOL ready; /* Bind successful? */
- BOOL finished;
- struct rw_buffer in_buffer, out_buffer;
- int messageid;
-};
-
-static struct winbind_ldap_server *ldap_servers;
-
-struct pending_ldap_message {
- struct pending_ldap_message *next, *prev;
- struct ldap_message *msg; /* The message the client sent us */
- int our_msgid; /* The messageid we used */
- struct winbind_ldap_client *client;
-};
-
-struct pending_ldap_message *pending_messages;
-
-static BOOL append_to_buf(struct rw_buffer *buf, uint8 *data, size_t length)
-{
- buf->data = SMB_REALLOC(buf->data, buf->length+length);
-
- if (buf->data == NULL)
- return False;
-
- memcpy(buf->data+buf->length, data, length);
-
- buf->length += length;
- return True;
-}
-
-static BOOL read_into_buf(int fd, struct rw_buffer *buf)
-{
- char tmp_buf[1024];
- int len;
-
- len = read(fd, tmp_buf, sizeof(tmp_buf));
- if (len == 0)
- return False;
-
- return append_to_buf(buf, tmp_buf, len);
-}
-
-static void peek_into_buf(struct rw_buffer *buf, uint8 **out,
- size_t *out_length)
-{
- *out = buf->data;
- *out_length = buf->length;
-}
-
-static void consumed_from_buf(struct rw_buffer *buf, size_t length)
-{
- uint8 *new = memdup(buf->data+length, buf->length-length);
- free(buf->data);
- buf->data = new;
- buf->length -= length;
-}
-
-static BOOL write_out_of_buf(int fd, struct rw_buffer *buf)
-{
- uint8 *tmp;
- size_t tmp_length, written;
-
- peek_into_buf(buf, &tmp, &tmp_length);
- if (tmp_length == 0)
- return True;
-
- written = write(fd, tmp, tmp_length);
- if (written < 0)
- return False;
-
- consumed_from_buf(buf, written);
- return True;
-}
-
-static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
-{
- DATA_BLOB blob;
- BOOL res;
-
- if (!ldap_encode(msg, &blob))
- return False;
-
- res = append_to_buf(buf, blob.data, blob.length);
-
- data_blob_free(&blob);
- return res;
-}
-
-static void new_ldap_client(int listen_sock)
-{
- struct sockaddr_un sunaddr;
- struct winbind_ldap_client *client;
- socklen_t len;
- int sock;
-
- /* Accept connection */
-
- len = sizeof(sunaddr);
-
- do {
- sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len);
- } while (sock == -1 && errno == EINTR);
-
- if (sock == -1)
- return;
-
- DEBUG(6,("accepted socket %d\n", sock));
-
- /* Create new connection structure */
-
- client = SMB_MALLOC_P(struct winbind_ldap_client);
-
- if (client == NULL)
- return;
-
- ZERO_STRUCTP(client);
-
- client->sock = sock;
- client->finished = False;
-
- DLIST_ADD(ldap_clients, client);
-}
-
-static struct ldap_message *get_msg_from_buf(struct rw_buffer *buffer,
- BOOL *error)
-{
- uint8 *buf;
- int buf_length, msg_length;
- DATA_BLOB blob;
- ASN1_DATA data;
- struct ldap_message *msg;
-
- DEBUG(10,("ldapsrv_recv\n"));
-
- *error = False;
-
- peek_into_buf(buffer, &buf, &buf_length);
-
- if (buf_length < 8) {
- /* Arbitrary heuristics: ldap messages are longer than eight
- * bytes, and their tag length fits into the eight bytes */
- return NULL;
- }
-
- /* LDAP Messages are always SEQUENCES */
-
- if (!asn1_object_length(buf, buf_length, ASN1_SEQUENCE(0),
- &msg_length))
- goto disconnect;
-
- if (buf_length < msg_length) {
- /* Not enough yet */
- return NULL;
- }
-
- /* We've got a complete LDAP request in the in-buffer */
-
- blob.data = buf;
- blob.length = msg_length;
-
- if (!asn1_load(&data, blob))
- goto disconnect;
-
- msg = new_ldap_message();
-
- if ((msg == NULL) || !ldap_decode(&data, msg)) {
- asn1_free(&data);
- goto disconnect;
- }
-
- asn1_free(&data);
-
- consumed_from_buf(buffer, msg_length);
-
- return msg;
-
- disconnect:
-
- *error = True;
- return NULL;
-}
-
-static int send_msg_to_server(struct ldap_message *msg,
- struct winbind_ldap_server *server)
-{
- int cli_messageid;
-
- cli_messageid = msg->messageid;
- msg->messageid = ldap_servers->messageid;
-
- if (!ldap_append_to_buf(msg, &ldap_servers->out_buffer))
- return -1;
-
- msg->messageid = cli_messageid;
- return ldap_servers->messageid++;
-}
-
-static int send_msg(struct ldap_message *msg)
-{
- /* This is the scheduling routine that should decide where to send
- * stuff. The first attempt is easy: We only have one server. This
- * will change once we handle referrals etc. */
-
- SMB_ASSERT(ldap_servers != NULL);
-
- if (!ldap_servers->ready)
- return -1;
-
- return send_msg_to_server(msg, ldap_servers);
-}
-
-static void fake_bind_response(struct winbind_ldap_client *client,
- int messageid)
-{
- struct ldap_message *msg = new_ldap_message();
-
- if (msg == NULL) {
- client->finished = True;
- return;
- }
-
- msg->messageid = messageid;
- msg->type = LDAP_TAG_BindResponse;
- msg->r.BindResponse.response.resultcode = 0;
- msg->r.BindResponse.response.dn = "";
- msg->r.BindResponse.response.dn = "";
- msg->r.BindResponse.response.errormessage = "";
- msg->r.BindResponse.response.referral = "";
- ldap_append_to_buf(msg, &client->out_buffer);
- destroy_ldap_message(msg);
-}
-
-static int open_ldap_socket(void)
-{
- static int fd = -1;
-
- if (fd >= 0)
- return fd;
-
- fd = create_pipe_sock(get_winbind_priv_pipe_dir(), "ldapi", 0750);
- return fd;
-}
-
-static BOOL do_sigterm = False;
-
-static void ldap_termination_handler(int signum)
-{
- do_sigterm = True;
- sys_select_signal();
-}
-
-static BOOL handled_locally(struct ldap_message *msg,
- struct winbind_ldap_server *server)
-{
- struct ldap_Result *r = &msg->r.BindResponse.response;
-
- if (msg->type != LDAP_TAG_BindResponse)
- return False;
-
- if (r->resultcode != 0) {
- destroy_ldap_message(msg);
- server->finished = True;
- }
- destroy_ldap_message(msg);
- server->ready = True;
- return True;
-}
-
-static void client_has_data(struct winbind_ldap_client *client)
-{
-
- struct ldap_message *msg;
-
- if (!read_into_buf(client->sock, &client->in_buffer)) {
- client->finished = True;
- return;
- }
-
- while ((msg = get_msg_from_buf(&client->in_buffer,
- &client->finished))) {
- struct pending_ldap_message *pending;
-
- if (msg->type == LDAP_TAG_BindRequest) {
- fake_bind_response(client, msg->messageid);
- destroy_ldap_message(msg);
- continue;
- }
-
- if (msg->type == LDAP_TAG_UnbindRequest) {
- destroy_ldap_message(msg);
- client->finished = True;
- break;
- }
-
- pending = SMB_MALLOC_P(struct pending_ldap_message);
- if (pending == NULL)
- continue;
-
- pending->msg = msg;
- pending->client = client;
- pending->our_msgid = send_msg(msg);
-
- if (pending->our_msgid < 0) {
- /* could not send */
- client->finished = True;
- free(pending);
- }
- DLIST_ADD(pending_messages, pending);
- }
-}
-
-static struct ldap_Result *ldap_msg2result(struct ldap_message *msg)
-{
- switch(msg->type) {
- case LDAP_TAG_BindResponse:
- return &msg->r.BindResponse.response;
- case LDAP_TAG_SearchResultDone:
- return &msg->r.SearchResultDone;
- case LDAP_TAG_ModifyResponse:
- return &msg->r.ModifyResponse;
- case LDAP_TAG_AddResponse:
- return &msg->r.AddResponse;
- case LDAP_TAG_DelResponse:
- return &msg->r.DelResponse;
- case LDAP_TAG_ModifyDNResponse:
- return &msg->r.ModifyDNResponse;
- case LDAP_TAG_CompareResponse:
- return &msg->r.CompareResponse;
- case LDAP_TAG_ExtendedResponse:
- return &msg->r.ExtendedResponse.response;
- }
- return NULL;
-}
-
-static void server_has_data(struct winbind_ldap_server *server)
-{
- struct ldap_message *msg;
-
- if (!read_into_buf(server->sock, &server->in_buffer)) {
- server->finished = True;
- return;
- }
-
- while ((msg = get_msg_from_buf(&server->in_buffer,
- &server->finished))) {
- struct pending_ldap_message *pending;
- struct rw_buffer *buf;
- struct ldap_Result *res;
-
- if (handled_locally(msg, server))
- continue;
-
- res = ldap_msg2result(msg);
-
- if ( (res != NULL) && (res->resultcode == 10) )
- DEBUG(5, ("Got Referral %s\n", res->referral));
-
- for (pending = pending_messages;
- pending != NULL;
- pending = pending->next) {
- if (pending->our_msgid == msg->messageid)
- break;
- }
-
- if (pending == NULL) {
- talloc_destroy(msg->mem_ctx);
- continue;
- }
-
- msg->messageid = pending->msg->messageid;
-
- buf = &pending->client->out_buffer;
- ldap_append_to_buf(msg, buf);
-
- if ( (msg->type != LDAP_TAG_SearchResultEntry) &&
- (msg->type != LDAP_TAG_SearchResultReference) ) {
- destroy_ldap_message(pending->msg);
- DLIST_REMOVE(pending_messages,
- pending);
- SAFE_FREE(pending);
- }
- destroy_ldap_message(msg);
- }
-}
-
-static void process_ldap_loop(void)
-{
- struct winbind_ldap_client *client;
- struct winbind_ldap_server *server;
- fd_set r_fds, w_fds;
- int maxfd, listen_sock, selret;
- struct timeval timeout;
-
- /* Free up temporary memory */
-
- lp_talloc_free();
- main_loop_talloc_free();
-
- if (do_sigterm) {
-#if 0
- TALLOC_CTX *mem_ctx = talloc_init("describe");
- DEBUG(0, ("%s\n", talloc_describe_all(mem_ctx)));
- talloc_destroy(mem_ctx);
-#endif
- exit(0);
- }
-
- /* Initialise fd lists for select() */
-
- listen_sock = open_ldap_socket();
-
- if (listen_sock == -1) {
- perror("open_ldap_socket");
- exit(1);
- }
-
- maxfd = listen_sock;
-
- FD_ZERO(&r_fds);
- FD_ZERO(&w_fds);
- FD_SET(listen_sock, &r_fds);
-
- timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
- timeout.tv_usec = 0;
-
- /* Set up client readers and writers */
-
- client = ldap_clients;
-
- while (client != NULL) {
-
- if (client->finished) {
- struct winbind_ldap_client *next = client->next;
- DLIST_REMOVE(ldap_clients, client);
- close(client->sock);
- SAFE_FREE(client->in_buffer.data);
- SAFE_FREE(client->out_buffer.data);
- SAFE_FREE(client);
- client = next;
- continue;
- }
-
- if (client->sock > maxfd)
- maxfd = client->sock;
-
- FD_SET(client->sock, &r_fds);
-
- if (client->out_buffer.length > 0)
- FD_SET(client->sock, &w_fds);
-
- client = client->next;
- }
-
- /* And now the servers */
-
- server = ldap_servers;
-
- while (server != NULL) {
-
- if (server->finished) {
- struct winbind_ldap_server *next = server->next;
- DLIST_REMOVE(ldap_servers, server);
- close(server->sock);
- SAFE_FREE(server);
- server = next;
- continue;
- }
-
- if (server->sock > maxfd)
- maxfd = server->sock;
-
- FD_SET(server->sock, &r_fds);
-
- if (server->out_buffer.length > 0)
- FD_SET(server->sock, &w_fds);
-
- server = server->next;
- }
-
- selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
-
- if (selret == 0)
- return;
-
- if (selret == -1 && errno != EINTR) {
- perror("select");
- exit(1);
- }
-
- if (FD_ISSET(listen_sock, &r_fds))
- new_ldap_client(listen_sock);
-
- for (client = ldap_clients; client != NULL; client = client->next) {
-
- if (FD_ISSET(client->sock, &r_fds))
- client_has_data(client);
-
- if ((!client->finished) && FD_ISSET(client->sock, &w_fds))
- write_out_of_buf(client->sock, &client->out_buffer);
- }
-
- for (server = ldap_servers; server != NULL; server = server->next) {
-
- if (FD_ISSET(server->sock, &r_fds))
- server_has_data(server);
-
- if (!server->finished && FD_ISSET(server->sock, &w_fds))
- write_out_of_buf(server->sock, &server->out_buffer);
- }
-}
-
-static BOOL setup_ldap_serverconn(void)
-{
- char *host;
- uint16 port;
- BOOL ldaps;
- struct hostent *hp;
- struct in_addr ip;
- TALLOC_CTX *mem_ctx = talloc_init("server");
- struct ldap_message *msg;
- char *dn, *pw;
-
- ldap_servers = SMB_MALLOC_P(struct winbind_ldap_server);
-
- if ((ldap_servers == NULL) || (mem_ctx == NULL))
- return False;
-
- if (!ldap_parse_basic_url(mem_ctx, "ldap://192.168.234.1:3899/",
- &host, &port, &ldaps))
- return False;
-
- hp = sys_gethostbyname(host);
-
- if ((hp == NULL) || (hp->h_addr == NULL))
- return False;
-
- putip((char *)&ip, (char *)hp->h_addr);
-
- ZERO_STRUCTP(ldap_servers);
- ldap_servers->sock = open_socket_out(SOCK_STREAM, &ip, port, 10000);
- ldap_servers->messageid = 1;
-
- if (!fetch_ldap_pw(&dn, &pw))
- return False;
-
- msg = new_ldap_simple_bind_msg(dn, pw);
-
- SAFE_FREE(dn);
- SAFE_FREE(pw);
-
- if (msg == NULL)
- return False;
-
- msg->messageid = ldap_servers->messageid++;
-
- ldap_append_to_buf(msg, &ldap_servers->out_buffer);
-
- destroy_ldap_message(msg);
-
- return (ldap_servers->sock >= 0);
-}
-
-void do_ldap_proxy(void)
-{
- int ldap_child;
-
- ldap_child = sys_fork();
-
- if (ldap_child != 0)
- return;
-
- /* tdb needs special fork handling */
- if (tdb_reopen_all() == -1) {
- DEBUG(0,("tdb_reopen_all failed.\n"));
- _exit(0);
- }
-
- if (!message_init()) {
- DEBUG(0, ("message_init failed\n"));
- _exit(0);
- }
-
- CatchSignal(SIGINT, ldap_termination_handler);
- CatchSignal(SIGQUIT, ldap_termination_handler);
- CatchSignal(SIGTERM, ldap_termination_handler);
-
- if (!setup_ldap_serverconn())
- return;
-
- while (1)
- process_ldap_loop();
-
- return;
-}
diff --git a/source/nsswitch/winbindd_misc.c b/source/nsswitch/winbindd_misc.c
index 1fbf4b33df2..9413a79abaa 100644
--- a/source/nsswitch/winbindd_misc.c
+++ b/source/nsswitch/winbindd_misc.c
@@ -115,6 +115,7 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
int extra_data_len = 0;
char *extra_data;
NTSTATUS result;
+ BOOL have_own_domain = False;
DEBUG(3, ("[%5lu]: list trusted domains\n",
(unsigned long)state->pid));
@@ -137,6 +138,22 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
names[i],
alt_names[i] ? alt_names[i] : names[i],
sid_string_static(&sids[i]));
+ /* add our primary domain */
+
+ for (i=0; i<num_domains; i++) {
+ if (strequal(names[i], domain->name)) {
+ have_own_domain = True;
+ break;
+ }
+ }
+
+ if (state->request.data.list_all_domains && !have_own_domain) {
+ extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
+ extra_data,
+ domain->name,
+ domain->alt_name ? domain->alt_name : domain->name,
+ sid_string_static(&domain->sid));
+ }
/* This is a bit excessive, but the extra data sooner or later will be
talloc'ed */
@@ -144,7 +161,7 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
extra_data_len = strlen(extra_data);
if (extra_data_len > 0) {
- state->response.extra_data = SMB_STRDUP(extra_data);
+ state->response.extra_data.data = SMB_STRDUP(extra_data);
state->response.length += extra_data_len+1;
}
@@ -302,7 +319,7 @@ static void sequence_recv(void *private_data, BOOL success)
cli_state->response.length =
sizeof(cli_state->response) +
strlen(state->extra_data) + 1;
- cli_state->response.extra_data =
+ cli_state->response.extra_data.data =
SMB_STRDUP(state->extra_data);
request_ok(cli_state);
return;
@@ -486,8 +503,8 @@ void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
(unsigned long)state->pid));
- state->response.extra_data = SMB_STRDUP(get_winbind_priv_pipe_dir());
- if (!state->response.extra_data) {
+ state->response.extra_data.data = SMB_STRDUP(get_winbind_priv_pipe_dir());
+ if (!state->response.extra_data.data) {
DEBUG(0, ("malloc failed\n"));
request_error(state);
return;
@@ -495,7 +512,7 @@ void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
/* must add one to length to copy the 0 for string termination */
state->response.length +=
- strlen((char *)state->response.extra_data) + 1;
+ strlen((char *)state->response.extra_data.data) + 1;
request_ok(state);
}
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index eda68ae5c71..fe09cd8a06d 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -34,7 +34,7 @@
/* Update this when you change the interface. */
-#define WINBIND_INTERFACE_VERSION 11
+#define WINBIND_INTERFACE_VERSION 14
/* Socket commands */
@@ -64,6 +64,7 @@ enum winbindd_cmd {
WINBINDD_PAM_AUTH,
WINBINDD_PAM_AUTH_CRAP,
WINBINDD_PAM_CHAUTHTOK,
+ WINBINDD_PAM_LOGOFF,
/* List various things */
@@ -82,8 +83,9 @@ enum winbindd_cmd {
WINBINDD_SID_TO_GID,
WINBINDD_UID_TO_SID,
WINBINDD_GID_TO_SID,
- WINBINDD_ALLOCATE_RID,
- WINBINDD_ALLOCATE_RID_AND_GID,
+
+ WINBINDD_ALLOCATE_UID,
+ WINBINDD_ALLOCATE_GID,
/* Miscellaneous other stuff */
@@ -114,7 +116,7 @@ enum winbindd_cmd {
/* return a list of group sids for a user sid */
WINBINDD_GETUSERSIDS,
- /* Return the domain groups a user is in */
+ /* Various group queries */
WINBINDD_GETUSERDOMGROUPS,
/* Initialize connection in a child */
@@ -153,9 +155,8 @@ typedef struct winbindd_gr {
fstring gr_name;
fstring gr_passwd;
gid_t gr_gid;
- size_t num_gr_mem;
- size_t gr_mem_ofs; /* offset to group membership */
- char **gr_mem;
+ uint32 num_gr_mem;
+ uint32 gr_mem_ofs; /* offset to group membership */
} WINBINDD_GR;
@@ -165,7 +166,6 @@ typedef struct winbindd_gr {
#define WBFLAG_PAM_LMKEY 0x0008
#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x0010
#define WBFLAG_QUERY_ONLY 0x0020
-#define WBFLAG_ALLOCATE_RID 0x0040
#define WBFLAG_PAM_UNIX_NAME 0x0080
#define WBFLAG_PAM_AFS_TOKEN 0x0100
#define WBFLAG_PAM_NT_STATUS_SQUASH 0x0200
@@ -175,6 +175,11 @@ typedef struct winbindd_gr {
/* Flag to say this is a winbindd internal send - don't recurse. */
#define WBFLAG_RECURSE 0x0800
+#define WBFLAG_PAM_KRB5 0x1000
+#define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x2000
+#define WBFLAG_PAM_CACHED_LOGIN 0x4000
+#define WBFLAG_PAM_GET_PWD_POLICY 0x8000
+
#define WINBINDD_MAX_EXTRA_DATA (128*1024)
/* Winbind request structure */
@@ -199,6 +204,8 @@ struct winbindd_request {
fstring user;
fstring pass;
fstring require_membership_of_sid;
+ fstring krb5_cc_type;
+ uid_t uid;
} auth; /* pam_winbind auth module */
struct {
unsigned char chal[8];
@@ -217,6 +224,11 @@ struct winbindd_request {
fstring oldpass;
fstring newpass;
} chauthtok; /* pam_winbind passwd module */
+ struct {
+ fstring user;
+ fstring krb5ccname;
+ uid_t uid;
+ } logoff; /* pam_winbind session module */
fstring sid; /* lookupsid, sid_to_[ug]id */
struct {
fstring dom_name; /* lookupname */
@@ -242,9 +254,15 @@ struct winbindd_request {
gid_t gid;
fstring sid;
} dual_idmapset;
+ BOOL list_all_domains;
} data;
- char *extra_data;
- size_t extra_len;
+ union {
+#if defined(uint64)
+ uint64 z;
+#endif
+ char *data;
+ } extra_data;
+ uint32 extra_len;
char null_term;
};
@@ -307,12 +325,41 @@ struct winbindd_response {
int pam_error;
char user_session_key[16];
char first_8_lm_hash[8];
+ fstring krb5ccname;
+ struct policy_settings {
+ uint16 min_length_password;
+ uint16 password_history;
+ uint32 password_properties;
+ uint32 expire;
+ uint32 min_passwordage;
+ } policy;
+ uint32 reject_reason;
+ struct info3_text {
+ uint32 logon_time;
+ uint32 logoff_time;
+ uint32 kickoff_time;
+ uint32 pass_last_set_time;
+ uint32 pass_can_change_time;
+ uint32 pass_must_change_time;
+ uint16 logon_count;
+ uint16 bad_pw_count;
+ uint32 user_rid;
+ uint32 group_rid;
+ fstring dom_sid;
+ uint32 num_groups;
+ uint32 user_flgs;
+ uint32 acct_flags;
+ uint32 num_other_sids;
+ fstring user_name;
+ fstring full_name;
+ fstring logon_script;
+ fstring profile_path;
+ fstring home_dir;
+ fstring dir_drive;
+ fstring logon_srv;
+ fstring logon_dom;
+ } info3;
} auth;
- uint32 rid; /* create user or group or allocate rid */
- struct {
- uint32 rid;
- gid_t gid;
- } rid_and_gid;
struct {
fstring name;
fstring alt_name;
@@ -333,7 +380,28 @@ struct winbindd_response {
/* Variable length return data */
- void *extra_data; /* getgrnam, getgrgid, getgrent */
+ union {
+#if defined(uint64)
+ uint64 z;
+#endif
+ void *data;
+ } extra_data;
+};
+
+struct WINBINDD_CCACHE_ENTRY {
+ const char *principal_name;
+ const char *ccname;
+ const char *service;
+ const char *username;
+ const char *sid_string;
+ const char *pass;
+ 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 890007ae389..6f077294934 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -6,6 +6,7 @@
Copyright (C) Andrew Tridgell 2000
Copyright (C) Tim Potter 2001
Copyright (C) Andrew Bartlett 2001-2002
+ 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
@@ -27,6 +28,59 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
+ struct winbindd_cli_state *state,
+ NET_USER_INFO_3 *info3)
+{
+ fstring str_sid;
+
+ state->response.data.auth.info3.logon_time =
+ nt_time_to_unix(&(info3->logon_time));
+ state->response.data.auth.info3.logoff_time =
+ nt_time_to_unix(&(info3->logoff_time));
+ state->response.data.auth.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));
+ state->response.data.auth.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));
+
+ state->response.data.auth.info3.logon_count = info3->logon_count;
+ state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count;
+
+ state->response.data.auth.info3.user_rid = info3->user_rid;
+ state->response.data.auth.info3.group_rid = info3->group_rid;
+ sid_to_string(str_sid, &(info3->dom_sid.sid));
+ fstrcpy(state->response.data.auth.info3.dom_sid, str_sid);
+
+ state->response.data.auth.info3.num_groups = info3->num_groups;
+ state->response.data.auth.info3.user_flgs = info3->user_flgs;
+
+ state->response.data.auth.info3.acct_flags = info3->acct_flags;
+ state->response.data.auth.info3.num_other_sids = info3->num_other_sids;
+
+ unistr2_to_ascii(state->response.data.auth.info3.user_name,
+ &info3->uni_user_name, -1);
+ unistr2_to_ascii(state->response.data.auth.info3.full_name,
+ &info3->uni_full_name, -1);
+ unistr2_to_ascii(state->response.data.auth.info3.logon_script,
+ &info3->uni_logon_script, -1);
+ unistr2_to_ascii(state->response.data.auth.info3.profile_path,
+ &info3->uni_profile_path, -1);
+ unistr2_to_ascii(state->response.data.auth.info3.home_dir,
+ &info3->uni_home_dir, -1);
+ unistr2_to_ascii(state->response.data.auth.info3.dir_drive,
+ &info3->uni_dir_drive, -1);
+
+ unistr2_to_ascii(state->response.data.auth.info3.logon_srv,
+ &info3->uni_logon_srv, -1);
+ unistr2_to_ascii(state->response.data.auth.info3.logon_dom,
+ &info3->uni_logon_dom, -1);
+
+ return NT_STATUS_OK;
+}
static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
struct winbindd_cli_state *state,
@@ -43,13 +97,13 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
}
size = prs_data_size(&ps);
- state->response.extra_data = SMB_MALLOC(size);
- if (!state->response.extra_data) {
+ state->response.extra_data.data = SMB_MALLOC(size);
+ if (!state->response.extra_data.data) {
prs_mem_free(&ps);
return NT_STATUS_NO_MEMORY;
}
- memset( state->response.extra_data, '\0', size );
- prs_copy_all_data_out(state->response.extra_data, &ps);
+ memset( state->response.extra_data.data, '\0', size );
+ prs_copy_all_data_out(state->response.extra_data.data, &ps);
state->response.length += size;
prs_mem_free(&ps);
return NT_STATUS_OK;
@@ -145,14 +199,15 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
return NT_STATUS_LOGON_FAILURE;
}
-static struct winbindd_domain *find_auth_domain(const char *domain_name)
+static struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state,
+ const char *domain_name)
{
struct winbindd_domain *domain;
if (IS_DC) {
domain = find_domain_from_name_noinit(domain_name);
if (domain == NULL) {
- DEBUG(3, ("Authentication for domain [%s] "
+ DEBUG(3, ("Authentication for domain [%s] refused"
"as it is not a trusted domain\n",
domain_name));
}
@@ -181,9 +236,402 @@ static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
resp->data.auth.pam_error = nt_status_to_pam(result);
}
+static NTSTATUS fillup_password_policy(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ struct winbindd_methods *methods;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ SAM_UNK_INFO_1 password_policy;
+
+ methods = domain->methods;
+
+ status = methods->password_policy(domain, state->mem_ctx, &password_policy);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ state->response.data.auth.policy.min_length_password =
+ password_policy.min_length_password;
+ state->response.data.auth.policy.password_history =
+ password_policy.password_history;
+ state->response.data.auth.policy.password_properties =
+ password_policy.password_properties;
+ state->response.data.auth.policy.expire =
+ nt_time_to_unix_abs(&(password_policy.expire));
+ state->response.data.auth.policy.min_passwordage =
+ nt_time_to_unix_abs(&(password_policy.min_passwordage));
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint16 *max_allowed_bad_attempts)
+{
+ struct winbindd_methods *methods;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ SAM_UNK_INFO_12 lockout_policy;
+
+ *max_allowed_bad_attempts = 0;
+
+ methods = domain->methods;
+
+ status = methods->lockout_policy(domain, mem_ctx, &lockout_policy);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout;
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS get_pwd_properties(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 *password_properties)
+{
+ struct winbindd_methods *methods;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ SAM_UNK_INFO_1 password_policy;
+
+ *password_properties = 0;
+
+ methods = domain->methods;
+
+ status = methods->password_policy(domain, mem_ctx, &password_policy);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
+ *password_properties = password_policy.password_properties;
+
+ return NT_STATUS_OK;
+}
+
+static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx,
+ const char *type,
+ uid_t uid,
+ BOOL *internal_ccache)
+{
+ /* accept FILE and WRFILE as krb5_cc_type from the client and then
+ * build the full ccname string based on the user's uid here -
+ * Guenther*/
+
+ const char *gen_cc = NULL;
+
+ *internal_ccache = True;
+
+ if (uid == -1) {
+ goto memory_ccache;
+ }
+
+ if (!type || type[0] == '\0') {
+ goto memory_ccache;
+ }
+
+ if (strequal(type, "FILE")) {
+ gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
+ } else if (strequal(type, "WRFILE")) {
+ gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
+ } else {
+ DEBUG(10,("we don't allow to set a %s type ccache\n", type));
+ goto memory_ccache;
+ }
+
+ *internal_ccache = False;
+ goto done;
+
+ memory_ccache:
+ gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbindd_pam_ccache");
+
+ done:
+ if (gen_cc == NULL) {
+ DEBUG(0,("out of memory\n"));
+ return NULL;
+ }
+
+ DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":""));
+
+ 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;
+
+ state->response.data.auth.krb5ccname[0] = '\0';
+
+ if (type[0] == '\0') {
+ return;
+ }
+
+ if (!strequal(type, "FILE") &&
+ !strequal(type, "WRFILE")) {
+ DEBUG(10,("won't return krbccname for a %s type ccache\n",
+ type));
+ return;
+ }
+
+ fstrcpy(state->response.data.auth.krb5ccname, cc);
+}
+
/**********************************************************************
- Authenticate a user with a clear text password
-**********************************************************************/
+ 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)
+{
+#ifdef HAVE_KRB5
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ krb5_error_code krb5_ret;
+ DATA_BLOB tkt, session_key_krb5;
+ DATA_BLOB ap_rep, session_key;
+ PAC_DATA *pac_data = NULL;
+ PAC_LOGON_INFO *logon_info = NULL;
+ char *client_princ = NULL;
+ char *client_princ_out = NULL;
+ char *local_service = NULL;
+ const char *cc = NULL;
+ const char *principal_s = NULL;
+ const char *service = NULL;
+ char *realm = NULL;
+ fstring name_domain, name_user;
+ time_t ticket_lifetime = 0;
+ time_t renewal_until = 0;
+ uid_t uid = -1;
+ ADS_STRUCT *ads;
+ time_t time_offset = 0;
+ BOOL internal_ccache = True;
+
+ ZERO_STRUCT(session_key);
+ ZERO_STRUCT(session_key_krb5);
+ ZERO_STRUCT(tkt);
+ ZERO_STRUCT(ap_rep);
+
+ ZERO_STRUCTP(info3);
+
+ *info3 = NULL;
+
+ /* 1st step:
+ * prepare a krb5_cc_cache string for the user */
+
+ uid = get_uid_from_state(state);
+ if (uid == -1) {
+ DEBUG(0,("no valid uid\n"));
+ }
+
+ 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;
+ }
+
+
+ /* 2nd step:
+ * get kerberos properties */
+
+ if (domain->private_data) {
+ ads = (ADS_STRUCT *)domain->private_data;
+ time_offset = ads->auth.time_offset;
+ }
+
+
+ /* 3rd step:
+ * do kerberos auth and setup ccache as the user */
+
+ parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+ 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 this is a user ccache, we need to act as the user to let the krb5
+ * library handle the chown, etc. */
+
+ /************************ NON-ROOT **********************/
+
+ if (!internal_ccache) {
+
+ seteuid(uid);
+ DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
+ }
+
+ krb5_ret = kerberos_kinit_password_ext(principal_s,
+ state->request.data.auth.pass,
+ time_offset,
+ &ticket_lifetime,
+ &renewal_until,
+ cc,
+ True,
+ WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
+
+ if (krb5_ret) {
+ DEBUG(1,("winbindd_raw_kerberos_login: kinit failed for '%s' with: %s (%d)\n",
+ principal_s, error_message(krb5_ret), krb5_ret));
+ result = krb5_to_nt_status(krb5_ret);
+ goto failed;
+ }
+
+ /* does http_timestring use heimdals libroken strftime?? - Guenther */
+ DEBUG(10,("got TGT for %s in %s (valid until: %s (%d), renewable till: %s (%d))\n",
+ principal_s, cc,
+ http_timestring(ticket_lifetime), (int)ticket_lifetime,
+ http_timestring(renewal_until), (int)renewal_until));
+
+ client_princ = talloc_strdup(state->mem_ctx, global_myname());
+ if (client_princ == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+ strlower_m(client_princ);
+
+ local_service = talloc_asprintf(state->mem_ctx, "HOST/%s@%s", client_princ, lp_realm());
+ if (local_service == NULL) {
+ DEBUG(0,("winbindd_raw_kerberos_login: out of memory\n"));
+ result = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+
+ krb5_ret = cli_krb5_get_ticket(local_service,
+ time_offset,
+ &tkt,
+ &session_key_krb5,
+ 0,
+ cc);
+ if (krb5_ret) {
+ DEBUG(1,("winbindd_raw_kerberos_login: failed to get ticket for %s: %s\n",
+ local_service, error_message(krb5_ret)));
+ result = krb5_to_nt_status(krb5_ret);
+ goto failed;
+ }
+
+ if (!internal_ccache) {
+ seteuid(0);
+ }
+
+ /************************ NON-ROOT **********************/
+
+ result = ads_verify_ticket(state->mem_ctx,
+ lp_realm(),
+ &tkt,
+ &client_princ_out,
+ &pac_data,
+ &ap_rep,
+ &session_key);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("winbindd_raw_kerberos_login: ads_verify_ticket failed: %s\n",
+ nt_errstr(result)));
+ goto failed;
+ }
+
+ DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n",
+ local_service));
+
+ if (!pac_data) {
+ DEBUG(3,("winbindd_raw_kerberos_login: no pac data\n"));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto failed;
+ }
+
+ logon_info = get_logon_info_from_pac(pac_data);
+ if (logon_info == NULL) {
+ DEBUG(1,("winbindd_raw_kerberos_login: no logon info\n"));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto failed;
+ }
+
+
+ /* last step:
+ * put results together */
+
+ *info3 = &logon_info->info3;
+
+ /* if we had a user's ccache then return that string for the pam
+ * environment */
+
+ if (!internal_ccache) {
+
+ setup_return_cc_name(state, cc);
+
+ result = add_ccache_to_list(principal_s,
+ cc,
+ service,
+ state->request.data.auth.user,
+ NULL,
+ state->request.data.auth.pass,
+ uid,
+ time(NULL),
+ ticket_lifetime,
+ renewal_until,
+ lp_winbind_refresh_tickets());
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n",
+ nt_errstr(result)));
+ }
+ }
+
+ result = NT_STATUS_OK;
+
+ goto done;
+
+failed:
+
+ /* we could have created a new credential cache with a valid tgt in it
+ * but we werent able to get or verify the service ticket for this
+ * local host and therefor didn't get the PAC, we need to remove that
+ * cache entirely now */
+
+ krb5_ret = ads_kdestroy(cc);
+ if (krb5_ret) {
+ DEBUG(0,("winbindd_raw_kerberos_login: "
+ "could not destroy krb5 credential cache: "
+ "%s\n", error_message(krb5_ret)));
+ }
+
+done:
+ data_blob_free(&session_key);
+ data_blob_free(&session_key_krb5);
+ data_blob_free(&ap_rep);
+ data_blob_free(&tkt);
+
+ SAFE_FREE(client_princ_out);
+
+ if (!internal_ccache) {
+ seteuid(0);
+ }
+
+ return result;
+#else
+ return NT_STATUS_NOT_SUPPORTED;
+#endif /* HAVE_KRB5 */
+}
void winbindd_pam_auth(struct winbindd_cli_state *state)
{
@@ -203,10 +651,19 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
/* Parse domain and username */
- parse_domain_user(state->request.data.auth.user,
- name_domain, name_user);
+ if (!parse_domain_user(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 "
+ "(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;
+ }
- domain = find_auth_domain(name_domain);
+ domain = find_auth_domain(state, name_domain);
if (domain == NULL) {
set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
@@ -222,12 +679,234 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
sendto_domain(state, domain);
}
-enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
- struct winbindd_cli_state *state)
+NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state,
+ NET_USER_INFO_3 **info3)
{
- NTSTATUS result;
+ NTSTATUS result = NT_STATUS_LOGON_FAILURE;
+ uint16 max_allowed_bad_attempts;
fstring name_domain, name_user;
- NET_USER_INFO_3 info3;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ uchar new_nt_pass[NT_HASH_LEN];
+ const uint8 *cached_nt_pass;
+ NET_USER_INFO_3 *my_info3;
+ time_t kickoff_time, must_change_time;
+
+ *info3 = NULL;
+
+ ZERO_STRUCTP(info3);
+
+ DEBUG(10,("winbindd_dual_pam_auth_cached\n"));
+
+ /* Parse domain and username */
+
+ parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+
+ if (!lookup_cached_name(state->mem_ctx,
+ name_domain,
+ name_user,
+ &sid,
+ &type)) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n"));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (type != SID_NAME_USER) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type)));
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ result = winbindd_get_creds(domain,
+ state->mem_ctx,
+ &sid,
+ &my_info3,
+ &cached_nt_pass);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
+ return result;
+ }
+
+ *info3 = my_info3;
+
+ E_md4hash(state->request.data.auth.pass, new_nt_pass);
+
+#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);
+#endif
+
+ if (!memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN)) {
+
+ /* User *DOES* know the password, update logon_time and reset
+ * bad_pw_count */
+
+ my_info3->user_flgs |= LOGON_CACHED_ACCOUNT;
+
+ if (my_info3->acct_flags & ACB_AUTOLOCK) {
+ return NT_STATUS_ACCOUNT_LOCKED_OUT;
+ }
+
+ if (my_info3->acct_flags & ACB_DISABLED) {
+ return NT_STATUS_ACCOUNT_DISABLED;
+ }
+
+ if (my_info3->acct_flags & ACB_WSTRUST) {
+ return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
+ }
+
+ if (my_info3->acct_flags & ACB_SVRTRUST) {
+ return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
+ }
+
+ if (my_info3->acct_flags & ACB_DOMTRUST) {
+ 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",
+ my_info3->acct_flags));
+ return NT_STATUS_LOGON_FAILURE;
+ }
+#endif
+ 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);
+ if (must_change_time != 0 && must_change_time < time(NULL)) {
+ return NT_STATUS_PASSWORD_EXPIRED;
+ }
+
+ /* FIXME: we possibly should handle logon hours as well (does xp when
+ * offline?) see auth/auth_sam.c:sam_account_ok for details */
+
+ unix_to_nt_time(&my_info3->logon_time, time(NULL));
+ my_info3->bad_pw_count = 0;
+
+ result = winbindd_update_creds_by_info3(domain,
+ state->mem_ctx,
+ state->request.data.auth.user,
+ state->request.data.auth.pass,
+ my_info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1,("failed to update creds: %s\n", nt_errstr(result)));
+ return result;
+ }
+
+ return NT_STATUS_OK;
+
+ }
+
+ /* User does *NOT* know the correct password, modify info3 accordingly */
+
+ /* failure of this is not critical */
+ result = get_max_bad_attempts_from_lockout_policy(domain, state->mem_ctx, &max_allowed_bad_attempts);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. "
+ "Won't be able to honour account lockout policies\n"));
+ }
+
+ /* increase counter */
+ my_info3->bad_pw_count++;
+
+ if (max_allowed_bad_attempts == 0) {
+ goto failed;
+ }
+
+ /* lockout user */
+ if (my_info3->bad_pw_count >= max_allowed_bad_attempts) {
+
+ uint32 password_properties;
+
+ result = get_pwd_properties(domain, state->mem_ctx, &password_properties);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get password properties.\n"));
+ }
+
+ if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) ||
+ (password_properties & DOMAIN_LOCKOUT_ADMINS)) {
+ my_info3->acct_flags |= ACB_AUTOLOCK;
+ }
+ }
+
+failed:
+ result = winbindd_update_creds_by_info3(domain,
+ state->mem_ctx,
+ state->request.data.auth.user,
+ NULL,
+ my_info3);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n",
+ nt_errstr(result)));
+ }
+
+ return NT_STATUS_LOGON_FAILURE;
+}
+
+NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state,
+ NET_USER_INFO_3 **info3)
+{
+ struct winbindd_domain *contact_domain;
+ fstring name_domain, name_user;
+ NTSTATUS result;
+
+ DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
+
+ /* Parse domain and username */
+
+ parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+ /* what domain should we contact? */
+
+ if ( IS_DC ) {
+ if (!(contact_domain = find_domain_from_name(name_domain))) {
+ DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
+ state->request.data.auth.user, name_domain, name_user, name_domain));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ } else {
+ if (is_myname(name_domain)) {
+ DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ contact_domain = find_domain_from_name(name_domain);
+ if (contact_domain == NULL) {
+ DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n",
+ state->request.data.auth.user, name_domain, name_user, name_domain));
+
+ contact_domain = find_our_domain();
+ }
+ }
+
+ set_dc_type_and_flags(contact_domain);
+
+ if (!contact_domain->active_directory) {
+ DEBUG(3,("krb5 auth requested but domain is not Active Directory\n"));
+ return NT_STATUS_INVALID_LOGON_TYPE;
+ }
+
+ result = winbindd_raw_kerberos_login(contact_domain, state, info3);
+done:
+ return result;
+}
+
+NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state,
+ NET_USER_INFO_3 **info3)
+{
+
struct rpc_pipe_client *netlogon_pipe;
uchar chal[8];
DATA_BLOB lm_resp;
@@ -236,17 +915,23 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
unsigned char local_lm_response[24];
unsigned char local_nt_response[24];
struct winbindd_domain *contact_domain;
+ fstring name_domain, name_user;
BOOL retry;
+ NTSTATUS result;
+ NET_USER_INFO_3 *my_info3;
- /* Ensure null termination */
- state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
+ ZERO_STRUCTP(info3);
- /* Ensure null termination */
- state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';
+ *info3 = NULL;
+
+ my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3);
+ if (my_info3 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
- state->request.data.auth.user));
+ DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
+
/* Parse domain and username */
parse_domain_user(state->request.data.auth.user, name_domain, name_user);
@@ -332,7 +1017,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
do {
- ZERO_STRUCT(info3);
+ ZERO_STRUCTP(my_info3);
retry = False;
result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
@@ -352,7 +1037,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
chal,
lm_resp,
nt_resp,
- &info3);
+ my_info3);
attempts += 1;
/* We have to try a second time as cm_connect_netlogon
@@ -381,25 +1066,187 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
} while ( (attempts < 2) && retry );
+ *info3 = my_info3;
+done:
+ return result;
+}
+
+enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ NTSTATUS result = NT_STATUS_LOGON_FAILURE;
+ fstring name_domain, name_user;
+ NET_USER_INFO_3 *info3 = NULL;
+
+ /* Ensure null termination */
+ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
+
+ /* Ensure null termination */
+ state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';
+
+ DEBUG(3, ("[%5lu]: dual pam auth %s\n", (unsigned long)state->pid,
+ state->request.data.auth.user));
+
+ /* Parse domain and username */
+
+ parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+ DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
+
+ /* Check for Kerberos authentication */
+ if (domain->online && (state->request.flags & WBFLAG_PAM_KRB5)) {
+
+ result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
+
+ if (NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
+ goto process_result;
+ } else {
+ DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result)));
+ }
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)) {
+ DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
+ domain->online = False;
+ }
+
+ /* there are quite some NT_STATUS errors where there is no
+ * point in retrying with a samlogon, we explictly have to take
+ * care not to increase the bad logon counter on the DC */
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_DISABLED) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_EXPIRED) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_ACCOUNT_LOCKED_OUT) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_INVALID_LOGON_HOURS) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_INVALID_WORKSTATION) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_LOGON_FAILURE) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_USER) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) {
+ goto process_result;
+ }
+
+ if (state->request.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) {
+ DEBUG(3,("falling back to samlogon\n"));
+ goto sam_logon;
+ } else {
+ goto cached_logon;
+ }
+ }
+
+sam_logon:
+ /* Check for Samlogon authentication */
+ if (domain->online) {
+ result = winbindd_dual_pam_auth_samlogon(domain, state, &info3);
+
+ if (NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
+ goto process_result;
+ } else {
+ DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", nt_errstr(result)));
+ if (domain->online) {
+ /* We're still online - fail. */
+ goto done;
+ }
+ /* Else drop through and see if we can check offline.... */
+ }
+ }
+
+cached_logon:
+ /* Check for Cached logons */
+ if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
+ lp_winbind_offline_logon()) {
+
+ result = winbindd_dual_pam_auth_cached(domain, state, &info3);
+
+ if (NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
+ goto process_result;
+ } else {
+ DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
+ goto done;
+ }
+ }
+
+process_result:
+
if (NT_STATUS_IS_OK(result)) {
- netsamlogon_cache_store(name_user, &info3);
- wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
+
+ DOM_SID user_sid;
+ /* In all codepaths were result == NT_STATUS_OK info3 must have
+ been initialized. */
+ if (!info3) {
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ netsamlogon_cache_store(name_user, info3);
+ wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
+
+ /* save name_to_sid info as early as possible */
+ sid_compose(&user_sid, &info3->dom_sid.sid, info3->user_rid);
+ cache_name2sid(domain, name_domain, name_user, SID_NAME_USER, &user_sid);
+
/* Check if the user is in the right group */
- if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3,
+ if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3,
state->request.data.auth.require_membership_of_sid))) {
DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
state->request.data.auth.user,
state->request.data.auth.require_membership_of_sid));
+ goto done;
}
- }
-done:
+ if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
+ result = append_info3_as_ndr(state->mem_ctx, state, info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to append INFO3 (NDR): %s\n", nt_errstr(result)));
+ goto done;
+ }
+ }
+
+ if (state->request.flags & WBFLAG_PAM_INFO3_TEXT) {
+ result = append_info3_as_txt(state->mem_ctx, state, info3);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10,("Failed to append INFO3 (TXT): %s\n", nt_errstr(result)));
+ goto done;
+ }
+
+ }
+
+ if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
+ 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;
+ }
+
+ }
+
+ /* this is required to provide password expiry warning */
+ if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) {
+ 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;
+ }
+ }
+
+ }
+done:
/* give us a more useful (more correct?) error code */
if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
- (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+ (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
result = NT_STATUS_NO_LOGON_SERVERS;
}
@@ -439,8 +1286,8 @@ done:
DOM_SID user_sid;
fstring sidstr;
- sid_copy(&user_sid, &info3.dom_sid.sid);
- sid_append_rid(&user_sid, info3.user_rid);
+ sid_copy(&user_sid, &info3->dom_sid.sid);
+ sid_append_rid(&user_sid, info3->user_rid);
sid_to_string(sidstr, &user_sid);
afsname = talloc_string_sub(state->mem_ctx, afsname,
"%s", sidstr);
@@ -464,20 +1311,21 @@ done:
cell += 1;
/* Append an AFS token string */
- state->response.extra_data =
+ state->response.extra_data.data =
afs_createtoken_str(afsname, cell);
- if (state->response.extra_data != NULL)
+ if (state->response.extra_data.data != NULL)
state->response.length +=
- strlen(state->response.extra_data)+1;
+ strlen(state->response.extra_data.data)+1;
no_token:
- talloc_free(afsname);
+ TALLOC_FREE(afsname);
}
-
+
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
+
/**********************************************************************
Challenge Response Authentication Protocol
**********************************************************************/
@@ -525,7 +1373,7 @@ void winbindd_pam_auth_crap(struct winbindd_cli_state *state)
}
if (domain_name != NULL)
- domain = find_auth_domain(domain_name);
+ domain = find_auth_domain(state, domain_name);
if (domain != NULL) {
sendto_domain(state, domain);
@@ -626,6 +1474,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
ZERO_STRUCT(info3);
retry = False;
+ netlogon_pipe = NULL;
result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
if (!NT_STATUS_IS_OK(result)) {
@@ -675,6 +1524,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
} while ( (attempts < 2) && retry );
if (NT_STATUS_IS_OK(result)) {
+
netsamlogon_cache_store(name_user, &info3);
wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
@@ -706,16 +1556,16 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
nt_domain = name_domain;
}
- fill_domain_username(username_out, nt_domain, nt_username);
+ fill_domain_username(username_out, nt_domain, nt_username, True);
DEBUG(5, ("Setting unix username to [%s]\n", username_out));
- state->response.extra_data = SMB_STRDUP(username_out);
- if (!state->response.extra_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(state->response.extra_data)+1;
+ state->response.length += strlen(state->response.extra_data.data)+1;
}
if (state->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
@@ -732,7 +1582,7 @@ done:
/* give us a more useful (more correct?) error code */
if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
- (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+ (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
result = NT_STATUS_NO_LOGON_SERVERS;
}
@@ -763,12 +1613,16 @@ done:
void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
{
- NTSTATUS result;
- char *oldpass, *newpass;
+ 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));
@@ -777,7 +1631,8 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
parse_domain_user(state->request.data.chauthtok.user, domain, user);
- if (!(contact_domain = find_domain_from_name(domain))) {
+ contact_domain = find_domain_from_name(domain);
+ if (!contact_domain) {
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;
@@ -798,10 +1653,73 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
goto done;
}
- result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass,
- oldpass);
+ 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)) {
+
+ state->response.data.auth.policy.min_length_password =
+ info.min_length_password;
+ state->response.data.auth.policy.password_history =
+ info.password_history;
+ state->response.data.auth.policy.password_properties =
+ info.password_properties;
+ state->response.data.auth.policy.expire =
+ nt_time_to_unix_abs(&info.expire);
+ state->response.data.auth.policy.min_passwordage =
+ nt_time_to_unix_abs(&info.min_passwordage);
+
+ state->response.data.auth.reject_reason =
+ 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))) ||
+ (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) ||
+ (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED))) {
+
+ DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n",
+ nt_errstr(result)));
+
+ state->response.data.auth.reject_reason = 0;
+
+ result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass);
+ }
+
+done:
+ if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
+ lp_winbind_offline_logon()) {
+
+ NTSTATUS cred_ret;
+
+ cred_ret = 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) && !got_info && contact_domain) {
+
+ NTSTATUS policy_ret;
+
+ policy_ret = fillup_password_policy(contact_domain, state);
+
+ /* failure of this is non critical, it will just provide no
+ * additional information to the client why the change has
+ * failed - Guenther */
+
+ if (!NT_STATUS_IS_OK(policy_ret)) {
+ DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret)));
+ goto process_result;
+ }
+ }
+
+process_result:
-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));
@@ -814,8 +1732,114 @@ 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)) {
request_ok(state);
- else
+ } else {
+ request_error(state);
+ }
+}
+
+void winbindd_pam_logoff(struct winbindd_cli_state *state)
+{
+ struct winbindd_domain *domain;
+ fstring name_domain, user;
+
+ DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
+ state->request.data.logoff.user));
+
+ /* Ensure null termination */
+ state->request.data.logoff.user
+ [sizeof(state->request.data.logoff.user)-1]='\0';
+
+ 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 (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.auth.user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
request_error(state);
+ return;
+ }
+
+ sendto_domain(state, domain);
}
+
+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));
+
+ if (!(state->request.flags & WBFLAG_PAM_KRB5)) {
+ result = NT_STATUS_OK;
+ 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));
+ goto process_result;
+ }
+
+ DEBUG(10,("winbindd_pam_logoff: found ccache [%s]\n", entry->ccname));
+
+ if (entry->uid < 0 || 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));
+ 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));
+ 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 = krb5_to_nt_status(ret);
+#else
+ result = NT_STATUS_NOT_SUPPORTED;
+#endif
+
+process_result:
+ 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);
+
+ 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 c32aa01a38a..2aaed1acefb 100644
--- a/source/nsswitch/winbindd_passdb.c
+++ b/source/nsswitch/winbindd_passdb.c
@@ -33,7 +33,7 @@ static void add_member(const char *domain, const char *user,
{
fstring name;
- fill_domain_username(name, domain, user);
+ fill_domain_username(name, domain, user, True);
safe_strcat(name, ",", sizeof(name)-1);
string_append(pp_members, name);
*p_num_members += 1;
@@ -151,7 +151,8 @@ BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
*gr_mem = NULL;
*gr_mem_len = 0;
- if (!pdb_enum_aliasmem(group_sid, &members, &num_members))
+ if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members,
+ &num_members)))
return True;
for (i=0; i<num_members; i++) {
@@ -244,13 +245,11 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
{
DEBUG(10, ("Finding name %s\n", name));
- if (!pdb_find_alias(name, sid))
+ if ( !lookup_name( mem_ctx, name, LOOKUP_NAME_ALL,
+ NULL, NULL, sid, type ) )
+ {
return NT_STATUS_NONE_MAPPED;
-
- if (sid_check_is_in_builtin(sid))
- *type = SID_NAME_WKN_GRP;
- else
- *type = SID_NAME_ALIAS;
+ }
return NT_STATUS_OK;
}
@@ -265,19 +264,24 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
char **name,
enum SID_NAME_USE *type)
{
- struct acct_info info;
+ const char *dom, *nam;
DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
- if (!pdb_get_aliasinfo(sid, &info))
+ /* Paranoia check */
+ if (!sid_check_is_in_builtin(sid) &&
+ !sid_check_is_in_our_domain(sid)) {
+ DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
+ "passdb backend\n", sid_string_static(sid)));
return NT_STATUS_NONE_MAPPED;
+ }
- *domain_name = talloc_strdup(mem_ctx, domain->name);
- *name = talloc_strdup(mem_ctx, info.acct_name);
- if (sid_check_is_in_builtin(sid))
- *type = SID_NAME_WKN_GRP;
- else
- *type = SID_NAME_ALIAS;
+ if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ *domain_name = talloc_strdup(mem_ctx, dom);
+ *name = talloc_strdup(mem_ctx, nam);
return NT_STATUS_OK;
}
@@ -297,7 +301,28 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
const DOM_SID *user_sid,
uint32 *num_groups, DOM_SID **user_gids)
{
- return NT_STATUS_NO_SUCH_USER;
+ NTSTATUS result;
+ DOM_SID *groups = NULL;
+ gid_t *gids = NULL;
+ size_t ngroups = 0;
+ struct samu *user;
+
+ if ( (user = samu_new(mem_ctx)) == NULL ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( !pdb_getsampwsid( user, user_sid ) ) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ result = pdb_enum_group_memberships( mem_ctx, user, &groups, &gids, &ngroups );
+
+ TALLOC_FREE( user );
+
+ *num_groups = (uint32)ngroups;
+ *user_gids = groups;
+
+ return result;
}
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
@@ -305,14 +330,14 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
uint32 num_sids, const DOM_SID *sids,
uint32 *p_num_aliases, uint32 **rids)
{
- BOOL result;
+ NTSTATUS result;
size_t num_aliases = 0;
result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
sids, num_sids, rids, &num_aliases);
*p_num_aliases = num_aliases;
- return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ return result;
}
/* Lookup group membership given a rid. */
@@ -322,16 +347,106 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
DOM_SID **sid_mem, char ***names,
uint32 **name_types)
{
+ size_t i, num_members, num_mapped;
+ uint32 *rids;
+ NTSTATUS result;
+ const DOM_SID **sids;
+ struct lsa_dom_info *lsa_domains;
+ struct lsa_name_info *lsa_names;
+
+ 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,
+ &num_members);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ if (num_members == 0) {
+ *num_names = 0;
+ *sid_mem = NULL;
+ *names = NULL;
+ *name_types = NULL;
+ 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);
+
+ if (((*sid_mem) == NULL) || ((*names) == NULL) ||
+ ((*name_types) == NULL) || (sids == NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num_members; i++) {
+ DOM_SID *sid = &((*sid_mem)[i]);
+ sid_copy(sid, &domain->sid);
+ sid_append_rid(sid, rids[i]);
+ sids[i] = sid;
+ }
+
+ result = lookup_sids(mem_ctx, num_members, sids, 1,
+ &lsa_domains, &lsa_names);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ num_mapped = 0;
+ for (i=0; i<num_members; i++) {
+ if (lsa_names[i].type != SID_NAME_USER) {
+ DEBUG(2, ("Got %s as group member -- ignoring\n",
+ sid_type_lookup(lsa_names[i].type)));
+ continue;
+ }
+ (*names)[i] = talloc_steal((*names),
+ lsa_names[i].name);
+ (*name_types)[i] = lsa_names[i].type;
+
+ num_mapped += 1;
+ }
+
+ *num_names = num_mapped;
+
return NT_STATUS_OK;
}
/* find the sequence number for a domain */
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
- *seq = 1;
+ BOOL result;
+ time_t seq_num;
+
+ result = pdb_get_seq_num(&seq_num);
+ if (!result) {
+ *seq = 1;
+ }
+
+ *seq = (int) seq_num;
+ /* *seq = 1; */
return NT_STATUS_OK;
}
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_12 *policy)
+{
+ /* actually we have that */
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS password_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_1 *policy)
+{
+ /* actually we have that */
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
/* get a list of trusted domains */
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -341,41 +456,35 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
DOM_SID **dom_sids)
{
NTSTATUS nt_status;
- int enum_ctx = 0;
- int num_sec_domains;
- TRUSTDOM **domains;
+ struct trustdom_info **domains;
+ int i;
+
*num_domains = 0;
*names = NULL;
*alt_names = NULL;
*dom_sids = NULL;
- do {
- int i;
- nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, 1,
- &num_sec_domains,
- &domains);
- *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names, char *,
- num_sec_domains + *num_domains);
- *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names, char *,
- num_sec_domains + *num_domains);
- *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids, DOM_SID,
- num_sec_domains + *num_domains);
-
- for (i=0; i< num_sec_domains; i++) {
- if (pull_ucs2_talloc(mem_ctx, &(*names)[*num_domains],
- domains[i]->name) == -1) {
- return NT_STATUS_NO_MEMORY;
- }
- (*alt_names)[*num_domains] = NULL;
- (*dom_sids)[*num_domains] = domains[i]->sid;
- (*num_domains)++;
- }
- } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
+ nt_status = secrets_trusted_domains(mem_ctx, num_domains,
+ &domains);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+ *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+ *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
- if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
- return NT_STATUS_OK;
+ if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
+ return NT_STATUS_NO_MEMORY;
}
- return nt_status;
+
+ for (i=0; i<*num_domains; i++) {
+ (*alt_names)[i] = NULL;
+ (*names)[i] = talloc_steal((*names), domains[i]->name);
+ sid_copy(&(*dom_sids)[i], &domains[i]->sid);
+ }
+
+ return NT_STATUS_OK;
}
/* the rpc backend methods are exposed via this structure */
@@ -391,5 +500,7 @@ struct winbindd_methods passdb_methods = {
lookup_useraliases,
lookup_groupmem,
sequence_number,
+ lockout_policy,
+ password_policy,
trusted_domains,
};
diff --git a/source/nsswitch/winbindd_reconnect.c b/source/nsswitch/winbindd_reconnect.c
index 77df9c1513c..7bc8be12131 100644
--- a/source/nsswitch/winbindd_reconnect.c
+++ b/source/nsswitch/winbindd_reconnect.c
@@ -220,6 +220,36 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
return result;
}
+/* find the lockout policy of a domain */
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_12 *policy)
+{
+ NTSTATUS result;
+
+ result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))
+ result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
+
+ return result;
+}
+
+/* find the password policy of a domain */
+static NTSTATUS password_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_1 *policy)
+{
+ NTSTATUS result;
+
+ result = msrpc_methods.password_policy(domain, mem_ctx, policy);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))
+ result = msrpc_methods.password_policy(domain, mem_ctx, policy);
+
+ return result;
+}
+
/* get a list of trusted domains */
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -255,5 +285,7 @@ struct winbindd_methods reconnect_methods = {
lookup_useraliases,
lookup_groupmem,
sequence_number,
+ lockout_policy,
+ password_policy,
trusted_domains,
};
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 6179189e309..4aaedad4a21 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -269,7 +269,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, &sids, &types);
+ &full_name, NULL, &sids, &types);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -883,6 +883,71 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
return result;
}
+/* find the lockout policy for a domain */
+NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_12 *lockout_policy)
+{
+ NTSTATUS result;
+ struct rpc_pipe_client *cli;
+ POLICY_HND dom_pol;
+ SAM_UNK_CTR ctr;
+
+ DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
+
+ result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ *lockout_policy = ctr.info.inf12;
+
+ DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n",
+ ctr.info.inf12.bad_attempt_lockout));
+
+ done:
+
+ return result;
+}
+
+/* find the password policy for a domain */
+NTSTATUS msrpc_password_policy(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ SAM_UNK_INFO_1 *password_policy)
+{
+ NTSTATUS result;
+ struct rpc_pipe_client *cli;
+ POLICY_HND dom_pol;
+ SAM_UNK_CTR ctr;
+
+ DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
+
+ result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ *password_policy = ctr.info.inf1;
+
+ DEBUG(10,("msrpc_password_policy: min_length_password %d\n",
+ ctr.info.inf1.min_length_password));
+
+ done:
+
+ return result;
+}
+
+
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
False,
@@ -896,5 +961,7 @@ struct winbindd_methods msrpc_methods = {
msrpc_lookup_useraliases,
lookup_groupmem,
sequence_number,
+ msrpc_lockout_policy,
+ msrpc_password_policy,
trusted_domains,
};
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 2685e98555c..a4cd8f76042 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -83,10 +83,10 @@ void winbindd_lookupname(struct winbindd_cli_state *state)
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());
@@ -506,10 +506,10 @@ static void gid2sid_idmap_set_mapping_recv(void *private_data, BOOL success)
request_ok(state->cli_state);
}
-void winbindd_allocate_rid(struct winbindd_cli_state *state)
+void winbindd_allocate_uid(struct winbindd_cli_state *state)
{
if ( !state->privileged ) {
- DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
+ DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
"denied!\n"));
request_error(state);
return;
@@ -518,25 +518,22 @@ void winbindd_allocate_rid(struct winbindd_cli_state *state)
sendto_child(state, idmap_child());
}
-enum winbindd_result winbindd_dual_allocate_rid(struct winbindd_domain *domain,
+enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- /* We tell idmap to always allocate a user RID. There might be a good
- * reason to keep RID allocation for users to even and groups to
- * odd. This needs discussion I think. For now only allocate user
- * rids. */
+ union unid_t id;
- if (!NT_STATUS_IS_OK(idmap_allocate_rid(&state->response.data.rid,
- USER_RID_TYPE)))
+ if (!NT_STATUS_IS_OK(idmap_allocate_id(&id, ID_USERID))) {
return WINBINDD_ERROR;
-
+ }
+ state->response.data.uid = id.uid;
return WINBINDD_OK;
}
-void winbindd_allocate_rid_and_gid(struct winbindd_cli_state *state)
+void winbindd_allocate_gid(struct winbindd_cli_state *state)
{
if ( !state->privileged ) {
- DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
+ DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
"denied!\n"));
request_error(state);
return;
@@ -545,30 +542,15 @@ void winbindd_allocate_rid_and_gid(struct winbindd_cli_state *state)
sendto_child(state, idmap_child());
}
-enum winbindd_result winbindd_dual_allocate_rid_and_gid(struct winbindd_domain *domain,
- struct winbindd_cli_state *state)
+enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
{
- NTSTATUS result;
- DOM_SID sid;
-
- /* We tell idmap to always allocate a user RID. This is really
- * historic and needs to be fixed. I *think* this has to do with the
- * way winbind determines its free RID space. */
-
- result = idmap_allocate_rid(&state->response.data.rid_and_gid.rid,
- USER_RID_TYPE);
+ union unid_t id;
- if (!NT_STATUS_IS_OK(result))
+ if (!NT_STATUS_IS_OK(idmap_allocate_id(&id, ID_GROUPID))) {
return WINBINDD_ERROR;
-
- sid_copy(&sid, get_global_sam_sid());
- sid_append_rid(&sid, state->response.data.rid_and_gid.rid);
-
- result = idmap_sid_to_gid(&sid, &state->response.data.rid_and_gid.gid,
- 0);
-
- if (!NT_STATUS_IS_OK(result))
- return WINBINDD_ERROR;
-
+ }
+ state->response.data.gid = id.gid;
return WINBINDD_OK;
}
+
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 0b88d5eee5f..6179e497b78 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -97,7 +97,7 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
/* Username */
- fill_domain_username(output_username, dom_name, user_name);
+ fill_domain_username(output_username, dom_name, user_name, True);
safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
@@ -122,10 +122,10 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
pw->pw_uid, pw->pw_gid, shell, pw->pw_shell))
return False;
- /* Password - set to "x" as we can't generate anything useful here.
+ /* Password - set to "*" as we can't generate anything useful here.
Authentication can be done using the pam_winbind module. */
- safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
+ safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
return True;
}
@@ -289,7 +289,7 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
pw = &s->state->response.data.pw;
pw->pw_uid = s->uid;
pw->pw_gid = s->gid;
- fill_domain_username(output_username, s->domain->name, s->username);
+ fill_domain_username(output_username, s->domain->name, s->username, True);
safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1);
@@ -307,10 +307,10 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
goto failed;
}
- /* Password - set to "x" as we can't generate anything useful here.
+ /* Password - set to "*" as we can't generate anything useful here.
Authentication can be done using the pam_winbind module. */
- safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
+ safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
request_ok(s->state);
return;
@@ -337,7 +337,7 @@ void winbindd_getpwnam(struct winbindd_cli_state *state)
if (!parse_domain_user(state->request.data.username, domname,
username)) {
- DEBUG(0, ("Could not parse domain user: %s\n",
+ DEBUG(5, ("Could not parse domain user: %s\n",
state->request.data.username));
request_error(state);
return;
@@ -553,16 +553,12 @@ static BOOL get_sam_user_entries(struct getent_state *ent, TALLOC_CTX *mem_ctx)
&info);
if (num_entries) {
- struct getpwent_user *tnl;
+ name_list = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, ent->num_sam_entries + num_entries);
- tnl = SMB_REALLOC_ARRAY(name_list, struct getpwent_user, ent->num_sam_entries + num_entries);
-
- if (!tnl) {
+ if (!name_list) {
DEBUG(0,("get_sam_user_entries realloc failed.\n"));
- SAFE_FREE(name_list);
goto done;
- } else
- name_list = tnl;
+ }
}
for (i = 0; i < num_entries; i++) {
@@ -636,15 +632,15 @@ void winbindd_getpwent(struct winbindd_cli_state *state)
num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries);
- if ((state->response.extra_data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) {
+ if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) {
request_error(state);
return;
}
- memset(state->response.extra_data, 0, num_users *
+ memset(state->response.extra_data.data, 0, num_users *
sizeof(struct winbindd_pw));
- user_list = (struct winbindd_pw *)state->response.extra_data;
+ user_list = (struct winbindd_pw *)state->response.extra_data.data;
if (!state->getpwent_initialized)
winbindd_setpwent_internal(state);
@@ -731,7 +727,7 @@ void winbindd_list_users(struct winbindd_cli_state *state)
WINBIND_USERINFO *info;
const char *which_domain;
uint32 num_entries = 0, total_entries = 0;
- char *ted, *extra_data = NULL;
+ char *extra_data = NULL;
int extra_data_len = 0;
enum winbindd_result rv = WINBINDD_ERROR;
@@ -767,15 +763,13 @@ void winbindd_list_users(struct winbindd_cli_state *state)
/* Allocate some memory for extra data */
total_entries += num_entries;
- ted = SMB_REALLOC(extra_data, sizeof(fstring) * total_entries);
+ extra_data = SMB_REALLOC(extra_data, sizeof(fstring) * total_entries);
- if (!ted) {
+ if (!extra_data) {
DEBUG(0,("failed to enlarge buffer!\n"));
- SAFE_FREE(extra_data);
goto done;
- } else
- extra_data = ted;
-
+ }
+
/* Pack user list into extra data fields */
for (i = 0; i < num_entries; i++) {
@@ -787,7 +781,7 @@ void winbindd_list_users(struct winbindd_cli_state *state)
fstrcpy(acct_name, info[i].acct_name);
}
- fill_domain_username(name, domain->name, acct_name);
+ fill_domain_username(name, domain->name, acct_name, True);
/* Append to extra data */
memcpy(&extra_data[extra_data_len], name,
@@ -801,7 +795,7 @@ void winbindd_list_users(struct winbindd_cli_state *state)
if (extra_data) {
extra_data[extra_data_len - 1] = '\0';
- state->response.extra_data = extra_data;
+ state->response.extra_data.data = extra_data;
state->response.length += extra_data_len;
}
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index 4c3306a8aca..d64345a36f3 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -61,8 +61,9 @@ struct winbindd_domain *domain_list(void)
{
/* Initialise list */
- if (!_domain_list)
- init_domain_list();
+ if ((!_domain_list) && (!init_domain_list())) {
+ smb_panic("Init_domain_list failed\n");
+ }
return _domain_list;
}
@@ -161,6 +162,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
domain->sequence_number = DOM_SEQUENCE_NONE;
domain->last_seq_check = 0;
domain->initialized = False;
+ domain->online = False;
if (sid) {
sid_copy(&domain->sid, sid);
}
@@ -234,7 +236,7 @@ static void trustdom_recv(void *private_data, BOOL success)
return;
}
- p = response->extra_data;
+ p = response->extra_data.data;
while ((p != NULL) && (*p != '\0')) {
char *q, *sidstr, *alt_name;
@@ -286,7 +288,7 @@ static void trustdom_recv(void *private_data, BOOL success)
p += 1;
}
- SAFE_FREE(response->extra_data);
+ SAFE_FREE(response->extra_data.data);
talloc_destroy(state->mem_ctx);
}
@@ -334,6 +336,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
struct winbindd_request *request;
struct winbindd_response *response;
struct init_child_state *state;
+ struct winbindd_domain *request_domain;
mem_ctx = talloc_init("init_child_connection");
if (mem_ctx == NULL) {
@@ -366,7 +369,6 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
fstrcpy(request->domain_name, domain->name);
request->data.init_conn.is_primary = True;
fstrcpy(request->data.init_conn.dcname, "");
-
async_request(mem_ctx, &domain->child, request, response,
init_child_recv, state);
return WINBINDD_PENDING;
@@ -378,7 +380,11 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
request->cmd = WINBINDD_GETDCNAME;
fstrcpy(request->domain_name, domain->name);
- async_domain_request(mem_ctx, find_our_domain(), request, response,
+ /* save online flag */
+ request_domain = find_our_domain();
+ request_domain->online = domain->online;
+
+ async_domain_request(mem_ctx, request_domain, request, response,
init_child_getdc_recv, state);
return WINBINDD_PENDING;
}
@@ -493,48 +499,48 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai
}
/* Look up global info for the winbind daemon */
-void init_domain_list(void)
+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();
/* Free existing list */
free_domain_list();
/* Add ourselves as the first entry. */
- if (IS_DC) {
- domain = add_trusted_domain(get_global_sam_name(), NULL,
- &passdb_methods,
- get_global_sam_sid());
- } else {
-
+ if ( role == ROLE_DOMAIN_MEMBER ) {
DOM_SID our_sid;
if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
- smb_panic("Could not fetch our SID - did we join?\n");
+ DEBUG(0, ("Could not fetch our SID - did we join?\n"));
+ return False;
}
domain = add_trusted_domain( lp_workgroup(), lp_realm(),
&cache_methods, &our_sid);
+ domain->primary = True;
+ setup_domain_child(domain, &domain->child, NULL);
}
- domain->primary = True;
+ /* Local SAM */
+
+ domain = add_trusted_domain(get_global_sam_name(), NULL,
+ &passdb_methods, get_global_sam_sid());
+ if ( role != ROLE_DOMAIN_MEMBER ) {
+ domain->primary = True;
+ }
setup_domain_child(domain, &domain->child, NULL);
- /* Add our local SAM domains */
+ /* BUILTIN domain */
domain = add_trusted_domain("BUILTIN", NULL, &passdb_methods,
&global_sid_Builtin);
setup_domain_child(domain, &domain->child, NULL);
- if (!IS_DC) {
- domain = add_trusted_domain(get_global_sam_name(), NULL,
- &passdb_methods,
- get_global_sam_sid());
- setup_domain_child(domain, &domain->child, NULL);
- }
+ return True;
}
/**
@@ -830,10 +836,9 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
if ( assume_domain(lp_workgroup())) {
fstrcpy(domain, lp_workgroup());
} else {
- fstrcpy( domain, get_global_sam_name() );
+ return False;
}
- }
- else {
+ } else {
fstrcpy(user, p+1);
fstrcpy(domain, domuser);
domain[PTR_DIFF(p, domuser)] = 0;
@@ -848,7 +853,9 @@ BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
char **domain, char **user)
{
fstring fstr_domain, fstr_user;
- parse_domain_user(domuser, fstr_domain, fstr_user);
+ if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
+ return False;
+ }
*domain = talloc_strdup(mem_ctx, fstr_domain);
*user = talloc_strdup(mem_ctx, fstr_user);
return ((*domain != NULL) && (*user != NULL));
@@ -867,14 +874,14 @@ BOOL parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
username is then unqualified in unix
*/
-void fill_domain_username(fstring name, const char *domain, const char *user)
+void fill_domain_username(fstring name, const char *domain, const char *user, BOOL can_assume)
{
fstring tmp_user;
fstrcpy(tmp_user, user);
strlower_m(tmp_user);
- if (assume_domain(domain)) {
+ if (can_assume && assume_domain(domain)) {
strlcpy(name, user, sizeof(fstring));
} else {
slprintf(name, sizeof(fstring) - 1, "%s%c%s",
@@ -1079,10 +1086,6 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state
#define HWM_GROUP "GROUP HWM"
#define HWM_USER "USER HWM"
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
-
-
/*****************************************************************************
Convert the idmap database from an older version.
*****************************************************************************/
@@ -1207,3 +1210,25 @@ BOOL winbindd_upgrade_idmap(void)
return idmap_convert(idmap_name);
}
+
+void winbindd_flush_nscd_cache(void)
+{
+#ifdef HAVE_NSCD_FLUSH_CACHE
+
+ /* Flush nscd caches to get accurate new information */
+ int ret = nscd_flush_cache("passwd");
+ if (ret) {
+ DEBUG(5,("failed to flush nscd cache for 'passwd' service: %s\n",
+ strerror(ret)));
+ }
+
+ ret = nscd_flush_cache("group");
+ if (ret) {
+ DEBUG(5,("failed to flush nscd cache for 'group' service: %s\n",
+ strerror(ret)));
+ }
+#else
+ return;
+#endif
+}
+
diff --git a/source/nsswitch/wins.c b/source/nsswitch/wins.c
index ac5b0f11572..f871a53982e 100644
--- a/source/nsswitch/wins.c
+++ b/source/nsswitch/wins.c
@@ -80,7 +80,7 @@ static void nss_wins_init(void)
TimeInit();
setup_logging("nss_wins",False);
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
}
diff --git a/source/pam_smbpass/pam_smb_acct.c b/source/pam_smbpass/pam_smb_acct.c
index 2ea7eea7d87..8970ffa8edf 100644
--- a/source/pam_smbpass/pam_smb_acct.c
+++ b/source/pam_smbpass/pam_smb_acct.c
@@ -46,11 +46,12 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags,
int retval;
const char *name;
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
void (*oldsig_handler)(int);
extern BOOL in_client;
/* Samba initialization. */
+ load_case_tables();
setup_logging( "pam_smbpass", False );
in_client = True;
@@ -79,10 +80,13 @@ int pam_sm_acct_mgmt( pam_handle_t *pamh, int flags,
}
/* Get the user's record. */
- pdb_init_sam(&sampass);
- pdb_getsampwnam(sampass, name );
- if (!sampass) {
+ if ( (sampass = samu_new( NULL )) != NULL ) {
+ pdb_getsampwnam(sampass, name );
+ }
+
+ /* check for lookup failure */
+ if ( !sampass || !strlen(pdb_get_username(sampass)) ) {
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_USER_UNKNOWN;
}
diff --git a/source/pam_smbpass/pam_smb_auth.c b/source/pam_smbpass/pam_smb_auth.c
index 5be6b4ec09c..15726aa8552 100644
--- a/source/pam_smbpass/pam_smb_auth.c
+++ b/source/pam_smbpass/pam_smb_auth.c
@@ -47,7 +47,7 @@ do { \
} while (0)
static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
- const char *name, SAM_ACCOUNT *sampass, BOOL exist);
+ const char *name, struct samu *sampass, BOOL exist);
/*
@@ -64,7 +64,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
{
unsigned int ctrl;
int retval, *ret_data = NULL;
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
extern BOOL in_client;
const char *name;
void (*oldsig_handler)(int) = NULL;
@@ -75,6 +75,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
/* Samba initialization. */
+ load_case_tables();
setup_logging("pam_smbpass",False);
in_client = True;
@@ -107,20 +108,20 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
AUTH_RETURN;
}
- pdb_init_sam(&sampass);
+ sampass = samu_new( NULL );
found = pdb_getsampwnam( sampass, name );
if (on( SMB_MIGRATE, ctrl )) {
retval = _smb_add_user(pamh, ctrl, name, sampass, found);
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
AUTH_RETURN;
}
if (!found) {
_log_err(LOG_ALERT, "Failed to find entry for user %s.", name);
retval = PAM_USER_UNKNOWN;
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
sampass = NULL;
AUTH_RETURN;
}
@@ -128,7 +129,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
/* if this user does not have a password... */
if (_smb_blankpasswd( ctrl, sampass )) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
retval = PAM_SUCCESS;
AUTH_RETURN;
}
@@ -139,14 +140,14 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
if (retval != PAM_SUCCESS ) {
_log_err(LOG_CRIT, "auth: no password provided for [%s]"
, name);
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
AUTH_RETURN;
}
/* verify the password of this user */
retval = _smb_verify_password( pamh, sampass, p, ctrl );
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
p = NULL;
AUTH_RETURN;
}
@@ -176,7 +177,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags,
/* Helper function for adding a user to the db. */
static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
- const char *name, SAM_ACCOUNT *sampass, BOOL exist)
+ const char *name, struct samu *sampass, BOOL exist)
{
pstring err_str;
pstring msg_str;
@@ -199,10 +200,10 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
/* Add the user to the db if they aren't already there. */
if (!exist) {
- retval = local_password_change( name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD,
+ retval = NT_STATUS_IS_OK(local_password_change( name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD,
pass, err_str,
sizeof(err_str),
- msg_str, sizeof(msg_str) );
+ msg_str, sizeof(msg_str) ));
if (!retval && *err_str)
{
err_str[PSTRING_LEN-1] = '\0';
@@ -221,8 +222,8 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
/* mimick 'update encrypted' as long as the 'no pw req' flag is not set */
if ( pdb_get_acct_ctrl(sampass) & ~ACB_PWNOTREQ )
{
- retval = local_password_change( name, LOCAL_SET_PASSWORD, pass, err_str, sizeof(err_str),
- msg_str, sizeof(msg_str) );
+ retval = NT_STATUS_IS_OK(local_password_change( name, LOCAL_SET_PASSWORD, pass, err_str, sizeof(err_str),
+ msg_str, sizeof(msg_str) ));
if (!retval && *err_str)
{
err_str[PSTRING_LEN-1] = '\0';
diff --git a/source/pam_smbpass/pam_smb_passwd.c b/source/pam_smbpass/pam_smb_passwd.c
index 8149bc12003..79bcfb6ff0f 100644
--- a/source/pam_smbpass/pam_smb_passwd.c
+++ b/source/pam_smbpass/pam_smb_passwd.c
@@ -47,9 +47,9 @@ int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user, const char *
err_str[0] = '\0';
msg_str[0] = '\0';
- retval = local_password_change( user, LOCAL_SET_PASSWORD, pass_new,
+ retval = NT_STATUS_IS_OK(local_password_change( user, LOCAL_SET_PASSWORD, pass_new,
err_str, sizeof(err_str),
- msg_str, sizeof(msg_str) );
+ msg_str, sizeof(msg_str) ));
if (!retval) {
if (*err_str) {
@@ -96,15 +96,14 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
extern BOOL in_client;
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
void (*oldsig_handler)(int);
const char *user;
char *pass_old;
char *pass_new;
- NTSTATUS nt_status;
-
/* Samba initialization. */
+ load_case_tables();
setup_logging( "pam_smbpass", False );
in_client = True;
@@ -130,16 +129,16 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
from a SIGPIPE it's not expecting */
oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN);
- if (!initialize_password_db(True)) {
+ if (!initialize_password_db(False)) {
_log_err( LOG_ALERT, "Cannot access samba password database" );
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_AUTHINFO_UNAVAIL;
}
/* obtain user record */
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
+ if ( !(sampass = samu_new( NULL )) ) {
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
- return nt_status_to_pam(nt_status);
+ return nt_status_to_pam(NT_STATUS_NO_MEMORY);
}
if (!pdb_getsampwnam(sampass,user)) {
@@ -147,6 +146,9 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_USER_UNKNOWN;
}
+ if (on( SMB_DEBUG, ctrl )) {
+ _log_err( LOG_DEBUG, "Located account for %s", user );
+ }
if (flags & PAM_PRELIM_CHECK) {
/*
@@ -158,7 +160,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
if (_smb_blankpasswd( ctrl, sampass )) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_SUCCESS;
}
@@ -172,7 +174,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
Announce = SMB_MALLOC_ARRAY(char, sizeof(greeting)+strlen(user));
if (Announce == NULL) {
_log_err(LOG_CRIT, "password: out of memory");
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return PAM_BUF_ERR;
}
@@ -188,7 +190,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
if (retval != PAM_SUCCESS) {
_log_err( LOG_NOTICE
, "password - (old) token not obtained" );
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
@@ -203,7 +205,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
}
pass_old = NULL;
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
@@ -233,7 +235,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
if (retval != PAM_SUCCESS) {
_log_err( LOG_NOTICE, "password: user not authenticated" );
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
@@ -261,7 +263,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
, "password: new password not obtained" );
}
pass_old = NULL; /* tidy up */
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
@@ -281,7 +283,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
if (retval != PAM_SUCCESS) {
_log_err(LOG_NOTICE, "new password not acceptable");
pass_new = pass_old = NULL; /* tidy up */
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
@@ -298,7 +300,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
uid_t uid;
/* password updated */
- if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &uid))) {
+ if (!sid_to_uid(pdb_get_user_sid(sampass), &uid)) {
_log_err( LOG_NOTICE, "Unable to get uid for user %s",
pdb_get_username(sampass));
_log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)",
@@ -313,7 +315,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
pass_old = pass_new = NULL;
if (sampass) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
sampass = NULL;
}
@@ -325,11 +327,11 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
}
if (sampass) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
sampass = NULL;
}
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
return retval;
}
diff --git a/source/pam_smbpass/support.c b/source/pam_smbpass/support.c
index 82d51103d26..c318a5c3ed1 100644
--- a/source/pam_smbpass/support.c
+++ b/source/pam_smbpass/support.c
@@ -167,7 +167,7 @@ int set_ctrl( int flags, int argc, const char **argv )
/* Read some options from the Samba config. Can be overridden by
the PAM config. */
- if(lp_load(service_file,True,False,False) == False) {
+ if(lp_load(service_file,True,False,False,True) == False) {
_log_err( LOG_ERR, "Error loading service file %s", service_file );
}
@@ -305,7 +305,7 @@ void _cleanup_failures( pam_handle_t * pamh, void *fl, int err )
}
}
-int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass,
+int _smb_verify_password( pam_handle_t * pamh, struct samu *sampass,
const char *p, unsigned int ctrl )
{
uchar lm_pw[16];
@@ -398,7 +398,7 @@ int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass,
service ? service : "**unknown**", name);
newauth->count = 1;
}
- if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &(newauth->id)))) {
+ if (!sid_to_uid(pdb_get_user_sid(sampass), &(newauth->id))) {
_log_err(LOG_NOTICE,
"failed auth request by %s for service %s as %s",
uidtoname(getuid()),
@@ -437,7 +437,7 @@ int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass,
* - to avoid prompting for one in such cases (CG)
*/
-int _smb_blankpasswd( unsigned int ctrl, SAM_ACCOUNT *sampass )
+int _smb_blankpasswd( unsigned int ctrl, struct samu *sampass )
{
int retval;
diff --git a/source/pam_smbpass/support.h b/source/pam_smbpass/support.h
index a13a2d0aeb9..0b2863d7b95 100644
--- a/source/pam_smbpass/support.h
+++ b/source/pam_smbpass/support.h
@@ -26,7 +26,7 @@ extern BOOL strequal(const char *, const char *);
extern struct smb_passwd *
_my_get_smbpwnam(FILE *, const char *, BOOL *, BOOL *, long *);
-extern int _smb_verify_password( pam_handle_t *pamh , SAM_ACCOUNT *sampass,
+extern int _smb_verify_password( pam_handle_t *pamh , struct samu *sampass,
const char *p, unsigned int ctrl );
/*
@@ -39,7 +39,7 @@ extern int _smb_get_user(pam_handle_t *, unsigned int,
/* _smb_blankpasswd() is a quick check for a blank password */
-extern int _smb_blankpasswd(unsigned int, SAM_ACCOUNT *);
+extern int _smb_blankpasswd(unsigned int, struct samu *);
/* obtain a password from the user */
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index c535903d2b7..e0cbc981def 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -54,6 +54,7 @@
#include "includes.h"
BOOL in_client = False; /* Not in the client by default */
+BOOL in_server = False; /* Not in the server by default */
BOOL bLoaded = False;
extern userdom_struct current_user_info;
@@ -76,6 +77,9 @@ extern enum protocol_types Protocol;
#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
#define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
+#define USERSHARE_VALID 1
+#define USERSHARE_PENDING_DELETE 2
+
int keepalive = DEFAULT_KEEPALIVE;
BOOL use_getwd_cache = True;
@@ -94,13 +98,13 @@ struct _param_opt_struct {
/*
* This structure describes global (ie., server-wide) parameters.
*/
-typedef struct
-{
+typedef struct {
char *smb_ports;
char *dos_charset;
char *unix_charset;
char *display_charset;
char *szPrintcapname;
+ char *szAddPortCommand;
char *szEnumPortsCommand;
char *szAddPrinterCommand;
char *szDeletePrinterCommand;
@@ -121,7 +125,7 @@ typedef struct
char *szConfigFile;
char *szSMBPasswdFile;
char *szPrivateDir;
- char **szPassdbBackend;
+ char *szPassdbBackend;
char **szPreloadModules;
char *szPasswordServer;
char *szSocketOptions;
@@ -167,7 +171,6 @@ typedef struct
BOOL bUtmp;
char *szIdmapUID;
char *szIdmapGID;
- BOOL bEnableRidAlgorithm;
BOOL bPassdbExpandExplicit;
int AlgorithmicRidBase;
char *szTemplateHomedir;
@@ -178,6 +181,8 @@ typedef struct
BOOL bWinbindUseDefaultDomain;
BOOL bWinbindTrustedDomainsOnly;
BOOL bWinbindNestedGroups;
+ BOOL bWinbindRefreshTickets;
+ BOOL bWinbindOfflineLogon;
char **szIdmapBackend;
char *szAddShareCommand;
char *szChangeShareCommand;
@@ -186,12 +191,17 @@ typedef struct
char *szGuestaccount;
char *szManglingMethod;
char **szServicesList;
+ char *szUsersharePath;
+ char *szUsershareTemplateShare;
+ char **szUsersharePrefixAllowList;
+ char **szUsersharePrefixDenyList;
int mangle_prefix;
int max_log_size;
char *szLogLevel;
int max_xmit;
int max_mux;
int max_open_files;
+ int open_files_db_hash_size;
int pwordlevel;
int unamelevel;
int deadtime;
@@ -294,28 +304,32 @@ typedef struct
BOOL bUnixExtensions;
BOOL bDisableNetbios;
BOOL bKernelChangeNotify;
+ BOOL bFamChangeNotify;
BOOL bUseKerberosKeytab;
BOOL bDeferSharingViolations;
BOOL bEnablePrivileges;
BOOL bASUSupport;
+ BOOL bUsershareOwnerOnly;
int restrict_anonymous;
int name_cache_timeout;
int client_signing;
int server_signing;
+ int iUsershareMaxShares;
+
BOOL bResetOnZeroVC;
param_opt_struct *param_opt;
-}
-global;
+} global;
static global Globals;
/*
* This structure describes a single service.
*/
-typedef struct
-{
+typedef struct {
BOOL valid;
BOOL autoloaded;
+ int usershare;
+ time_t usershare_last_mod;
char *szService;
char *szPath;
char *szUsername;
@@ -397,6 +411,7 @@ typedef struct
BOOL bMap_hidden;
BOOL bMap_archive;
BOOL bStoreDosAttributes;
+ BOOL bDmapiSupport;
BOOL bLocking;
int iStrictLocking;
BOOL bPosixLocking;
@@ -444,14 +459,15 @@ typedef struct
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
-}
-service;
+} service;
/* This is a default service used to prime a services structure */
static service sDefault = {
True, /* valid */
False, /* not autoloaded */
+ 0, /* not a usershare */
+ (time_t)0, /* No last mod time */
NULL, /* szService */
NULL, /* szPath */
NULL, /* szUsername */
@@ -533,8 +549,9 @@ static service sDefault = {
False, /* bMap_hidden */
True, /* bMap_archive */
False, /* bStoreDosAttributes */
+ False, /* bDmapiSupport */
True, /* bLocking */
- True, /* iStrictLocking */
+ Auto, /* iStrictLocking */
True, /* bPosixLocking */
True, /* bShareModes */
True, /* bOpLocks */
@@ -559,9 +576,9 @@ static service sDefault = {
False, /* bInheritPerms */
False, /* bInheritACLS */
False, /* bInheritOwner */
- False, /* bMSDfsRoot */
+ True, /* bMSDfsRoot */
False, /* bUseClientDriver */
- False, /* bDefaultDevmode */
+ True, /* bDefaultDevmode */
False, /* bForcePrintername */
True, /* bNTAclSupport */
False, /* bForceUnknownAclUser */
@@ -608,7 +625,6 @@ static BOOL handle_workgroup( int snum, const char *pszParmValue, char **ptr );
static BOOL handle_netbios_aliases( int snum, const char *pszParmValue, char **ptr );
static BOOL handle_netbios_scope( int snum, const char *pszParmValue, char **ptr );
static BOOL handle_charset( int snum, const char *pszParmValue, char **ptr );
-static BOOL handle_acl_compatibility( int snum, const char *pszParmValue, char **ptr);
static BOOL handle_printing( int snum, const char *pszParmValue, char **ptr);
static void set_server_role(void);
@@ -764,6 +780,13 @@ static const struct enum_list enum_smb_signing_vals[] = {
{-1, NULL}
};
+/* ACL compatibility options. */
+static const struct enum_list enum_acl_compat_vals[] = {
+ { ACL_COMPAT_AUTO, "auto" },
+ { ACL_COMPAT_WINNT, "winnt" },
+ { ACL_COMPAT_WIN2K, "win2k" },
+ { -1, NULL}
+};
/*
Do you want session setups at user level security with a invalid
@@ -848,7 +871,7 @@ static struct parm_struct parm_table[] = {
{"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD},
{"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED},
{"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED},
- {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD},
+ {"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD},
{"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED},
{"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED},
{"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE},
@@ -893,7 +916,7 @@ static struct parm_struct parm_table[] = {
{"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
{"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
- {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
+ {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED },
{"acl map full control", P_BOOL, P_LOCAL, &sDefault.bAclMapFullControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
{"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
{"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE},
@@ -955,7 +978,7 @@ static struct parm_struct parm_table[] = {
{"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED},
{"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED},
- {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, NULL, enum_acl_compat_vals, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
{"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
@@ -992,6 +1015,7 @@ static struct parm_struct parm_table[] = {
{"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},
{"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},
@@ -1000,6 +1024,7 @@ static struct parm_struct parm_table[] = {
{"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_ADVANCED},
{"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED},
{"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
+ {"open files database hash size", P_INTEGER, P_GLOBAL, &Globals.open_files_db_hash_size, NULL, NULL, FLAG_ADVANCED},
{"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL, FLAG_ADVANCED},
{"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
@@ -1036,6 +1061,7 @@ static struct parm_struct parm_table[] = {
{"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL},
{"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL},
+ {"addport command", P_STRING, P_GLOBAL, &Globals.szAddPortCommand, NULL, NULL, FLAG_ADVANCED},
{"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED},
{"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED},
{"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED},
@@ -1075,6 +1101,8 @@ static struct parm_struct parm_table[] = {
{"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED},
{"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED},
{"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"dmapi support", P_BOOL, P_LOCAL, &sDefault.bDmapiSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+
{N_("Domain Options"), P_SEP, P_SEPARATOR},
@@ -1212,6 +1240,12 @@ static struct parm_struct parm_table[] = {
{"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
{"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
{"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
+ {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
+ {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED},
+ {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
+ {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED},
+ {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED},
+ {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
{"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
{"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
{"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
@@ -1240,7 +1274,6 @@ static struct parm_struct parm_table[] = {
{N_("Winbind options"), P_SEP, P_SEPARATOR},
- {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED},
{"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},
@@ -1256,8 +1289,9 @@ static struct parm_struct parm_table[] = {
{"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED},
{"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED},
{"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED},
- {"winbind max idle children", P_INTEGER, P_GLOBAL, &Globals.winbind_max_idle_children, NULL, NULL, FLAG_ADVANCED},
{"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},
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
};
@@ -1352,11 +1386,17 @@ static void init_printer_values(service *pService)
Initialise the global parameter structure.
***************************************************************************/
-static void init_globals(void)
+static void init_globals(BOOL first_time_only)
{
static BOOL done_init = False;
pstring s;
+ /* If requested to initialize only once and we've already done it... */
+ if (first_time_only && done_init) {
+ /* ... then we have nothing more to do */
+ return;
+ }
+
if (!done_init) {
int i;
@@ -1460,6 +1500,7 @@ static void init_globals(void)
Globals.bLargeReadwrite = True;
Globals.max_log_size = 5000;
Globals.max_open_files = MAX_OPEN_FILES;
+ Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
Globals.maxprotocol = PROTOCOL_NT1;
Globals.minprotocol = PROTOCOL_CORE;
Globals.security = SEC_USER;
@@ -1486,6 +1527,7 @@ static void init_globals(void)
Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
Globals.change_notify_timeout = 60; /* 1 minute 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;
@@ -1532,13 +1574,12 @@ static void init_globals(void)
a large number of sites (tridge) */
Globals.bHostnameLookups = False;
- str_list_free(&Globals.szPassdbBackend);
#ifdef WITH_LDAP_SAMCONFIG
string_set(&Globals.szLdapServer, "localhost");
Globals.ldap_port = 636;
- Globals.szPassdbBackend = str_list_make("ldapsam_compat", NULL);
+ string_set(&Globals.szPassdbBackend, "ldapsam_compat");
#else
- Globals.szPassdbBackend = str_list_make("smbpasswd", NULL);
+ string_set(&Globals.szPassdbBackend, "smbpasswd");
#endif /* WITH_LDAP_SAMCONFIG */
string_set(&Globals.szLdapSuffix, "");
string_set(&Globals.szLdapMachineSuffix, "");
@@ -1596,15 +1637,15 @@ static void init_globals(void)
string_set(&Globals.szIPrintServer, "");
Globals.winbind_cache_time = 300; /* 5 minutes */
- Globals.bWinbindEnumUsers = True;
- Globals.bWinbindEnumGroups = True;
+ Globals.bWinbindEnumUsers = False;
+ Globals.bWinbindEnumGroups = False;
Globals.bWinbindUseDefaultDomain = False;
Globals.bWinbindTrustedDomainsOnly = False;
- Globals.bWinbindNestedGroups = False;
- Globals.winbind_max_idle_children = 3;
+ Globals.bWinbindNestedGroups = True;
Globals.szWinbindNssInfo = str_list_make("template", NULL);
+ Globals.bWinbindRefreshTickets = False;
+ Globals.bWinbindOfflineLogon = False;
- Globals.bEnableRidAlgorithm = True;
Globals.bPassdbExpandExplicit = True;
Globals.name_cache_timeout = 660; /* In seconds */
@@ -1618,12 +1659,18 @@ static void init_globals(void)
Globals.bDeferSharingViolations = True;
string_set(&Globals.smb_ports, SMB_PORTS);
- /* don't enable privileges by default since Domain
- Admins can then assign thr rights to perform certain
- operations as root */
-
- Globals.bEnablePrivileges = False;
- Globals.bASUSupport = True;
+ Globals.bEnablePrivileges = True;
+ Globals.bHostMSDfs = True;
+ Globals.bASUSupport = False;
+
+ /* User defined shares. */
+ pstrcpy(s, dyn_LOCKDIR);
+ pstrcat(s, "/usershares");
+ string_set(&Globals.szUsersharePath, s);
+ string_set(&Globals.szUsershareTemplateShare, "");
+ Globals.iUsershareMaxShares = 0;
+ /* By default disallow sharing of directories not owned by the sharer. */
+ Globals.bUsershareOwnerOnly = True;
}
static TALLOC_CTX *lp_talloc;
@@ -1632,14 +1679,27 @@ static TALLOC_CTX *lp_talloc;
Free up temporary memory - called from the main loop.
********************************************************************/
-void lp_talloc_free(void)
+void lp_TALLOC_FREE(void)
{
if (!lp_talloc)
return;
- talloc_free(lp_talloc);
+ TALLOC_FREE(lp_talloc);
lp_talloc = NULL;
}
+TALLOC_CTX *tmp_talloc_ctx(void)
+{
+ if (lp_talloc == NULL) {
+ lp_talloc = talloc_init(NULL);
+ }
+
+ if (lp_talloc == NULL) {
+ smb_panic("Could not create temporary talloc context\n");
+ }
+
+ return lp_talloc;
+}
+
/*******************************************************************
Convenience routine to grab string parameters into temporary memory
and run standard_sub_basic on them. The buffers can be written to by
@@ -1716,6 +1776,7 @@ FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
+FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
@@ -1755,7 +1816,7 @@ 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_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
+FN_GLOBAL_STRING(lp_passdb_backend, &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)
@@ -1782,16 +1843,16 @@ FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
-FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
+FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.szAclCompat)
FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
FN_GLOBAL_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_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
-FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm)
FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
#ifdef WITH_LDAP_SAMCONFIG
@@ -1809,9 +1870,13 @@ FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
+FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
+FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
+FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
+FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
@@ -1865,6 +1930,7 @@ 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_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)
@@ -1875,6 +1941,7 @@ FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
+FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
@@ -1899,6 +1966,8 @@ 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_usershare_max_shares, &Globals.iUsershareMaxShares)
+
FN_LOCAL_STRING(lp_preexec, szPreExec)
FN_LOCAL_STRING(lp_postexec, szPostExec)
FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
@@ -1963,6 +2032,7 @@ FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
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)
@@ -2025,7 +2095,6 @@ FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
-FN_GLOBAL_INTEGER(lp_winbind_max_idle_children, &Globals.winbind_max_idle_children)
FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
@@ -2099,14 +2168,17 @@ static param_opt_struct *get_parametrics(int snum, const char *type, const char
}
+#define MISSING_PARAMETER(name) \
+ DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
+
/*******************************************************************
convenience routine to return int parameters.
********************************************************************/
static int lp_int(const char *s)
{
- if (!s) {
- DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
+ if (!s || !*s) {
+ MISSING_PARAMETER(lp_int);
return (-1);
}
@@ -2116,12 +2188,12 @@ static int lp_int(const char *s)
/*******************************************************************
convenience routine to return unsigned long parameters.
********************************************************************/
-static int lp_ulong(const char *s)
+static unsigned long lp_ulong(const char *s)
{
- if (!s) {
- DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
- return (-1);
+ if (!s || !*s) {
+ MISSING_PARAMETER(lp_ulong);
+ return (0);
}
return strtoul(s, NULL, 10);
@@ -2134,8 +2206,8 @@ static BOOL lp_bool(const char *s)
{
BOOL ret = False;
- if (!s) {
- DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
+ if (!s || !*s) {
+ MISSING_PARAMETER(lp_bool);
return False;
}
@@ -2154,8 +2226,8 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
{
int i;
- if (!s || !_enum) {
- DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s));
+ if (!s || !*s || !_enum) {
+ MISSING_PARAMETER(lp_enum);
return (-1);
}
@@ -2168,6 +2240,7 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
return (-1);
}
+#undef MISSING_PARAMETER
/* DO NOT USE lp_parm_string ANYMORE!!!!
* use lp_parm_const_string or lp_parm_talloc_string
@@ -2409,7 +2482,7 @@ static int add_a_service(const service *pservice, const char *name)
service **tsp;
int *tinvalid;
- tsp = SMB_REALLOC_ARRAY(ServicePtrs, service *, num_to_alloc);
+ tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
if (tsp == NULL) {
DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
return (-1);
@@ -2423,7 +2496,7 @@ static int add_a_service(const service *pservice, const char *name)
iNumServices++;
/* enlarge invalid_services here for now... */
- tinvalid = SMB_REALLOC_ARRAY(invalid_services, int,
+ tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
num_to_alloc);
if (tinvalid == NULL) {
DEBUG(0,("add_a_service: failed to enlarge "
@@ -2466,7 +2539,7 @@ static char *canonicalize_servicename(const char *src)
}
fstrcpy( canon, src );
- strupper_m( canon );
+ strlower_m( canon );
return canon;
}
@@ -2876,10 +2949,12 @@ static BOOL service_ok(int iService)
}
if (ServicePtrs[iService]->szPath[0] == '\0' &&
- strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0) {
- DEBUG(0, ("No path in service %s - using %s\n",
- ServicePtrs[iService]->szService, tmpdir()));
- string_set(&ServicePtrs[iService]->szPath, tmpdir());
+ strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
+ ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
+ ) {
+ DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
+ ServicePtrs[iService]->szService));
+ ServicePtrs[iService]->bAvailable = False;
}
/* If a service is flagged unavailable, log the fact at level 0. */
@@ -3146,7 +3221,7 @@ static BOOL handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
{
uint32 low, high;
- if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
+ if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
return False;
/* Parse OK */
@@ -3163,7 +3238,7 @@ static BOOL handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
{
uint32 low, high;
- if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
+ if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
return False;
/* Parse OK */
@@ -3242,23 +3317,6 @@ char *lp_ldap_idmap_suffix(void)
return lp_string(Globals.szLdapSuffix);
}
-/***************************************************************************
-***************************************************************************/
-
-static BOOL handle_acl_compatibility(int snum, const char *pszParmValue, char **ptr)
-{
- if (strequal(pszParmValue, "auto"))
- string_set(ptr, "");
- else if (strequal(pszParmValue, "winnt"))
- string_set(ptr, "winnt");
- else if (strequal(pszParmValue, "win2k"))
- string_set(ptr, "win2k");
- else
- return False;
-
- return True;
-}
-
/****************************************************************************
set the value for a P_ENUM
***************************************************************************/
@@ -3430,16 +3488,15 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
switch (parm_table[parmnum].type)
{
case P_BOOL:
- set_boolean((BOOL *)parm_ptr, pszParmValue);
+ *(BOOL *)parm_ptr = lp_bool(pszParmValue);
break;
case P_BOOLREV:
- set_boolean((BOOL *)parm_ptr, pszParmValue);
- *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
+ *(BOOL *)parm_ptr = !lp_bool(pszParmValue);
break;
case P_INTEGER:
- *(int *)parm_ptr = atoi(pszParmValue);
+ *(int *)parm_ptr = lp_int(pszParmValue);
break;
case P_CHAR:
@@ -3820,16 +3877,39 @@ 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, result = False;
+ int i;
+ BOOL result = False;
parm_class p_class;
unsigned flag = 0;
+ fstring local_parm_name;
+ char *parm_opt;
+ const char *parm_opt_value;
+
+ /* check for parametrical option */
+ fstrcpy( local_parm_name, parm_name);
+ parm_opt = strchr( local_parm_name, ':');
+
+ if (parm_opt) {
+ *parm_opt = '\0';
+ parm_opt++;
+ if (strlen(parm_opt)) {
+ parm_opt_value = lp_parm_const_string( snum,
+ local_parm_name, parm_opt, NULL);
+ if (parm_opt_value) {
+ printf( "%s\n", parm_opt_value);
+ result = True;
+ }
+ }
+ return result;
+ }
+ /* check for a key and print the value */
if (isGlobal) {
p_class = P_GLOBAL;
flag = FLAG_GLOBAL;
} else
p_class = P_LOCAL;
-
+
for (i = 0; parm_table[i].label; i++) {
if (strwicmp(parm_table[i].label, parm_name) == 0 &&
(parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
@@ -4015,9 +4095,11 @@ void lp_killunused(BOOL (*snumused) (int))
if (!VALID(i))
continue;
- /* don't kill autoloaded services */
- if ( ServicePtrs[i]->autoloaded )
+ /* don't kill autoloaded or usershare services */
+ if ( ServicePtrs[i]->autoloaded ||
+ ServicePtrs[i]->usershare == USERSHARE_VALID) {
continue;
+ }
if (!snumused || !snumused(i)) {
free_service_byindex(i);
@@ -4166,6 +4248,7 @@ static void set_server_role(void)
/***********************************************************
If we should send plaintext/LANMAN passwords in the clinet
************************************************************/
+
static void set_allowed_client_auth(void)
{
if (Globals.bClientNTLMv2Auth) {
@@ -4177,12 +4260,671 @@ static void set_allowed_client_auth(void)
}
/***************************************************************************
+ JRA.
+ The following code allows smbd to read a user defined share file.
+ Yes, this is my intent. Yes, I'm comfortable with that...
+
+ THE FOLLOWING IS SECURITY CRITICAL CODE.
+
+ It washes your clothes, it cleans your house, it guards you while you sleep...
+ Do not f%^k with it....
+***************************************************************************/
+
+#define MAX_USERSHARE_FILE_SIZE (10*1024)
+
+/***************************************************************************
+ Check allowed stat state of a usershare file.
+ Ensure we print out who is dicking with us so the admin can
+ get their sorry ass fired.
+***************************************************************************/
+
+static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
+{
+ if (!S_ISREG(psbuf->st_mode)) {
+ DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
+ "not a regular file\n",
+ fname, (unsigned int)psbuf->st_uid ));
+ return False;
+ }
+
+ /* Ensure this doesn't have the other write bit set. */
+ if (psbuf->st_mode & S_IWOTH) {
+ DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
+ "public write. Refusing to allow as a usershare file.\n",
+ fname, (unsigned int)psbuf->st_uid ));
+ return False;
+ }
+
+ /* Should be 10k or less. */
+ if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
+ DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
+ "too large (%u) to be a user share file.\n",
+ fname, (unsigned int)psbuf->st_uid,
+ (unsigned int)psbuf->st_size ));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ Parse the contents of a usershare file.
+***************************************************************************/
+
+enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
+ SMB_STRUCT_STAT *psbuf,
+ const char *servicename,
+ int snum,
+ char **lines,
+ int numlines,
+ pstring sharepath,
+ pstring comment,
+ SEC_DESC **ppsd)
+{
+ const char **prefixallowlist = lp_usershare_prefix_allow_list();
+ const char **prefixdenylist = lp_usershare_prefix_deny_list();
+ SMB_STRUCT_DIR *dp;
+ SMB_STRUCT_STAT sbuf;
+
+ if (numlines < 4) {
+ return USERSHARE_MALFORMED_FILE;
+ }
+
+ if (!strequal(lines[0], "#VERSION 1")) {
+ return USERSHARE_BAD_VERSION;
+ }
+
+ if (!strnequal(lines[1], "path=", 5)) {
+ return USERSHARE_MALFORMED_PATH;
+ }
+
+ pstrcpy(sharepath, &lines[1][5]);
+ trim_string(sharepath, " ", " ");
+
+ if (!strnequal(lines[2], "comment=", 8)) {
+ return USERSHARE_MALFORMED_COMMENT_DEF;
+ }
+
+ pstrcpy(comment, &lines[2][8]);
+ trim_string(comment, " ", " ");
+ trim_char(comment, '"', '"');
+
+ if (!strnequal(lines[3], "usershare_acl=", 14)) {
+ return USERSHARE_MALFORMED_ACL_DEF;
+ }
+
+ if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
+ return USERSHARE_ACL_ERR;
+ }
+
+ if (snum != -1 && strequal(sharepath, ServicePtrs[snum]->szPath)) {
+ /* Path didn't change, no checks needed. */
+ return USERSHARE_OK;
+ }
+
+ /* The path *must* be absolute. */
+ if (sharepath[0] != '/') {
+ DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
+ servicename, sharepath));
+ return USERSHARE_PATH_NOT_ABSOLUTE;
+ }
+
+ /* If there is a usershare prefix deny list ensure one of these paths
+ doesn't match the start of the user given path. */
+ if (prefixdenylist) {
+ int i;
+ for ( i=0; prefixdenylist[i]; i++ ) {
+ DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
+ servicename, i, prefixdenylist[i], sharepath ));
+ if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
+ DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
+ "usershare prefix deny list entries.\n",
+ servicename, sharepath));
+ return USERSHARE_PATH_IS_DENIED;
+ }
+ }
+ }
+
+ /* If there is a usershare prefix allow list ensure one of these paths
+ does match the start of the user given path. */
+
+ if (prefixallowlist) {
+ int i;
+ for ( i=0; prefixallowlist[i]; i++ ) {
+ DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
+ servicename, i, prefixallowlist[i], sharepath ));
+ if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
+ break;
+ }
+ }
+ if (prefixallowlist[i] == NULL) {
+ DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
+ "usershare prefix allow list entries.\n",
+ servicename, sharepath));
+ return USERSHARE_PATH_NOT_ALLOWED;
+ }
+ }
+
+ /* Ensure this is pointing to a directory. */
+ dp = sys_opendir(sharepath);
+
+ if (!dp) {
+ DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
+ servicename, sharepath));
+ return USERSHARE_PATH_NOT_DIRECTORY;
+ }
+
+ /* Ensure the owner of the usershare file has permission to share
+ this directory. */
+
+ if (sys_stat(sharepath, &sbuf) == -1) {
+ DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
+ servicename, sharepath, strerror(errno) ));
+ sys_closedir(dp);
+ return USERSHARE_POSIX_ERR;
+ }
+
+ sys_closedir(dp);
+
+ if (!S_ISDIR(sbuf.st_mode)) {
+ DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
+ servicename, sharepath ));
+ return USERSHARE_PATH_NOT_DIRECTORY;
+ }
+
+ /* Check if sharing is restricted to owner-only. */
+ /* psbuf is the stat of the usershare definition file,
+ sbuf is the stat of the target directory to be shared. */
+
+ if (lp_usershare_owner_only()) {
+ /* root can share anything. */
+ if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
+ return USERSHARE_PATH_NOT_ALLOWED;
+ }
+ }
+
+ return USERSHARE_OK;
+}
+
+/***************************************************************************
+ Deal with a usershare file.
+ Returns:
+ >= 0 - snum
+ -1 - Bad name, invalid contents.
+ - service name already existed and not a usershare, problem
+ with permissions to share directory etc.
+***************************************************************************/
+
+static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
+{
+ SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_STAT lsbuf;
+ pstring fname;
+ pstring sharepath;
+ pstring comment;
+ fstring service_name;
+ char **lines = NULL;
+ int numlines = 0;
+ int fd = -1;
+ int iService = -1;
+ TALLOC_CTX *ctx = NULL;
+ SEC_DESC *psd = NULL;
+
+ /* Ensure share name doesn't contain invalid characters. */
+ if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
+ DEBUG(0,("process_usershare_file: share name %s contains "
+ "invalid characters (any of %s)\n",
+ file_name, INVALID_SHARENAME_CHARS ));
+ return -1;
+ }
+
+ fstrcpy(service_name, file_name);
+
+ pstrcpy(fname, dir_name);
+ pstrcat(fname, "/");
+ pstrcat(fname, file_name);
+
+ /* Minimize the race condition by doing an lstat before we
+ open and fstat. Ensure this isn't a symlink link. */
+
+ if (sys_lstat(fname, &lsbuf) != 0) {
+ DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
+ fname, strerror(errno) ));
+ return -1;
+ }
+
+ /* This must be a regular file, not a symlink, directory or
+ other strange filetype. */
+ if (!check_usershare_stat(fname, &lsbuf)) {
+ return -1;
+ }
+
+ /* See if there is already a servicenum for this name. */
+ /* tdb_fetch_int32 returns -1 if not found. */
+ iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
+
+ if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
+ /* Nothing changed - Mark valid and return. */
+ DEBUG(10,("process_usershare_file: service %s not changed.\n",
+ service_name ));
+ ServicePtrs[iService]->usershare = USERSHARE_VALID;
+ return iService;
+ }
+
+ /* Try and open the file read only - no symlinks allowed. */
+#ifdef O_NOFOLLOW
+ fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
+#else
+ fd = sys_open(fname, O_RDONLY, 0);
+#endif
+
+ if (fd == -1) {
+ DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
+ fname, strerror(errno) ));
+ return -1;
+ }
+
+ /* Now fstat to be *SURE* it's a regular file. */
+ if (sys_fstat(fd, &sbuf) != 0) {
+ close(fd);
+ DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
+ fname, strerror(errno) ));
+ return -1;
+ }
+
+ /* Is it the same dev/inode as was lstated ? */
+ if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
+ close(fd);
+ DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
+ "Symlink spoofing going on ?\n", fname ));
+ return -1;
+ }
+
+ /* This must be a regular file, not a symlink, directory or
+ other strange filetype. */
+ if (!check_usershare_stat(fname, &sbuf)) {
+ return -1;
+ }
+
+ lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
+
+ close(fd);
+ if (lines == NULL) {
+ DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
+ fname, (unsigned int)sbuf.st_uid ));
+ return -1;
+ }
+
+ /* Should we allow printers to be shared... ? */
+ ctx = talloc_init("usershare_sd_xctx");
+ if (!ctx) {
+ SAFE_FREE(lines);
+ return 1;
+ }
+
+ if (parse_usershare_file(ctx, &sbuf, service_name, iService, lines, numlines, sharepath, comment, &psd) != USERSHARE_OK) {
+ talloc_destroy(ctx);
+ SAFE_FREE(lines);
+ return -1;
+ }
+
+ SAFE_FREE(lines);
+
+ /* Everything ok - add the service possibly using a template. */
+ if (iService < 0) {
+ const service *sp = &sDefault;
+ if (snum_template != -1) {
+ sp = ServicePtrs[snum_template];
+ }
+
+ if ((iService = add_a_service(sp, service_name)) < 0) {
+ DEBUG(0, ("process_usershare_file: Failed to add "
+ "new service %s\n", service_name));
+ talloc_destroy(ctx);
+ return -1;
+ }
+
+ /* Read only is controlled by usershare ACL below. */
+ ServicePtrs[iService]->bRead_only = False;
+ }
+
+ /* Write the ACL of the new/modified share. */
+ if (!set_share_security(ctx, service_name, psd)) {
+ DEBUG(0, ("process_usershare_file: Failed to set share "
+ "security for user share %s\n",
+ service_name ));
+ lp_remove_service(iService);
+ talloc_destroy(ctx);
+ return -1;
+ }
+
+ talloc_destroy(ctx);
+
+ /* If from a template it may be marked invalid. */
+ ServicePtrs[iService]->valid = True;
+
+ /* Set the service as a valid usershare. */
+ ServicePtrs[iService]->usershare = USERSHARE_VALID;
+
+ /* And note when it was loaded. */
+ ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
+ string_set(&ServicePtrs[iService]->szPath, sharepath);
+ string_set(&ServicePtrs[iService]->comment, comment);
+
+ return iService;
+}
+
+/***************************************************************************
+ Checks if a usershare entry has been modified since last load.
+***************************************************************************/
+
+static BOOL usershare_exists(int iService, time_t *last_mod)
+{
+ SMB_STRUCT_STAT lsbuf;
+ const char *usersharepath = Globals.szUsersharePath;
+ pstring fname;
+
+ pstrcpy(fname, usersharepath);
+ pstrcat(fname, "/");
+ pstrcat(fname, ServicePtrs[iService]->szService);
+
+ if (sys_lstat(fname, &lsbuf) != 0) {
+ return False;
+ }
+
+ if (!S_ISREG(lsbuf.st_mode)) {
+ return False;
+ }
+
+ *last_mod = lsbuf.st_mtime;
+ return True;
+}
+
+/***************************************************************************
+ Load a usershare service by name. Returns a valid servicenumber or -1.
+***************************************************************************/
+
+int load_usershare_service(const char *servicename)
+{
+ SMB_STRUCT_STAT sbuf;
+ const char *usersharepath = Globals.szUsersharePath;
+ int max_user_shares = Globals.iUsershareMaxShares;
+ int snum_template = -1;
+
+ if (*usersharepath == 0 || max_user_shares == 0) {
+ return -1;
+ }
+
+ if (sys_stat(usersharepath, &sbuf) != 0) {
+ DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
+ usersharepath, strerror(errno) ));
+ return -1;
+ }
+
+ if (!S_ISDIR(sbuf.st_mode)) {
+ DEBUG(0,("load_usershare_service: %s is not a directory.\n",
+ usersharepath ));
+ return -1;
+ }
+
+ /*
+ * This directory must be owned by root, and have the 't' bit set.
+ * It also must not be writable by "other".
+ */
+
+#ifdef S_ISVTX
+ if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+#else
+ if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+#endif
+ DEBUG(0,("load_usershare_service: directory %s is not owned by root "
+ "or does not have the sticky bit 't' set or is writable by anyone.\n",
+ usersharepath ));
+ return -1;
+ }
+
+ /* Ensure the template share exists if it's set. */
+ if (Globals.szUsershareTemplateShare[0]) {
+ /* We can't use lp_servicenumber here as we are recommending that
+ template shares have -valid=False set. */
+ for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
+ if (ServicePtrs[snum_template]->szService &&
+ strequal(ServicePtrs[snum_template]->szService,
+ Globals.szUsershareTemplateShare)) {
+ break;
+ }
+ }
+
+ if (snum_template == -1) {
+ DEBUG(0,("load_usershare_service: usershare template share %s "
+ "does not exist.\n",
+ Globals.szUsershareTemplateShare ));
+ return -1;
+ }
+ }
+
+ return process_usershare_file(usersharepath, servicename, snum_template);
+}
+
+/***************************************************************************
+ Load all user defined shares from the user share directory.
+ We only do this if we're enumerating the share list.
+ This is the function that can delete usershares that have
+ been removed.
+***************************************************************************/
+
+int load_usershare_shares(void)
+{
+ SMB_STRUCT_DIR *dp;
+ SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_DIRENT *de;
+ int num_usershares = 0;
+ int max_user_shares = Globals.iUsershareMaxShares;
+ unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
+ unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
+ unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
+ int iService;
+ int snum_template = -1;
+ const char *usersharepath = Globals.szUsersharePath;
+ int ret = lp_numservices();
+
+ if (max_user_shares == 0 || *usersharepath == '\0') {
+ return lp_numservices();
+ }
+
+ if (sys_stat(usersharepath, &sbuf) != 0) {
+ DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
+ usersharepath, strerror(errno) ));
+ return ret;
+ }
+
+ /*
+ * This directory must be owned by root, and have the 't' bit set.
+ * It also must not be writable by "other".
+ */
+
+#ifdef S_ISVTX
+ if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+#else
+ if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+#endif
+ DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
+ "or does not have the sticky bit 't' set or is writable by anyone.\n",
+ usersharepath ));
+ return ret;
+ }
+
+ /* Ensure the template share exists if it's set. */
+ if (Globals.szUsershareTemplateShare[0]) {
+ /* We can't use lp_servicenumber here as we are recommending that
+ template shares have -valid=False set. */
+ for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
+ if (ServicePtrs[snum_template]->szService &&
+ strequal(ServicePtrs[snum_template]->szService,
+ Globals.szUsershareTemplateShare)) {
+ break;
+ }
+ }
+
+ if (snum_template == -1) {
+ DEBUG(0,("load_usershare_shares: usershare template share %s "
+ "does not exist.\n",
+ Globals.szUsershareTemplateShare ));
+ return ret;
+ }
+ }
+
+ /* Mark all existing usershares as pending delete. */
+ for (iService = iNumServices - 1; iService >= 0; iService--) {
+ if (VALID(iService) && ServicePtrs[iService]->usershare) {
+ ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
+ }
+ }
+
+ dp = sys_opendir(usersharepath);
+ if (!dp) {
+ DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
+ usersharepath, strerror(errno) ));
+ return ret;
+ }
+
+ for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
+ (de = sys_readdir(dp));
+ num_dir_entries++ ) {
+ int r;
+ const char *n = de->d_name;
+
+ /* Ignore . and .. */
+ if (*n == '.') {
+ if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
+ continue;
+ }
+ }
+
+ if (n[0] == ':') {
+ /* Temporary file used when creating a share. */
+ num_tmp_dir_entries++;
+ }
+
+ /* Allow 20% tmp entries. */
+ if (num_tmp_dir_entries > allowed_tmp_entries) {
+ DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
+ "in directory %s\n",
+ num_tmp_dir_entries, usersharepath));
+ break;
+ }
+
+ r = process_usershare_file(usersharepath, n, snum_template);
+ if (r == 0) {
+ /* Update the services count. */
+ num_usershares++;
+ if (num_usershares >= max_user_shares) {
+ DEBUG(0,("load_usershare_shares: max user shares reached "
+ "on file %s in directory %s\n",
+ n, usersharepath ));
+ break;
+ }
+ } else if (r == -1) {
+ num_bad_dir_entries++;
+ }
+
+ /* Allow 20% bad entries. */
+ if (num_bad_dir_entries > allowed_bad_entries) {
+ DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
+ "in directory %s\n",
+ num_bad_dir_entries, usersharepath));
+ break;
+ }
+
+ /* Allow 20% bad entries. */
+ if (num_dir_entries > max_user_shares + allowed_bad_entries) {
+ DEBUG(0,("load_usershare_shares: too many total entries (%u) "
+ "in directory %s\n",
+ num_dir_entries, usersharepath));
+ break;
+ }
+ }
+
+ sys_closedir(dp);
+
+ /* Sweep through and delete any non-refreshed usershares that are
+ not currently in use. */
+ for (iService = iNumServices - 1; iService >= 0; iService--) {
+ if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
+ if (conn_snum_used(iService)) {
+ continue;
+ }
+ /* Remove from the share ACL db. */
+ DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
+ lp_servicename(iService) ));
+ delete_share_security(iService);
+ free_service_byindex(iService);
+ }
+ }
+
+ return lp_numservices();
+}
+
+/********************************************************
+ Destroy global resources allocated in this file
+********************************************************/
+
+void gfree_loadparm(void)
+{
+ struct file_lists *f;
+ struct file_lists *next;
+ int i;
+
+ lp_TALLOC_FREE();
+
+ /* Free the file lists */
+
+ f = file_lists;
+ while( f ) {
+ next = f->next;
+ SAFE_FREE( f->name );
+ SAFE_FREE( f->subfname );
+ SAFE_FREE( f );
+ f = next;
+ }
+
+ /* Free resources allocated to services */
+
+ for ( i = 0; i < iNumServices; i++ ) {
+ if ( VALID(i) ) {
+ free_service_byindex(i);
+ }
+ }
+
+ SAFE_FREE( ServicePtrs );
+ iNumServices = 0;
+
+ /* Now release all resources allocated to global
+ parameters and the default service */
+
+ for (i = 0; parm_table[i].label; i++)
+ {
+ if ( parm_table[i].type == P_STRING
+ || parm_table[i].type == P_USTRING )
+ {
+ string_free( (char**)parm_table[i].ptr );
+ }
+ else if (parm_table[i].type == P_LIST) {
+ str_list_free( (char***)parm_table[i].ptr );
+ }
+ }
+}
+
+/***************************************************************************
Load the services array from the services file. Return True on success,
False on failure.
***************************************************************************/
-BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
- BOOL add_ipc)
+BOOL lp_load(const char *pszFname,
+ BOOL global_only,
+ BOOL save_defaults,
+ BOOL add_ipc,
+ BOOL initialize_globals)
{
pstring n2;
BOOL bRetval;
@@ -4201,7 +4943,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
bInGlobalSection = True;
bGlobalOnly = global_only;
- init_globals();
+ init_globals(! initialize_globals);
debug_init();
if (save_defaults) {
@@ -4323,8 +5065,9 @@ int lp_servicenumber(const char *pszServiceName)
int iService;
fstring serviceName;
- if (!pszServiceName)
+ if (!pszServiceName) {
return GLOBAL_SECTION_SNUM;
+ }
for (iService = iNumServices - 1; iService >= 0; iService--) {
if (VALID(iService) && ServicePtrs[iService]->szService) {
@@ -4334,8 +5077,30 @@ int lp_servicenumber(const char *pszServiceName)
*/
fstrcpy(serviceName, ServicePtrs[iService]->szService);
standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName));
- if (strequal(serviceName, pszServiceName))
+ if (strequal(serviceName, pszServiceName)) {
break;
+ }
+ }
+ }
+
+ if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
+ time_t last_mod;
+
+ if (!usershare_exists(iService, &last_mod)) {
+ /* Remove the share security tdb entry for it. */
+ delete_share_security(iService);
+ /* Remove it from the array. */
+ free_service_byindex(iService);
+ /* Doesn't exist anymore. */
+ return GLOBAL_SECTION_SNUM;
+ }
+
+ /* Has it been modified ? If so delete and reload. */
+ if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
+ /* Remove it from the array. */
+ free_service_byindex(iService);
+ /* and now reload it. */
+ iService = load_usershare_service(pszServiceName);
}
}
@@ -4549,15 +5314,6 @@ const char *lp_printername(int snum)
}
-/****************************************************************
- Compatibility fn. for 2.2.2 code.....
-*****************************************************************/
-
-void get_private_directory(pstring privdir)
-{
- pstrcpy (privdir, lp_private_dir());
-}
-
/***********************************************************
Allow daemons such as winbindd to fix their logfile name.
************************************************************/
@@ -4688,3 +5444,22 @@ void lp_set_posix_pathnames(void)
{
posix_pathnames = True;
}
+
+/*******************************************************************
+ Global state for POSIX lock processing - CIFS unix extensions.
+********************************************************************/
+
+static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
+
+enum brl_flavour lp_posix_cifsu_locktype(void)
+{
+ return posix_cifsx_locktype;
+}
+
+/*******************************************************************
+********************************************************************/
+
+void lp_set_posix_cifsx_locktype(enum brl_flavour val)
+{
+ posix_cifsx_locktype = val;
+}
diff --git a/source/param/params.c b/source/param/params.c
index 2a6c8b3e650..6669e80191d 100644
--- a/source/param/params.c
+++ b/source/param/params.c
@@ -262,10 +262,8 @@ static BOOL Section( myFILE *InFile, BOOL (*sfunc)(const char *) )
while( (EOF != c) && (c > 0) ) {
/* Check that the buffer is big enough for the next character. */
if( i > (bSize - 2) ) {
- char *tb;
-
- tb = (char *)SMB_REALLOC( bufr, bSize +BUFR_INC );
- if( NULL == tb ) {
+ char *tb = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR( bufr, bSize +BUFR_INC );
+ if(!tb) {
DEBUG(0, ("%s Memory re-allocation failure.", func) );
return False;
}
@@ -356,8 +354,8 @@ static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *)
/* Loop until we've found the start of the value. */
if( i > (bSize - 2) ) {
/* Ensure there's space for next char. */
- char *tb = (char *)SMB_REALLOC( bufr, bSize + BUFR_INC );
- if( NULL == tb ) {
+ char *tb = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR( bufr, bSize + BUFR_INC );
+ if (!tb) {
DEBUG(0, ("%s Memory re-allocation failure.", func) );
return False;
}
@@ -414,8 +412,8 @@ static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *)
while( (EOF !=c) && (c > 0) ) {
if( i > (bSize - 2) ) {
/* Make sure there's enough room. */
- char *tb = (char *)SMB_REALLOC( bufr, bSize + BUFR_INC );
- if( NULL == tb ) {
+ char *tb = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR( bufr, bSize + BUFR_INC );
+ if (!tb) {
DEBUG(0, ("%s Memory re-allocation failure.", func));
return False;
}
@@ -532,7 +530,7 @@ static myFILE *OpenConfFile( const char *FileName )
if (!ret)
return NULL;
- ret->buf = file_load(FileName, &ret->size);
+ ret->buf = file_load(FileName, &ret->size, 0);
if( NULL == ret->buf ) {
DEBUG( lvl, ("%s Unable to open configuration file \"%s\":\n\t%s\n",
func, FileName, strerror(errno)) );
diff --git a/source/passdb/login_cache.c b/source/passdb/login_cache.c
index d82cfcc5601..fba5990d811 100644
--- a/source/passdb/login_cache.c
+++ b/source/passdb/login_cache.c
@@ -1,6 +1,6 @@
/*
Unix SMB/CIFS implementation.
- SAM_ACCOUNT local cache for
+ struct samu local cache for
Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2004.
This program is free software; you can redistribute it and/or modify
@@ -64,7 +64,7 @@ BOOL login_cache_shutdown(void)
}
/* if we can't read the cache, oh well, no need to return anything */
-LOGIN_CACHE * login_cache_read(SAM_ACCOUNT *sampass)
+LOGIN_CACHE * login_cache_read(struct samu *sampass)
{
TDB_DATA keybuf, databuf;
LOGIN_CACHE *entry;
@@ -108,7 +108,7 @@ LOGIN_CACHE * login_cache_read(SAM_ACCOUNT *sampass)
return entry;
}
-BOOL login_cache_write(const SAM_ACCOUNT *sampass, LOGIN_CACHE entry)
+BOOL login_cache_write(const struct samu *sampass, LOGIN_CACHE entry)
{
TDB_DATA keybuf, databuf;
@@ -155,7 +155,7 @@ BOOL login_cache_write(const SAM_ACCOUNT *sampass, LOGIN_CACHE entry)
return ret == 0;
}
-BOOL login_cache_delentry(const SAM_ACCOUNT *sampass)
+BOOL login_cache_delentry(const struct samu *sampass)
{
int ret;
TDB_DATA keybuf;
diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c
index b397e084c33..942d2771782 100644
--- a/source/passdb/lookup_sid.c
+++ b/source/passdb/lookup_sid.c
@@ -3,6 +3,7 @@
uid/user handling
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Gerald (Jerry) Carter 2003
+ 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
@@ -22,129 +23,804 @@
#include "includes.h"
/*****************************************************************
- *THE CANONICAL* convert name to SID function.
- Tries local lookup first - for local domains - then uses winbind.
+ Dissect a user-provided name into domain, name, sid and type.
+
+ If an explicit domain name was given in the form domain\user, it
+ has to try that. If no explicit domain name was given, we have
+ to do guesswork.
*****************************************************************/
-BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
+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)
{
- fstring sid;
- BOOL local_lookup = False;
-
- *name_type = SID_NAME_UNKNOWN;
+ char *p;
+ const char *tmp;
+ const char *domain = NULL;
+ const char *name = NULL;
+ uint32 rid;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+
+ if (tmp_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ p = strchr_m(full_name, '\\');
+
+ if (p != NULL) {
+ domain = talloc_strndup(tmp_ctx, full_name,
+ PTR_DIFF(p, full_name));
+ name = talloc_strdup(tmp_ctx, p+1);
+ } else {
+ domain = talloc_strdup(tmp_ctx, "");
+ name = talloc_strdup(tmp_ctx, full_name);
+ }
+
+ if ((domain == NULL) || (name == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ return False;
+ }
- /* If we are looking up a domain user, make sure it is
- for the local machine only */
-
if (strequal(domain, get_global_sam_name())) {
- if (local_lookup_name(name, psid, name_type)) {
- DEBUG(10,
- ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
- domain, name, sid_to_string(sid,psid),
- sid_type_lookup(*name_type), (unsigned int)*name_type));
- return True;
+
+ /* It's our own domain, lookup the name in passdb */
+ if (lookup_global_sam_name(name, flags, &rid, &type)) {
+ sid_copy(&sid, get_global_sam_sid());
+ sid_append_rid(&sid, rid);
+ goto ok;
}
- } else {
- /* Remote */
- if (winbind_lookup_name(domain, name, psid, name_type)) {
-
- DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n",
- domain, name, sid_to_string(sid, psid),
- (unsigned int)*name_type));
- return True;
+ goto failed;
+ }
+
+ if (strequal(domain, builtin_domain_name())) {
+
+ /* Explicit request for a name in BUILTIN */
+ if (lookup_builtin_name(name, &rid)) {
+ sid_copy(&sid, &global_sid_Builtin);
+ sid_append_rid(&sid, rid);
+ type = SID_NAME_ALIAS;
+ goto ok;
}
+ goto failed;
}
-
- DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n",
- local_lookup ? "local" : "winbind", domain, name));
+ /* Try the explicit winbind lookup first, don't let it guess the
+ * domain yet at this point yet. This comes later. */
+
+ if ((domain[0] != '\0') &&
+ (winbind_lookup_name(domain, name, &sid, &type))) {
+ goto ok;
+ }
+
+ if (strequal(domain, unix_users_domain_name())) {
+ if (lookup_unix_user_name(name, &sid)) {
+ type = SID_NAME_USER;
+ goto ok;
+ }
+ goto failed;
+ }
+
+ if (strequal(domain, unix_groups_domain_name())) {
+ if (lookup_unix_group_name(name, &sid)) {
+ type = SID_NAME_DOM_GRP;
+ goto ok;
+ }
+ goto failed;
+ }
+
+ if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
+ goto failed;
+ }
+
+ /*
+ * Nasty hack necessary for too common scenarios:
+ *
+ * For 'valid users = +users' we know "users" is most probably not
+ * BUILTIN\users but the unix group users. This hack requires the
+ * admin to explicitly qualify BUILTIN if BUILTIN\users is meant.
+ *
+ * Please note that LOOKUP_NAME_GROUP can not be requested via for
+ * example lsa_lookupnames, it only comes into this routine via
+ * the expansion of group names coming in from smb.conf
+ */
+
+ if ((flags & LOOKUP_NAME_GROUP) &&
+ (lookup_unix_group_name(name, &sid))) {
+ domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
+ type = SID_NAME_DOM_GRP;
+ goto ok;
+ }
+
+ /* Now the guesswork begins, we haven't been given an explicit
+ * domain. Try the sequence as documented on
+ * http://msdn.microsoft.com/library/en-us/secmgmt/security/lsalookupnames.asp
+ * November 27, 2005 */
+
+ /* 1. well-known names */
+
+ if (lookup_wellknown_name(tmp_ctx, name, &sid, &domain)) {
+ type = SID_NAME_WKN_GRP;
+ goto ok;
+ }
+
+ /* 2. Builtin domain as such */
+
+ if (strequal(name, builtin_domain_name())) {
+ /* Swap domain and name */
+ tmp = name; name = domain; domain = tmp;
+ sid_copy(&sid, &global_sid_Builtin);
+ type = SID_NAME_DOMAIN;
+ goto ok;
+ }
+
+ /* 3. Account domain */
+
+ if (strequal(name, get_global_sam_name())) {
+ if (!secrets_fetch_domain_sid(name, &sid)) {
+ DEBUG(3, ("Could not fetch my SID\n"));
+ goto failed;
+ }
+ /* Swap domain and name */
+ tmp = name; name = domain; domain = tmp;
+ type = SID_NAME_DOMAIN;
+ goto ok;
+ }
+
+ /* 4. Primary domain */
+
+ 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;
+ }
+ /* Swap domain and name */
+ tmp = name; name = domain; domain = tmp;
+ type = SID_NAME_DOMAIN;
+ goto ok;
+ }
+
+ /* 5. Trusted domains as such, to me it looks as if members don't do
+ this, tested an XP workstation in a NT domain -- vl */
+
+ if (IS_DC && (secrets_fetch_trusted_domain_password(name, NULL,
+ &sid, NULL))) {
+ /* Swap domain and name */
+ tmp = name; name = domain; domain = tmp;
+ type = SID_NAME_DOMAIN;
+ goto ok;
+ }
+
+ /* 6. Builtin aliases */
+
+ if (lookup_builtin_name(name, &rid)) {
+ domain = talloc_strdup(tmp_ctx, builtin_domain_name());
+ sid_copy(&sid, &global_sid_Builtin);
+ sid_append_rid(&sid, rid);
+ type = SID_NAME_ALIAS;
+ goto ok;
+ }
+
+ /* 7. Local systems' SAM (DCs don't have a local SAM) */
+ /* 8. Primary SAM (On members, this is the domain) */
+
+ /* Both cases are done by looking at our passdb */
+
+ if (lookup_global_sam_name(name, flags, &rid, &type)) {
+ domain = talloc_strdup(tmp_ctx, get_global_sam_name());
+ sid_copy(&sid, get_global_sam_sid());
+ sid_append_rid(&sid, rid);
+ goto ok;
+ }
+
+ /* Now our local possibilities are exhausted. */
+
+ if (!(flags & LOOKUP_NAME_REMOTE)) {
+ goto failed;
+ }
+
+ /* If we are not a DC, we have to ask in our primary domain. Let
+ * winbind do that. */
+
+ if (!IS_DC &&
+ (winbind_lookup_name(lp_workgroup(), name, &sid, &type))) {
+ domain = talloc_strdup(tmp_ctx, lp_workgroup());
+ goto ok;
+ }
+
+ /* 9. Trusted domains */
+
+ /* If we're a DC we have to ask all trusted DC's. Winbind does not do
+ * that (yet), but give it a chance. */
+
+ if (IS_DC && winbind_lookup_name("", name, &sid, &type)) {
+ DOM_SID dom_sid;
+ uint32 tmp_rid;
+ enum SID_NAME_USE domain_type;
+
+ if (type == SID_NAME_DOMAIN) {
+ /* Swap name and type */
+ tmp = name; name = domain; domain = tmp;
+ goto ok;
+ }
+
+ /* Here we have to cope with a little deficiency in the
+ * winbind API: We have to ask it again for the name of the
+ * domain it figured out itself. Maybe fix that later... */
+
+ sid_copy(&dom_sid, &sid);
+ sid_split_rid(&dom_sid, &tmp_rid);
+
+ if (!winbind_lookup_sid(tmp_ctx, &dom_sid, &domain, NULL,
+ &domain_type) ||
+ (domain_type != SID_NAME_DOMAIN)) {
+ DEBUG(2, ("winbind could not find the domain's name "
+ "it just looked up for us\n"));
+ goto failed;
+ }
+ goto ok;
+ }
+
+ /* 10. Don't translate */
+
+ /* 11. Ok, windows would end here. Samba has two more options:
+ Unmapped users and unmapped groups */
+
+ if (lookup_unix_user_name(name, &sid)) {
+ domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
+ type = SID_NAME_USER;
+ goto ok;
+ }
+
+ if (lookup_unix_group_name(name, &sid)) {
+ domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
+ type = SID_NAME_DOM_GRP;
+ goto ok;
+ }
+
+ failed:
+ TALLOC_FREE(tmp_ctx);
return False;
+
+ ok:
+ if ((domain == NULL) || (name == NULL)) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(tmp_ctx);
+ return False;
+ }
+
+ if (ret_name != NULL) {
+ *ret_name = talloc_steal(mem_ctx, name);
+ }
+
+ if (ret_domain != NULL) {
+ char *tmp_dom = talloc_strdup(tmp_ctx, domain);
+ strupper_m(tmp_dom);
+ *ret_domain = talloc_steal(mem_ctx, tmp_dom);
+ }
+
+ if (ret_sid != NULL) {
+ sid_copy(ret_sid, &sid);
+ }
+
+ if (ret_type != NULL) {
+ *ret_type = type;
+ }
+
+ TALLOC_FREE(tmp_ctx);
+ return True;
}
-/*****************************************************************
- *THE CANONICAL* convert SID to name function.
- Tries local lookup first - for local sids, then tries winbind.
-*****************************************************************/
+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)
+{
+ /* 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;
+
+ sid_copy(&sid, domain_sid);
+ sid_append_rid(&sid, rids[i]);
+
+ 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 {
+ types[i] = SID_NAME_UNKNOWN;
+ }
+ }
+ return True;
+}
-BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name,
- enum SID_NAME_USE *name_type)
+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)
{
- if (!name_type)
+ int i;
+
+ *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
+
+ if ((*names == NULL) || (*types == NULL)) {
return False;
+ }
- *name_type = SID_NAME_UNKNOWN;
+ if (sid_check_is_domain(domain_sid)) {
+ NTSTATUS result;
- /* Check if this is our own sid. This should perhaps be done by
- winbind? For the moment handle it here. */
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, get_global_sam_name());
+ }
- if (sid_check_is_domain(sid)) {
- fstrcpy(dom_name, get_global_sam_name());
- fstrcpy(name, "");
- *name_type = SID_NAME_DOMAIN;
+ if (*domain_name == NULL) {
+ return False;
+ }
+
+ become_root();
+ result = pdb_lookup_rids(domain_sid, num_rids, rids,
+ *names, *types);
+ unbecome_root();
+
+ return (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
+ NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
+ }
+
+ if (sid_check_is_builtin(domain_sid)) {
+
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, builtin_domain_name());
+ }
+
+ if (*domain_name == NULL) {
+ return False;
+ }
+
+ for (i=0; i<num_rids; i++) {
+ if (lookup_builtin_rid(*names, rids[i],
+ &(*names)[i])) {
+ if ((*names)[i] == NULL) {
+ return False;
+ }
+ (*types)[i] = SID_NAME_ALIAS;
+ } else {
+ (*types)[i] = SID_NAME_UNKNOWN;
+ }
+ }
return True;
}
- if (sid_check_is_in_our_domain(sid)) {
- uint32 rid;
- SMB_ASSERT(sid_peek_rid(sid, &rid));
+ if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
+ for (i=0; i<num_rids; i++) {
+ DOM_SID sid;
+ sid_copy(&sid, domain_sid);
+ sid_append_rid(&sid, rids[i]);
+ if (lookup_wellknown_sid(mem_ctx, &sid,
+ domain_name, &(*names)[i])) {
+ if ((*names)[i] == NULL) {
+ return False;
+ }
+ (*types)[i] = SID_NAME_WKN_GRP;
+ } else {
+ (*types)[i] = SID_NAME_UNKNOWN;
+ }
+ }
+ return True;
+ }
+
+ if (sid_check_is_unix_users(domain_sid)) {
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, unix_users_domain_name());
+ }
+ for (i=0; i<num_rids; i++) {
+ (*names)[i] = talloc_strdup(
+ (*names), uidtoname(rids[i]));
+ (*types)[i] = SID_NAME_USER;
+ }
+ return True;
+ }
- /* For our own domain passdb is responsible */
- fstrcpy(dom_name, get_global_sam_name());
- return lookup_global_sam_rid(rid, name, name_type);
+ if (sid_check_is_unix_groups(domain_sid)) {
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, unix_groups_domain_name());
+ }
+ for (i=0; i<num_rids; i++) {
+ (*names)[i] = talloc_strdup(
+ (*names), gidtoname(rids[i]));
+ (*types)[i] = SID_NAME_DOM_GRP;
+ }
+ return True;
}
- if (sid_check_is_builtin(sid)) {
+ return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
+ domain_name, *names, *types);
+}
- /* Got through map_domain_sid_to_name here so that the mapping
- * of S-1-5-32 to the name "BUILTIN" in as few places as
- * possible. We might add i18n... */
- SMB_ASSERT(map_domain_sid_to_name(sid, dom_name));
+/*
+ * Is the SID a domain as such? If yes, lookup its name.
+ */
- /* Yes, W2k3 returns "BUILTIN" both as domain and name here */
- fstrcpy(name, dom_name);
+static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
+ const char **name)
+{
+ const char *tmp;
+ enum SID_NAME_USE type;
- *name_type = SID_NAME_DOMAIN;
+ if (sid_check_is_domain(sid)) {
+ *name = talloc_strdup(mem_ctx, get_global_sam_name());
return True;
}
- if (sid_check_is_in_builtin(sid)) {
- uint32 rid;
+ if (sid_check_is_builtin(sid)) {
+ *name = talloc_strdup(mem_ctx, builtin_domain_name());
+ return True;
+ }
- SMB_ASSERT(sid_peek_rid(sid, &rid));
+ if (sid_check_is_wellknown_domain(sid, &tmp)) {
+ *name = talloc_strdup(mem_ctx, tmp);
+ return True;
+ }
- /* Got through map_domain_sid_to_name here so that the mapping
- * of S-1-5-32 to the name "BUILTIN" in as few places as
- * possible. We might add i18n... */
- SMB_ASSERT(map_domain_sid_to_name(&global_sid_Builtin,
- dom_name));
+ if (sid->num_auths != 4) {
+ /* This can't be a domain */
+ return False;
+ }
- /* There's only aliases in S-1-5-32 */
- *name_type = SID_NAME_ALIAS;
+ if (IS_DC) {
+ uint32 i, num_domains;
+ struct trustdom_info **domains;
- return lookup_builtin_rid(rid, name);
+ /* This is relatively expensive, but it happens only on DCs
+ * and for SIDs that have 4 sub-authorities and thus look like
+ * domains */
+
+ if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
+ &num_domains,
+ &domains))) {
+ return False;
+ }
+
+ for (i=0; i<num_domains; i++) {
+ if (sid_equal(sid, &domains[i]->sid)) {
+ *name = talloc_strdup(mem_ctx,
+ domains[i]->name);
+ return True;
+ }
+ }
+ return False;
}
- if (winbind_lookup_sid(sid, dom_name, name, name_type)) {
+ if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
+ (type == SID_NAME_DOMAIN)) {
+ *name = tmp;
return True;
}
- DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying "
- "special SIDs.\n", sid_string_static(sid)));
+ return False;
+}
- {
- const char *dom, *obj_name;
-
- if (lookup_special_sid(sid, &dom, &obj_name, name_type)) {
- DEBUG(10, ("found %s\\%s\n", dom, obj_name));
- fstrcpy(dom_name, dom);
- fstrcpy(name, obj_name);
- return True;
+/*
+ * This tries to implement the rather weird rules for the lsa_lookup level
+ * parameter.
+ *
+ * This is as close as we can get to what W2k3 does. With this we survive the
+ * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
+ * different, but I assume that's just being too liberal. For example, W2k3
+ * replies to everything else but the levels 1-6 with INVALID_PARAMETER
+ * whereas NT4 does the same as level 1 (I think). I did not fully test that
+ * with NT4, this is what w2k3 does.
+ *
+ * Level 1: Ask everywhere
+ * Level 2: Ask domain and trusted domains, no builtin and wkn
+ * Level 3: Only ask domain
+ * Level 4: W2k3ad: Only ask AD trusts
+ * Level 5: Don't lookup anything
+ * Level 6: Like 4
+ */
+
+static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
+{
+ int ret = False;
+
+ switch(level) {
+ case 1:
+ ret = True;
+ break;
+ case 2:
+ ret = (!sid_check_is_builtin(sid) &&
+ !sid_check_is_wellknown_domain(sid, NULL));
+ break;
+ case 3:
+ case 4:
+ case 6:
+ ret = sid_check_is_domain(sid);
+ break;
+ case 5:
+ ret = False;
+ break;
+ }
+
+ DEBUG(10, ("%s SID %s in level %d\n",
+ ret ? "Accepting" : "Rejecting",
+ sid_string_static(sid), level));
+ return ret;
+}
+
+/*
+ * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
+ * references to domains, it is explicitly made for this.
+ *
+ * This attempts to be as efficient as possible: It collects all SIDs
+ * belonging to a domain and hands them in bulk to the appropriate lookup
+ * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
+ * *hugely* from this. Winbind is going to be extended with a lookup_rids
+ * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
+ * appropriate DC.
+ */
+
+NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
+ const DOM_SID **sids, int level,
+ struct lsa_dom_info **ret_domains,
+ struct lsa_name_info **ret_names)
+{
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_name_info *name_infos;
+ struct lsa_dom_info *dom_infos;
+
+ int i, j;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ 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,
+ MAX_REF_DOMAINS);
+ if ((name_infos == NULL) || (dom_infos == NULL)) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ /* First build up the data structures:
+ *
+ * dom_infos is a list of domains referenced in the list of
+ * SIDs. Later we will walk the list of domains and look up the RIDs
+ * in bulk.
+ *
+ * name_infos is a shadow-copy of the SIDs array to collect the real
+ * data.
+ *
+ * dom_info->idxs is an index into the name_infos array. The
+ * difficulty we have here is that we need to keep the SIDs the client
+ * asked for in the same order for the reply
+ */
+
+ for (i=0; i<num_sids; i++) {
+ DOM_SID sid;
+ uint32 rid;
+ const char *domain_name = NULL;
+
+ sid_copy(&sid, sids[i]);
+ name_infos[i].type = SID_NAME_USE_NONE;
+
+ if (lookup_as_domain(&sid, name_infos, &domain_name)) {
+ /* We can't push that through the normal lookup
+ * process, as this would reference illegal
+ * domains.
+ *
+ * For example S-1-5-32 would end up referencing
+ * domain S-1-5- with RID 32 which is clearly wrong.
+ */
+ if (domain_name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ name_infos[i].rid = 0;
+ name_infos[i].type = SID_NAME_DOMAIN;
+ name_infos[i].name = NULL;
+
+ if (sid_check_is_builtin(&sid)) {
+ /* Yes, W2k3 returns "BUILTIN" both as domain
+ * and name here */
+ name_infos[i].name = talloc_strdup(
+ name_infos, builtin_domain_name());
+ if (name_infos[i].name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+ } else {
+ /* This is a normal SID with rid component */
+ if (!sid_split_rid(&sid, &rid)) {
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ }
+
+ if (!check_dom_sid_to_level(&sid, level)) {
+ name_infos[i].rid = 0;
+ name_infos[i].type = SID_NAME_UNKNOWN;
+ name_infos[i].name = NULL;
+ continue;
+ }
+
+ for (j=0; j<MAX_REF_DOMAINS; j++) {
+ if (!dom_infos[j].valid) {
+ break;
+ }
+ if (sid_equal(&sid, &dom_infos[j].sid)) {
+ break;
+ }
+ }
+
+ if (j == MAX_REF_DOMAINS) {
+ /* TODO: What's the right error message here? */
+ result = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ if (!dom_infos[j].valid) {
+ /* We found a domain not yet referenced, create a new
+ * ref. */
+ dom_infos[j].valid = True;
+ sid_copy(&dom_infos[j].sid, &sid);
+
+ if (domain_name != NULL) {
+ /* 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);
+ } else {
+ /* lookup_rids will take care of this */
+ dom_infos[j].name = NULL;
+ }
+ }
+
+ name_infos[i].dom_idx = j;
+
+ if (name_infos[i].type == SID_NAME_USE_NONE) {
+ name_infos[i].rid = rid;
+
+ ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
+ &dom_infos[j].num_idxs);
+
+ if (dom_infos[j].idxs == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
}
- DEBUG(10, ("lookup_sid failed\n"));
+ /* Iterate over the domains found */
- return False;
+ for (i=0; i<MAX_REF_DOMAINS; i++) {
+ uint32_t *rids;
+ const char **names;
+ enum SID_NAME_USE *types;
+ struct lsa_dom_info *dom = &dom_infos[i];
+
+ if (!dom->valid) {
+ /* No domains left, we're done */
+ break;
+ }
+
+ rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
+
+ if (rids == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (j=0; j<dom->num_idxs; j++) {
+ rids[j] = name_infos[dom->idxs[j]].rid;
+ }
+
+ if (!lookup_rids(tmp_ctx, &dom->sid,
+ dom->num_idxs, rids, &dom->name,
+ &names, &types)) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ talloc_steal(dom_infos, dom->name);
+
+ 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]);
+ } 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;
+
+ done:
+ TALLOC_FREE(tmp_ctx);
+ return result;
+}
+
+/*****************************************************************
+ *THE CANONICAL* convert SID to name function.
+*****************************************************************/
+
+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)
+{
+ 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) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
+ &domain, &name))) {
+ goto done;
+ }
+
+ if (name->type == SID_NAME_UNKNOWN) {
+ goto done;
+ }
+
+ if (ret_domain != NULL) {
+ *ret_domain = talloc_steal(mem_ctx, domain->name);
+ }
+
+ if (ret_name != NULL) {
+ *ret_name = talloc_steal(mem_ctx, name->name);
+ }
+
+ if (ret_type != NULL) {
+ *ret_type = name->type;
+ }
+
+ ret = True;
+
+ done:
+ if (ret) {
+ DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
+ sid_string_static(sid), domain->name,
+ name->name, name->type));
+ } else {
+ DEBUG(10, ("failed to lookup sid %s\n",
+ sid_string_static(sid)));
+ }
+ TALLOC_FREE(tmp_ctx);
+ return ret;
}
/*****************************************************************
@@ -187,10 +863,9 @@ static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
for (pc = uid_sid_cache_head; pc; pc = pc->next) {
if (pc->uid == uid) {
- fstring sid;
*psid = pc->sid;
DEBUG(3,("fetch sid from uid cache %u -> %s\n",
- (unsigned int)uid, sid_to_string(sid, psid)));
+ (unsigned int)uid, sid_string_static(psid)));
DLIST_PROMOTE(uid_sid_cache_head, pc);
return True;
}
@@ -208,10 +883,9 @@ static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
for (pc = uid_sid_cache_head; pc; pc = pc->next) {
if (sid_compare(&pc->sid, psid) == 0) {
- fstring sid;
*puid = pc->uid;
DEBUG(3,("fetch uid from cache %u -> %s\n",
- (unsigned int)*puid, sid_to_string(sid, psid)));
+ (unsigned int)*puid, sid_string_static(psid)));
DLIST_PROMOTE(uid_sid_cache_head, pc);
return True;
}
@@ -223,7 +897,7 @@ static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
Store uid to SID mapping in cache.
*****************************************************************/
-static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
+void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
{
struct uid_sid_cache *pc;
@@ -261,10 +935,9 @@ static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
for (pc = gid_sid_cache_head; pc; pc = pc->next) {
if (pc->gid == gid) {
- fstring sid;
*psid = pc->sid;
DEBUG(3,("fetch sid from gid cache %u -> %s\n",
- (unsigned int)gid, sid_to_string(sid, psid)));
+ (unsigned int)gid, sid_string_static(psid)));
DLIST_PROMOTE(gid_sid_cache_head, pc);
return True;
}
@@ -282,10 +955,9 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
for (pc = gid_sid_cache_head; pc; pc = pc->next) {
if (sid_compare(&pc->sid, psid) == 0) {
- fstring sid;
*pgid = pc->gid;
DEBUG(3,("fetch gid from cache %u -> %s\n",
- (unsigned int)*pgid, sid_to_string(sid, psid)));
+ (unsigned int)*pgid, sid_string_static(psid)));
DLIST_PROMOTE(gid_sid_cache_head, pc);
return True;
}
@@ -297,7 +969,7 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
Store gid to SID mapping in cache.
*****************************************************************/
-static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
+void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
{
struct gid_sid_cache *pc;
@@ -329,201 +1001,259 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
*THE CANONICAL* convert uid_t to SID function.
*****************************************************************/
-NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
+void uid_to_sid(DOM_SID *psid, uid_t uid)
{
- fstring sid;
uid_t low, high;
+ uint32 rid;
ZERO_STRUCTP(psid);
if (fetch_sid_from_uid_cache(psid, uid))
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
-
- /* DC's never use winbindd to resolve users outside the
- defined idmap range */
+ return;
- if ( lp_server_role()==ROLE_DOMAIN_MEMBER
- || (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) )
- {
- if (winbind_uid_to_sid(psid, uid)) {
+ if (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_to_string(sid, psid)));
+ DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
+ (unsigned int)uid, sid_string_static(psid)));
+ goto done;
+ }
- if (psid)
- store_uid_sid_cache(psid, uid);
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
- }
+ if (pdb_uid_to_rid(uid, &rid)) {
+ /* This is a mapped user */
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, rid);
+ goto done;
}
- if (!local_uid_to_sid(psid, uid)) {
- DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid ));
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
+ goto done;
+ } else {
+ sid_copy(psid, &global_sid_Unix_Users);
+ sid_append_rid(psid, uid);
+ goto done;
}
-
- DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid)));
+
+ done:
+ DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
+ sid_string_static(psid)));
store_uid_sid_cache(psid, uid);
- return NT_STATUS_OK;
+ return;
}
/*****************************************************************
*THE CANONICAL* convert gid_t to SID function.
*****************************************************************/
-NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
+void gid_to_sid(DOM_SID *psid, gid_t gid)
{
- fstring sid;
gid_t low, high;
ZERO_STRUCTP(psid);
if (fetch_sid_from_gid_cache(psid, gid))
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+ return;
- /* DC's never use winbindd to resolve groups outside the
- defined idmap range */
+ if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
+ winbind_gid_to_sid(psid, gid)) {
- if ( lp_server_role()==ROLE_DOMAIN_MEMBER
- || (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) )
- {
- if (winbind_gid_to_sid(psid, gid)) {
+ DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
+ (unsigned int)gid, sid_string_static(psid)));
+ goto done;
+ }
- DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
- (unsigned int)gid, sid_to_string(sid, psid)));
-
- if (psid)
- store_gid_sid_cache(psid, gid);
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
- }
+ if (pdb_gid_to_sid(gid, psid)) {
+ /* This is a mapped group */
+ goto done;
}
- if (!local_gid_to_sid(psid, gid)) {
- DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid ));
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, pdb_gid_to_group_rid(gid));
+ goto done;
+ } else {
+ sid_copy(psid, &global_sid_Unix_Groups);
+ sid_append_rid(psid, gid);
+ goto done;
}
-
- DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid)));
+
+ done:
+ DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
+ sid_string_static(psid)));
store_gid_sid_cache(psid, gid);
- return NT_STATUS_OK;
+ return;
}
/*****************************************************************
*THE CANONICAL* convert SID to uid function.
*****************************************************************/
-NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
+BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
{
- fstring dom_name, name, sid_str;
- enum SID_NAME_USE name_type;
+ enum SID_NAME_USE type;
+ uint32 rid;
+ gid_t gid;
if (fetch_uid_from_cache(puid, psid))
- return NT_STATUS_OK;
+ return True;
- /* if this is our SID then go straight to a local lookup */
-
- if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
- DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
- sid_string_static(psid) ));
-
- if ( local_sid_to_uid(puid, psid, &name_type) )
- goto success;
-
- DEBUG(10,("sid_to_uid: local lookup failed\n"));
-
- return NT_STATUS_UNSUCCESSFUL;
+ if (fetch_gid_from_cache(&gid, psid)) {
+ return False;
}
-
- /* If it is not our local domain, only hope is winbindd */
- if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) {
- DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n",
- sid_string_static(psid) ));
-
- return NT_STATUS_UNSUCCESSFUL;
+ if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
+ uid_t uid = rid;
+ *puid = uid;
+ goto done;
}
- /* If winbindd does know the SID, ensure this is a user */
+ if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+ union unid_t id;
+
+ if (pdb_sid_to_id(psid, &id, &type)) {
+ if (type != SID_NAME_USER) {
+ DEBUG(5, ("sid %s is a %s, expected a user\n",
+ sid_string_static(psid),
+ sid_type_lookup(type)));
+ return False;
+ }
+ *puid = id.uid;
+ goto done;
+ }
+ if (pdb_rid_algorithm() &&
+ algorithmic_pdb_rid_is_user(rid)) {
+ *puid = algorithmic_pdb_user_rid_to_uid(rid);
+ goto done;
+ }
- if (name_type != SID_NAME_USER) {
- DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n",
- (unsigned int)name_type ));
- return NT_STATUS_INVALID_PARAMETER;
+ /* This was ours, but it was neither mapped nor
+ * algorithmic. Fail */
+ return False;
}
- /* get the uid. Has to work or else we are dead in the water */
+ 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(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
- sid_to_string(sid_str, psid) ));
- return NT_STATUS_UNSUCCESSFUL;
+ 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;
}
-success:
- DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid),
+ /* TODO: Here would be the place to allocate both a gid and a uid for
+ * the SID in question */
+
+ return False;
+
+ done:
+ DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
(unsigned int)*puid ));
store_uid_sid_cache(psid, *puid);
-
- return NT_STATUS_OK;
+ return True;
}
+
/*****************************************************************
*THE CANONICAL* convert SID to gid function.
Group mapping is used for gids that maps to Wellknown SIDs
*****************************************************************/
-NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
{
- fstring dom_name, name, sid_str;
- enum SID_NAME_USE name_type;
+ 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 NT_STATUS_OK;
+ return True;
- /*
- * First we must look up the name and decide if this is a group sid.
- * Group mapping can deal with foreign SIDs
- */
+ if (fetch_uid_from_cache(&uid, psid))
+ return False;
+
+ if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
+ gid_t gid = rid;
+ *pgid = gid;
+ goto done;
+ }
+
+ if ((sid_check_is_in_builtin(psid) ||
+ sid_check_is_in_wellknown_domain(psid))) {
+ if (pdb_getgrsid(&map, *psid)) {
+ *pgid = map.gid;
+ goto done;
+ }
+ return False;
+ }
- if ( local_sid_to_gid(pgid, psid, &name_type) )
- goto success;
+ if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+ if (pdb_sid_to_id(psid, &id, &type)) {
+ if ((type != SID_NAME_DOM_GRP) &&
+ (type != SID_NAME_ALIAS)) {
+ DEBUG(5, ("sid %s is a %s, expected a group\n",
+ sid_string_static(psid),
+ sid_type_lookup(type)));
+ return False;
+ }
+ *pgid = id.gid;
+ goto done;
+ }
+ if (pdb_rid_algorithm() &&
+ !algorithmic_pdb_rid_is_user(rid)) {
+ /* This must be a group, presented as alias */
+ *pgid = pdb_group_rid_to_gid(rid);
+ goto done;
+ }
+ /* This was ours, but it was neither mapped nor
+ * algorithmic. Fail. */
+ return False;
+ }
- if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
- DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then winbind)\n", sid_to_string(sid_str, psid)));
+ 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)));
- return NT_STATUS_UNSUCCESSFUL;
+ return False;
}
/* winbindd knows it; Ensure this is a group sid */
- if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS)
- && (name_type != SID_NAME_WKN_GRP))
- {
- DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
- (unsigned int)name_type ));
-
- /* winbindd is running and knows about this SID. Just the wrong type.
- Don't fallback to a local lookup here */
-
- return NT_STATUS_INVALID_PARAMETER;
+ 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)));
+ return False;
}
/* winbindd knows it and it is a type of group; sid_to_gid must succeed
or we are dead in the water */
if ( !winbind_sid_to_gid(pgid, psid) ) {
- DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid for sid %s\n",
- sid_to_string(sid_str, psid) ));
- return NT_STATUS_UNSUCCESSFUL;
+ DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
+ "for sid %s\n", sid_string_static(psid)));
+ return False;
}
-success:
- DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid),
- (unsigned int)*pgid ));
+ done:
+ DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
+ (unsigned int)*pgid ));
store_gid_sid_cache(psid, *pgid);
- return NT_STATUS_OK;
+ return True;
}
diff --git a/source/passdb/machine_sid.c b/source/passdb/machine_sid.c
index 87ec27d34ea..d7cae06749c 100644
--- a/source/passdb/machine_sid.c
+++ b/source/passdb/machine_sid.c
@@ -35,13 +35,14 @@ static DOM_SID *global_sam_sid=NULL;
Read a SID from a file. This is for compatibility with the old MACHINE.SID
style of SID storage
****************************************************************************/
+
static BOOL read_sid_from_file(const char *fname, DOM_SID *sid)
{
char **lines;
int numlines;
BOOL ret;
- lines = file_lines_load(fname, &numlines);
+ lines = file_lines_load(fname, &numlines,0);
if (!lines || numlines < 1) {
if (lines) file_lines_free(lines);
@@ -198,3 +199,27 @@ void reset_global_sam_sid(void)
{
SAFE_FREE(global_sam_sid);
}
+
+/*****************************************************************
+ Check if the SID is our domain SID (S-1-5-21-x-y-z).
+*****************************************************************/
+
+BOOL sid_check_is_domain(const DOM_SID *sid)
+{
+ return sid_equal(sid, get_global_sam_sid());
+}
+
+/*****************************************************************
+ Check if the SID is our domain SID (S-1-5-21-x-y-z).
+*****************************************************************/
+
+BOOL sid_check_is_in_our_domain(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_equal(&dom_sid, get_global_sam_sid());
+}
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 2c8ab514f55..876f04bdfe7 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -3,9 +3,10 @@
Password and authentication handling
Copyright (C) Jeremy Allison 1996-2001
Copyright (C) Luke Kenneth Casson Leighton 1996-1998
- Copyright (C) Gerald (Jerry) Carter 2000-2001
+ Copyright (C) Gerald (Jerry) Carter 2000-2006
Copyright (C) Andrew Bartlett 2001-2002
Copyright (C) Simo Sorce 2003
+ 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
@@ -35,7 +36,7 @@
standalone box will map to WKS\user.
******************************************************************/
-const char *get_default_sam_name(void)
+const char *my_sam_name(void)
{
/* standalone servers can only use the local netbios name */
if ( lp_server_role() == ROLE_STANDALONE )
@@ -46,410 +47,204 @@ const char *get_default_sam_name(void)
return lp_workgroup();
}
-/************************************************************
- Fill the SAM_ACCOUNT with default values.
- ***********************************************************/
+/**********************************************************************
+***********************************************************************/
-void pdb_fill_default_sam(SAM_ACCOUNT *user)
+static int samu_destroy(void *p)
{
- ZERO_STRUCT(user->private_u); /* Don't touch the talloc context */
-
- /* no initial methods */
- user->methods = NULL;
-
- /* Don't change these timestamp settings without a good reason.
- They are important for NT member server compatibility. */
-
- user->private_u.logon_time = (time_t)0;
- user->private_u.pass_last_set_time = (time_t)0;
- user->private_u.pass_can_change_time = (time_t)0;
- user->private_u.logoff_time =
- user->private_u.kickoff_time =
- user->private_u.pass_must_change_time = get_time_t_max();
- user->private_u.fields_present = 0x00ffffff;
- user->private_u.logon_divs = 168; /* hours per week */
- user->private_u.hours_len = 21; /* 21 times 8 bits = 168 */
- memset(user->private_u.hours, 0xff, user->private_u.hours_len); /* available at all hours */
- user->private_u.bad_password_count = 0;
- user->private_u.logon_count = 0;
- user->private_u.unknown_6 = 0x000004ec; /* don't know */
-
- /* Some parts of samba strlen their pdb_get...() returns,
- so this keeps the interface unchanged for now. */
-
- user->private_u.username = "";
- user->private_u.domain = "";
- user->private_u.nt_username = "";
- user->private_u.full_name = "";
- user->private_u.home_dir = "";
- user->private_u.logon_script = "";
- user->private_u.profile_path = "";
- user->private_u.acct_desc = "";
- user->private_u.workstations = "";
- user->private_u.unknown_str = "";
- user->private_u.munged_dial = "";
-
- user->private_u.plaintext_pw = NULL;
-
- /*
- Unless we know otherwise have a Account Control Bit
- value of 'normal user'. This helps User Manager, which
- asks for a filtered list of users.
- */
+ struct samu *user = p;
- user->private_u.acct_ctrl = ACB_NORMAL;
-}
+ data_blob_clear_free( &user->lm_pw );
+ data_blob_clear_free( &user->nt_pw );
-static void destroy_pdb_talloc(SAM_ACCOUNT **user)
-{
- if (*user) {
- data_blob_clear_free(&((*user)->private_u.lm_pw));
- data_blob_clear_free(&((*user)->private_u.nt_pw));
+ if ( user->plaintext_pw )
+ memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
- if((*user)->private_u.plaintext_pw!=NULL)
- memset((*user)->private_u.plaintext_pw,'\0',strlen((*user)->private_u.plaintext_pw));
- talloc_destroy((*user)->mem_ctx);
- *user = NULL;
- }
+ return 0;
}
-
/**********************************************************************
- Allocates memory and initialises a struct sam_passwd on supplied mem_ctx.
+ generate a new struct samuser
***********************************************************************/
-NTSTATUS pdb_init_sam_talloc(TALLOC_CTX *mem_ctx, SAM_ACCOUNT **user)
+struct samu* samu_new( TALLOC_CTX *ctx )
{
- if (*user != NULL) {
- DEBUG(0,("pdb_init_sam_talloc: SAM_ACCOUNT was non NULL\n"));
-#if 0
- smb_panic("non-NULL pointer passed to pdb_init_sam\n");
-#endif
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!mem_ctx) {
- DEBUG(0,("pdb_init_sam_talloc: mem_ctx was NULL!\n"));
- return NT_STATUS_UNSUCCESSFUL;
+ struct samu *user;
+
+ if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
+ DEBUG(0,("samuser_new: Talloc failed!\n"));
+ return NULL;
}
+
+ talloc_set_destructor( user, samu_destroy );
+
+ /* no initial methods */
+
+ user->methods = NULL;
- *user=TALLOC_P(mem_ctx, SAM_ACCOUNT);
-
- if (*user==NULL) {
- DEBUG(0,("pdb_init_sam_talloc: error while allocating memory\n"));
- return NT_STATUS_NO_MEMORY;
- }
+ /* Don't change these timestamp settings without a good reason.
+ They are important for NT member server compatibility. */
- (*user)->mem_ctx = mem_ctx;
+ user->logon_time = (time_t)0;
+ user->pass_last_set_time = (time_t)0;
+ user->pass_can_change_time = (time_t)0;
+ user->logoff_time = get_time_t_max();
+ user->kickoff_time = get_time_t_max();
+ user->pass_must_change_time = get_time_t_max();
+ user->fields_present = 0x00ffffff;
+ user->logon_divs = 168; /* hours per week */
+ user->hours_len = 21; /* 21 times 8 bits = 168 */
+ memset(user->hours, 0xff, user->hours_len); /* available at all hours */
+ user->bad_password_count = 0;
+ user->logon_count = 0;
+ user->unknown_6 = 0x000004ec; /* don't know */
- (*user)->free_fn = NULL;
+ /* Some parts of samba strlen their pdb_get...() returns,
+ so this keeps the interface unchanged for now. */
+
+ user->username = "";
+ user->domain = "";
+ user->nt_username = "";
+ user->full_name = "";
+ user->home_dir = "";
+ user->logon_script = "";
+ user->profile_path = "";
+ user->acct_desc = "";
+ user->workstations = "";
+ user->unknown_str = "";
+ user->munged_dial = "";
+
+ user->plaintext_pw = NULL;
+
+ /* Unless we know otherwise have a Account Control Bit
+ value of 'normal user'. This helps User Manager, which
+ asks for a filtered list of users. */
- pdb_fill_default_sam(*user);
+ user->acct_ctrl = ACB_NORMAL;
- return NT_STATUS_OK;
+
+ return user;
}
+/*********************************************************************
+ Initialize a struct samu from a struct passwd including the user
+ and group SIDs. The *user structure is filled out with the Unix
+ attributes and a user SID.
+*********************************************************************/
-/*************************************************************
- Allocates memory and initialises a struct sam_passwd.
- ************************************************************/
-
-NTSTATUS pdb_init_sam(SAM_ACCOUNT **user)
+static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, BOOL create)
{
- TALLOC_CTX *mem_ctx;
- NTSTATUS nt_status;
-
- mem_ctx = talloc_init("passdb internal SAM_ACCOUNT allocation");
+ const char *guest_account = lp_guestaccount();
+ const char *domain = global_myname();
+ uint32 urid;
- if (!mem_ctx) {
- DEBUG(0,("pdb_init_sam: error while doing talloc_init()\n"));
- return NT_STATUS_NO_MEMORY;
+ if ( !pwd ) {
+ return NT_STATUS_NO_SUCH_USER;
}
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, user))) {
- talloc_destroy(mem_ctx);
- return nt_status;
- }
+ /* Basic properties based upon the Unix account information */
- (*user)->free_fn = destroy_pdb_talloc;
-
- return NT_STATUS_OK;
-}
-
-/**************************************************************************
- * This function will take care of all the steps needed to correctly
- * allocate and set the user SID, please do use this function to create new
- * users, messing with SIDs is not good.
- *
- * account_data must be provided initialized, pwd may be null.
- * SSS
- ***************************************************************************/
-
-static NTSTATUS pdb_set_sam_sids(SAM_ACCOUNT *account_data, const struct passwd *pwd)
-{
- const char *guest_account = lp_guestaccount();
- GROUP_MAP map;
- BOOL ret;
+ pdb_set_username(user, pwd->pw_name, PDB_SET);
+ pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
+ pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
- if (!account_data || !pwd) {
- return NT_STATUS_INVALID_PARAMETER;
- }
+ /* save the password structure for later use */
+
+ user->unix_pw = tcopy_passwd( user, pwd );
- /* this is a hack this thing should not be set
- this way --SSS */
- if (!(guest_account && *guest_account)) {
- DEBUG(1, ("NULL guest account!?!?\n"));
- return NT_STATUS_UNSUCCESSFUL;
- } else {
- /* Ensure this *must* be set right */
- if (strcmp(pwd->pw_name, guest_account) == 0) {
- if (!pdb_set_user_sid_from_rid(account_data, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- if (!pdb_set_group_sid_from_rid(account_data, DOMAIN_GROUP_RID_GUESTS, PDB_DEFAULT)) {
- return NT_STATUS_UNSUCCESSFUL;
- }
- return NT_STATUS_OK;
+ /* Special case for the guest account which must have a RID of 501 */
+
+ if ( strequal( pwd->pw_name, guest_account ) ) {
+ if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
+ return NT_STATUS_NO_SUCH_USER;
}
+ return NT_STATUS_OK;
}
-
- if (!pdb_set_user_sid_from_rid(account_data, algorithmic_pdb_uid_to_user_rid(pwd->pw_uid), PDB_SET)) {
- DEBUG(0,("Can't set User SID from RID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* call the mapping code here */
- become_root();
- ret = pdb_getgrgid(&map, pwd->pw_gid);
- unbecome_root();
- if( ret ) {
- if (!pdb_set_group_sid(account_data, &map.sid, PDB_SET)){
- DEBUG(0,("Can't set Group SID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
+ /* Non-guest accounts...Check for a workstation or user account */
+
+ if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
+ /* workstation */
+
+ if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
+ DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n",
+ pwd->pw_name));
+ return NT_STATUS_INVALID_COMPUTER_NAME;
+ }
}
else {
- if (!pdb_set_group_sid_from_rid(account_data, pdb_gid_to_group_rid(pwd->pw_gid), PDB_SET)) {
- DEBUG(0,("Can't set Group SID\n"));
- return NT_STATUS_INVALID_PARAMETER;
+ /* user */
+
+ if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
+ DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n",
+ pwd->pw_name));
+ return NT_STATUS_INVALID_ACCOUNT_NAME;
}
+
+ /* set some basic attributes */
+
+ pdb_set_profile_path(user, talloc_sub_specified(user,
+ lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
+ PDB_DEFAULT);
+ pdb_set_homedir(user, talloc_sub_specified(user,
+ lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
+ PDB_DEFAULT);
+ pdb_set_dir_drive(user, talloc_sub_specified(user,
+ lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
+ PDB_DEFAULT);
+ pdb_set_logon_script(user, talloc_sub_specified(user,
+ lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
+ PDB_DEFAULT);
}
-
- return NT_STATUS_OK;
-}
-
-/*************************************************************
- Initialises a struct sam_passwd with sane values.
- ************************************************************/
-
-NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd)
-{
- NTSTATUS ret;
-
- if (!pwd) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- pdb_fill_default_sam(sam_account);
-
- pdb_set_username(sam_account, pwd->pw_name, PDB_SET);
- pdb_set_fullname(sam_account, pwd->pw_gecos, PDB_SET);
-
- pdb_set_unix_homedir(sam_account, pwd->pw_dir, PDB_SET);
-
- pdb_set_domain (sam_account, get_global_sam_name(), PDB_DEFAULT);
- /* When we get a proper uid -> SID and SID -> uid allocation
- mechinism, we should call it here.
-
- We can't just set this to 0 or allow it only to be filled
- in when added to the backend, because the user's SID
- may already be in security descriptors etc.
-
- -- abartlet 11-May-02
- */
-
- ret = pdb_set_sam_sids(sam_account, pwd);
- if (!NT_STATUS_IS_OK(ret)) return ret;
-
- /* check if this is a user account or a machine account */
- if (pwd->pw_name[strlen(pwd->pw_name)-1] != '$')
- {
- pdb_set_profile_path(sam_account,
- talloc_sub_specified((sam_account)->mem_ctx,
- lp_logon_path(),
- pwd->pw_name, global_myname(),
- pwd->pw_uid, pwd->pw_gid),
- PDB_DEFAULT);
-
- pdb_set_homedir(sam_account,
- talloc_sub_specified((sam_account)->mem_ctx,
- lp_logon_home(),
- pwd->pw_name, global_myname(),
- pwd->pw_uid, pwd->pw_gid),
- PDB_DEFAULT);
-
- pdb_set_dir_drive(sam_account,
- talloc_sub_specified((sam_account)->mem_ctx,
- lp_logon_drive(),
- pwd->pw_name, global_myname(),
- pwd->pw_uid, pwd->pw_gid),
- PDB_DEFAULT);
+ /* Now deal with the user SID. If we have a backend that can generate
+ RIDs, then do so. But sometimes the caller just wanted a structure
+ initialized and will fill in these fields later (such as from a
+ NET_USER_INFO_3 structure) */
+
+ if ( create && !pdb_rid_algorithm() ) {
+ uint32 user_rid;
+ DOM_SID user_sid;
- pdb_set_logon_script(sam_account,
- talloc_sub_specified((sam_account)->mem_ctx,
- lp_logon_script(),
- pwd->pw_name, global_myname(),
- pwd->pw_uid, pwd->pw_gid),
- PDB_DEFAULT);
- if (!pdb_set_acct_ctrl(sam_account, ACB_NORMAL, PDB_DEFAULT)) {
- DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n", pwd->pw_name));
- return NT_STATUS_UNSUCCESSFUL;
- }
- } else {
- if (!pdb_set_acct_ctrl(sam_account, ACB_WSTRUST, PDB_DEFAULT)) {
- DEBUG(1, ("Failed to set 'trusted workstation account' flags for user %s.\n", pwd->pw_name));
- return NT_STATUS_UNSUCCESSFUL;
+ if ( !pdb_new_rid( &user_rid ) ) {
+ DEBUG(3, ("Could not allocate a new RID\n"));
+ return NT_STATUS_ACCESS_DENIED;
}
- }
- return NT_STATUS_OK;
-}
-
-
-/*************************************************************
- Initialises a struct sam_passwd with sane values.
- ************************************************************/
-
-NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd)
-{
- NTSTATUS nt_status;
- if (!pwd) {
- new_sam_acct = NULL;
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) {
- new_sam_acct = NULL;
- return nt_status;
- }
+ sid_copy( &user_sid, get_global_sam_sid() );
+ sid_append_rid( &user_sid, user_rid );
- if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*new_sam_acct, pwd))) {
- pdb_free_sam(new_sam_acct);
- new_sam_acct = NULL;
- return nt_status;
+ if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
+ DEBUG(3, ("pdb_set_user_sid failed\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ return NT_STATUS_OK;
}
- return NT_STATUS_OK;
-}
-
-
-/*************************************************************
- Initialises a SAM_ACCOUNT ready to add a new account, based
- on the UNIX user. Pass in a RID if you have one
- ************************************************************/
-
-NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username,
- uint32 rid)
-{
- NTSTATUS nt_status = NT_STATUS_NO_MEMORY;
- struct passwd *pwd;
- BOOL ret;
-
- pwd = Get_Pwnam(username);
-
- if (!pwd)
- return NT_STATUS_NO_SUCH_USER;
+ /* generate a SID for the user with the RID algorithm */
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) {
- *new_sam_acct = NULL;
- return nt_status;
- }
-
- /* see if we need to generate a new rid using the 2.2 algorithm */
- if ( rid == 0 && lp_enable_rid_algorithm() ) {
- DEBUG(10,("pdb_init_sam_new: no RID specified. Generating one via old algorithm\n"));
- rid = algorithmic_pdb_uid_to_user_rid(pwd->pw_uid);
+ urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
+
+ if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
+ return NT_STATUS_INTERNAL_ERROR;
}
- /* set the new SID */
-
- ret = pdb_set_user_sid_from_rid( *new_sam_acct, rid, PDB_SET );
-
- return (ret ? NT_STATUS_OK : NT_STATUS_NO_SUCH_USER);
+ return NT_STATUS_OK;
}
+/********************************************************************
+ Set the Unix user attributes
+********************************************************************/
-/**
- * Free the contets of the SAM_ACCOUNT, but not the structure.
- *
- * Also wipes the LM and NT hashes and plaintext password from
- * memory.
- *
- * @param user SAM_ACCOUNT to free members of.
- **/
-
-static void pdb_free_sam_contents(SAM_ACCOUNT *user)
+NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
{
-
- /* Kill off sensitive data. Free()ed by the
- talloc mechinism */
-
- data_blob_clear_free(&(user->private_u.lm_pw));
- data_blob_clear_free(&(user->private_u.nt_pw));
- if (user->private_u.plaintext_pw!=NULL)
- memset(user->private_u.plaintext_pw,'\0',strlen(user->private_u.plaintext_pw));
-
- if (user->private_u.backend_private_data && user->private_u.backend_private_data_free_fn) {
- user->private_u.backend_private_data_free_fn(&user->private_u.backend_private_data);
- }
+ return samu_set_unix_internal( user, pwd, False );
}
-
-/************************************************************
- Reset the SAM_ACCOUNT and free the NT/LM hashes.
- ***********************************************************/
-
-NTSTATUS pdb_reset_sam(SAM_ACCOUNT *user)
+NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
{
- if (user == NULL) {
- DEBUG(0,("pdb_reset_sam: SAM_ACCOUNT was NULL\n"));
-#if 0
- smb_panic("NULL pointer passed to pdb_free_sam\n");
-#endif
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- pdb_free_sam_contents(user);
-
- pdb_fill_default_sam(user);
-
- return NT_STATUS_OK;
-}
-
-
-/************************************************************
- Free the SAM_ACCOUNT and the member pointers.
- ***********************************************************/
-
-NTSTATUS pdb_free_sam(SAM_ACCOUNT **user)
-{
- if (*user == NULL) {
- DEBUG(0,("pdb_free_sam: SAM_ACCOUNT was NULL\n"));
-#if 0
- smb_panic("NULL pointer passed to pdb_free_sam\n");
-#endif
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- pdb_free_sam_contents(*user);
-
- if ((*user)->free_fn) {
- (*user)->free_fn(user);
- }
-
- return NT_STATUS_OK;
+ return samu_set_unix_internal( user, pwd, True );
}
/**********************************************************
@@ -458,7 +253,7 @@ NTSTATUS pdb_free_sam(SAM_ACCOUNT **user)
null). length *MUST BE MORE THAN 2* !
**********************************************************/
-char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
+char *pdb_encode_acct_ctrl(uint32 acct_ctrl, size_t length)
{
static fstring acct_str;
@@ -494,9 +289,9 @@ char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
Decode the account control bits from a string.
**********************************************************/
-uint16 pdb_decode_acct_ctrl(const char *p)
+uint32 pdb_decode_acct_ctrl(const char *p)
{
- uint16 acct_ctrl = 0;
+ uint32 acct_ctrl = 0;
BOOL finished = False;
/*
@@ -536,7 +331,7 @@ uint16 pdb_decode_acct_ctrl(const char *p)
Routine to set 32 hex password characters from a 16 byte array.
**************************************************************/
-void pdb_sethexpwd(char *p, const unsigned char *pwd, uint16 acct_ctrl)
+void pdb_sethexpwd(char *p, const unsigned char *pwd, uint32 acct_ctrl)
{
if (pwd != NULL) {
int i;
@@ -634,6 +429,9 @@ BOOL pdb_gethexhours(const char *p, unsigned char *hours)
return (True);
}
+/********************************************************************
+********************************************************************/
+
int algorithmic_rid_base(void)
{
static int rid_offset = 0;
@@ -666,6 +464,11 @@ uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
}
+uid_t max_algorithmic_uid(void)
+{
+ return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
+}
+
/*******************************************************************
converts UNIX uid to an NT User RID.
********************************************************************/
@@ -686,6 +489,11 @@ gid_t pdb_group_rid_to_gid(uint32 group_rid)
return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
}
+gid_t max_algorithmic_gid(void)
+{
+ return pdb_group_rid_to_gid(0xffffffff);
+}
+
/*******************************************************************
converts NT Group RID to a UNIX uid.
@@ -704,7 +512,7 @@ uint32 pdb_gid_to_group_rid(gid_t gid)
Decides if a RID is a well known RID.
********************************************************************/
-static BOOL pdb_rid_is_well_known(uint32 rid)
+static BOOL rid_is_well_known(uint32 rid)
{
/* Not using rid_offset here, because this is the actual
NT fixed value (1000) */
@@ -718,7 +526,7 @@ static BOOL pdb_rid_is_well_known(uint32 rid)
BOOL algorithmic_pdb_rid_is_user(uint32 rid)
{
- if(pdb_rid_is_well_known(rid)) {
+ if ( rid_is_well_known(rid) ) {
/*
* The only well known user RIDs are DOMAIN_USER_RID_ADMIN
* and DOMAIN_USER_RID_GUEST.
@@ -732,215 +540,85 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid)
}
/*******************************************************************
- Look up a rid in the SAM we're responsible for (i.e. passdb)
+ Convert a name into a SID. Used in the lookup name rpc.
********************************************************************/
-BOOL lookup_global_sam_rid(uint32 rid, fstring name,
- enum SID_NAME_USE *psid_name_use)
+BOOL lookup_global_sam_name(const char *user, int flags, uint32_t *rid,
+ enum SID_NAME_USE *type)
{
- SAM_ACCOUNT *sam_account = NULL;
GROUP_MAP map;
BOOL ret;
- DOM_SID sid;
-
- *psid_name_use = SID_NAME_UNKNOWN;
- DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n",
- (unsigned int)rid));
-
- sid_copy(&sid, get_global_sam_sid());
- sid_append_rid(&sid, rid);
-
- /* see if the passdb can help us with the name of the user */
- if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
- return False;
- }
-
- /* BEING ROOT BLLOCK */
- become_root();
- if (pdb_getsampwsid(sam_account, &sid)) {
- unbecome_root(); /* -----> EXIT BECOME_ROOT() */
- fstrcpy(name, pdb_get_username(sam_account));
- *psid_name_use = SID_NAME_USER;
-
- pdb_free_sam(&sam_account);
-
+ /* Windows treats "MACHINE\None" as a special name for
+ rid 513 on non-DCs. You cannot create a user or group
+ name "None" on Windows. You will get an error that
+ the group already exists. */
+
+ if ( strequal( user, "None" ) ) {
+ *rid = DOMAIN_GROUP_RID_USERS;
+ *type = SID_NAME_DOM_GRP;
+
return True;
}
- pdb_free_sam(&sam_account);
-
- ret = pdb_getgrsid(&map, sid);
- unbecome_root();
- /* END BECOME_ROOT BLOCK */
-
- if ( ret ) {
- if (map.gid!=(gid_t)-1) {
- DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
- "gid %u\n", map.nt_name,
- (unsigned int)map.gid));
- } else {
- DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
- "no unix gid. Returning name.\n",
- map.nt_name));
- }
- fstrcpy(name, map.nt_name);
- *psid_name_use = map.sid_name_use;
- return True;
- }
+ /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
+ * correctly in the case where foo also exists as a user. If the flag
+ * is set, don't look for users at all. */
- if (rid == DOMAIN_USER_RID_ADMIN) {
- *psid_name_use = SID_NAME_USER;
- fstrcpy(name, "Administrator");
- return True;
- }
+ if ((flags & LOOKUP_NAME_GROUP) == 0) {
+ struct samu *sam_account = NULL;
+ DOM_SID user_sid;
- if (algorithmic_pdb_rid_is_user(rid)) {
- uid_t uid;
- struct passwd *pw = NULL;
-
- DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid));
+ if ( !(sam_account = samu_new( NULL )) ) {
+ return False;
+ }
+
+ become_root();
+ ret = pdb_getsampwnam(sam_account, user);
+ unbecome_root();
- uid = algorithmic_pdb_user_rid_to_uid(rid);
- pw = sys_getpwuid( uid );
-
- DEBUG(5,("lookup_global_sam_rid: looking up uid %u %s\n",
- (unsigned int)uid, pw ? "succeeded" : "failed" ));
-
- if ( !pw )
- fstr_sprintf(name, "unix_user.%u", (unsigned int)uid);
- else
- fstrcpy( name, pw->pw_name );
-
- DEBUG(5,("lookup_global_sam_rid: found user %s for rid %u\n",
- name, (unsigned int)rid ));
-
- *psid_name_use = SID_NAME_USER;
-
- return ( pw != NULL );
- } else {
- gid_t gid;
- struct group *gr;
-
- DEBUG(5, ("assuming RID %u is a group\n", (unsigned)rid));
-
- gid = pdb_group_rid_to_gid(rid);
- gr = getgrgid(gid);
-
- DEBUG(5,("lookup_global_sam_rid: looking up gid %u %s\n",
- (unsigned int)gid, gr ? "succeeded" : "failed" ));
-
- if( !gr )
- fstr_sprintf(name, "unix_group.%u", (unsigned int)gid);
- else
- fstrcpy( name, gr->gr_name);
-
- DEBUG(5,("lookup_global_sam_rid: found group %s for rid %u\n",
- name, (unsigned int)rid ));
-
- /* assume algorithmic groups are domain global groups */
-
- *psid_name_use = SID_NAME_DOM_GRP;
+ if (ret) {
+ sid_copy(&user_sid, pdb_get_user_sid(sam_account));
+ }
- return ( gr != NULL );
- }
-}
-
-/*******************************************************************
- Convert a name into a SID. Used in the lookup name rpc.
- ********************************************************************/
+ TALLOC_FREE(sam_account);
-BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use)
-{
- DOM_SID local_sid;
- DOM_SID sid;
- fstring user;
- SAM_ACCOUNT *sam_account = NULL;
- struct group *grp;
- GROUP_MAP map;
+ if (ret) {
+ if (!sid_check_is_in_our_domain(&user_sid)) {
+ DEBUG(0, ("User %s with invalid SID %s in passdb\n",
+ user, sid_string_static(&user_sid)));
+ return False;
+ }
- *psid_name_use = SID_NAME_UNKNOWN;
+ sid_peek_rid(&user_sid, rid);
+ *type = SID_NAME_USER;
+ return True;
+ }
+ }
/*
- * user may be quoted a const string, and map_username and
- * friends can modify it. Make a modifiable copy. JRA.
+ * Maybe it is a group ?
*/
- fstrcpy(user, c_user);
-
- sid_copy(&local_sid, get_global_sam_sid());
-
- if (map_name_to_wellknown_sid(&sid, psid_name_use, user)){
- fstring sid_str;
- sid_copy( psid, &sid);
- sid_to_string(sid_str, &sid);
- DEBUG(10,("lookup_name: name %s = SID %s, type = %u\n", user, sid_str,
- (unsigned int)*psid_name_use ));
- return True;
- }
-
- (void)map_username(user);
+ become_root();
+ ret = pdb_getgrnam(&map, user);
+ unbecome_root();
- if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
+ if (!ret) {
return False;
}
-
- /* BEGIN ROOT BLOCK */
-
- become_root();
- if (pdb_getsampwnam(sam_account, user)) {
- unbecome_root();
- sid_copy(psid, pdb_get_user_sid(sam_account));
- *psid_name_use = SID_NAME_USER;
-
- pdb_free_sam(&sam_account);
- return True;
- }
-
- pdb_free_sam(&sam_account);
-
- /*
- * Maybe it was a group ?
- */
- /* check if it's a mapped group */
- if (pdb_getgrnam(&map, user)) {
- /* yes it's a mapped group */
- sid_copy(&local_sid, &map.sid);
- *psid_name_use = map.sid_name_use;
- } else {
- /* it's not a mapped group */
- grp = getgrnam(user);
- if(!grp) {
- unbecome_root(); /* ---> exit form block */
- return False;
- }
-
- /*
- *check if it's mapped, if it is reply it doesn't exist
- *
- * that's to prevent this case:
- *
- * unix group ug is mapped to nt group ng
- * someone does a lookup on ug
- * we must not reply as it doesn't "exist" anymore
- * for NT. For NT only ng exists.
- * JFM, 30/11/2001
- */
-
- if (pdb_getgrgid(&map, grp->gr_gid)){
- unbecome_root(); /* ---> exit form block */
- return False;
- }
-
- sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
- *psid_name_use = SID_NAME_ALIAS;
+ /* BUILTIN groups are looked up elsewhere */
+ if (!sid_check_is_in_our_domain(&map.sid)) {
+ DEBUG(10, ("Found group %s (%s) not in our domain -- "
+ "ignoring.", user,
+ sid_string_static(&map.sid)));
+ return False;
}
- unbecome_root();
- /* END ROOT BLOCK */
-
- sid_copy( psid, &local_sid);
+ /* yes it's a mapped group */
+ sid_peek_rid(&map.sid, rid);
+ *type = map.sid_name_use;
return True;
}
@@ -948,34 +626,67 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi
Change a password entry in the local smbpasswd file.
*************************************************************/
-BOOL local_password_change(const char *user_name, int local_flags,
+NTSTATUS local_password_change(const char *user_name, int local_flags,
const char *new_passwd,
char *err_str, size_t err_str_len,
char *msg_str, size_t msg_str_len)
{
- SAM_ACCOUNT *sam_pass=NULL;
- uint16 other_acb;
+ struct samu *sam_pass=NULL;
+ uint32 other_acb;
+ NTSTATUS result;
*err_str = '\0';
*msg_str = '\0';
/* Get the smb passwd entry for this user */
- pdb_init_sam(&sam_pass);
+
+ if ( !(sam_pass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
become_root();
if(!pdb_getsampwnam(sam_pass, user_name)) {
unbecome_root();
- pdb_free_sam(&sam_pass);
+ TALLOC_FREE(sam_pass);
if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
- /* Might not exist in /etc/passwd. Use rid algorithm here */
- if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) {
- slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s. Does this user exist in the UNIX password database ?\n", user_name);
- return False;
+ int tmp_debug = DEBUGLEVEL;
+ struct passwd *pwd;
+
+ /* Might not exist in /etc/passwd. */
+
+ if (tmp_debug < 1) {
+ DEBUGLEVEL = 1;
+ }
+
+ if ( !(pwd = getpwnam_alloc( NULL, user_name)) ) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ /* create the struct samu and initialize the basic Unix properties */
+
+ if ( !(sam_pass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ result = samu_set_unix( sam_pass, pwd );
+
+ DEBUGLEVEL = tmp_debug;
+
+ TALLOC_FREE( pwd );
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
+ return result;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ slprintf(err_str, err_str_len-1, "Failed to " "initialize account for user %s: %s\n",
+ user_name, nt_errstr(result));
+ return result;
}
} else {
slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
- return False;
+ return NT_STATUS_NO_SUCH_USER;
}
} else {
unbecome_root();
@@ -988,20 +699,20 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (local_flags & LOCAL_TRUST_ACCOUNT) {
if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
} else {
if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -1013,22 +724,22 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (local_flags & LOCAL_DISABLE_USER) {
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_ENABLE_USER) {
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
}
if (local_flags & LOCAL_SET_NO_PASSWORD) {
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_SET_PASSWORD) {
/*
@@ -1043,45 +754,46 @@ BOOL local_password_change(const char *user_name, int local_flags,
if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
}
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
}
if (local_flags & LOCAL_ADD_USER) {
- if (pdb_add_sam_account(sam_pass)) {
+ if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return True;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_OK;
} else {
slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_DELETE_USER) {
- if (!pdb_delete_sam_account(sam_pass)) {
+ if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_UNSUCCESSFUL;
}
slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
} else {
- if(!pdb_update_sam_account(sam_pass)) {
+ result = pdb_update_sam_account(sam_pass);
+ if(!NT_STATUS_IS_OK(result)) {
slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
- pdb_free_sam(&sam_pass);
- return False;
+ TALLOC_FREE(sam_pass);
+ return result;
}
if(local_flags & LOCAL_DISABLE_USER)
slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
@@ -1091,627 +803,20 @@ BOOL local_password_change(const char *user_name, int local_flags,
slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
}
- pdb_free_sam(&sam_pass);
- return True;
-}
-
-/****************************************************************************
- Convert a uid to SID - algorithmic.
-****************************************************************************/
-
-DOM_SID *algorithmic_uid_to_sid(DOM_SID *psid, uid_t uid)
-{
- if ( !lp_enable_rid_algorithm() )
- return NULL;
-
- DEBUG(8,("algorithmic_uid_to_sid: falling back to RID algorithm\n"));
- sid_copy( psid, get_global_sam_sid() );
- sid_append_rid( psid, algorithmic_pdb_uid_to_user_rid(uid) );
- DEBUG(10,("algorithmic_uid_to_sid: uid (%d) -> SID %s.\n",
- (unsigned int)uid, sid_string_static(psid) ));
-
- return psid;
-}
-
-/****************************************************************************
- Convert a uid to SID - locally.
-****************************************************************************/
-
-DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
-{
- SAM_ACCOUNT *sampw = NULL;
- struct passwd *unix_pw;
- BOOL ret;
-
- unix_pw = sys_getpwuid( uid );
-
- if ( !unix_pw ) {
- DEBUG(4,("local_uid_to_sid: host has no idea of uid %lu\n", (unsigned long)uid));
- return algorithmic_uid_to_sid( psid, uid);
- }
-
- if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
- DEBUG(0,("local_uid_to_sid: failed to allocate SAM_ACCOUNT object\n"));
- return NULL;
- }
-
- become_root();
- ret = pdb_getsampwnam( sampw, unix_pw->pw_name );
- unbecome_root();
-
- if ( ret )
- sid_copy( psid, pdb_get_user_sid(sampw) );
- else {
- DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n",
- unix_pw->pw_name, (unsigned long)uid));
-
- algorithmic_uid_to_sid( psid, uid);
- }
-
- pdb_free_sam(&sampw);
-
- DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n",
- (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name));
-
- return psid;
-}
-
-/****************************************************************************
- Convert a SID to uid - locally.
-****************************************************************************/
-
-BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
- SAM_ACCOUNT *sampw = NULL;
- struct passwd *unix_pw;
- const char *user_name;
-
- *name_type = SID_NAME_UNKNOWN;
-
- /*
- * We can only convert to a uid if this is our local
- * Domain SID (ie. we are the controling authority).
- */
- if (!sid_check_is_in_our_domain(psid) ) {
- DEBUG(5,("local_sid_to_uid: this SID (%s) is not from our domain\n", sid_string_static(psid)));
- return False;
- }
-
- /* lookup the user account */
-
- if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
- DEBUG(0,("local_sid_to_uid: Failed to allocate memory for SAM_ACCOUNT object\n"));
- return False;
- }
-
- become_root();
- if ( !pdb_getsampwsid(sampw, psid) ) {
- unbecome_root();
- pdb_free_sam(&sampw);
- DEBUG(8,("local_sid_to_uid: Could not find SID %s in passdb\n",
- sid_string_static(psid)));
- return False;
- }
- unbecome_root();
-
- user_name = pdb_get_username(sampw);
-
- unix_pw = sys_getpwnam( user_name );
-
- if ( !unix_pw ) {
- DEBUG(0,("local_sid_to_uid: %s found in passdb but getpwnam() return NULL!\n",
- user_name));
- pdb_free_sam( &sampw );
- return False;
- }
-
- *puid = unix_pw->pw_uid;
-
- DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_string_static(psid),
- (unsigned int)*puid, user_name ));
-
- *name_type = SID_NAME_USER;
- pdb_free_sam( &sampw );
- return True;
-}
-
-/****************************************************************************
- Convert a gid to SID - locally.
-****************************************************************************/
-
-DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
-{
- GROUP_MAP group;
- BOOL ret;
-
- /* we don't need to disable winbindd since the gid is stored in
- the GROUP_MAP object */
-
- /* done as root since ldap backend requires root to open a connection */
-
- become_root();
- ret = pdb_getgrgid( &group, gid );
- unbecome_root();
-
- if ( !ret ) {
-
- /* fallback to rid mapping if enabled */
-
- if ( lp_enable_rid_algorithm() ) {
- sid_copy(psid, get_global_sam_sid());
- sid_append_rid(psid, pdb_gid_to_group_rid(gid));
-
- DEBUG(10,("local_gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n",
- (unsigned int)gid, sid_string_static(psid)));
-
- return psid;
- }
- else
- return NULL;
- }
-
- sid_copy( psid, &group.sid );
-
- DEBUG(10,("local_gid_to_sid: gid (%d) -> SID %s.\n",
- (unsigned int)gid, sid_string_static(psid)));
-
- return psid;
-}
-
-/****************************************************************************
- Convert a SID to gid - locally.
-****************************************************************************/
-
-BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
- uint32 rid;
- GROUP_MAP group;
- BOOL ret;
-
- *name_type = SID_NAME_UNKNOWN;
-
- /* This call can enumerate group mappings for foreign sids as well.
- So don't check for a match against our domain SID */
-
- /* we don't need to disable winbindd since the gid is stored in
- the GROUP_MAP object */
-
- become_root();
- ret = pdb_getgrsid(&group, *psid);
- unbecome_root();
-
- if ( !ret ) {
-
- /* Fallback to algorithmic rid mapping if enabled */
-
- if ( lp_enable_rid_algorithm() ) {
-
- if (!sid_check_is_in_our_domain(psid) ) {
- DEBUG(5,("local_sid_to_gid: RID algorithm only supported for our domain (%s is not)\n", sid_string_static(psid)));
- return False;
- }
-
- if (!sid_peek_rid(psid, &rid)) {
- DEBUG(10,("local_sid_to_gid: invalid SID!\n"));
- return False;
- }
-
- DEBUG(10,("local_sid_to_gid: Fall back to algorithmic mapping\n"));
-
- if (algorithmic_pdb_rid_is_user(rid)) {
- DEBUG(3, ("local_sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(psid)));
- return False;
- } else {
- *pgid = pdb_group_rid_to_gid(rid);
- DEBUG(10,("local_sid_to_gid: mapping: %s -> %u\n", sid_string_static(psid), (unsigned int)(*pgid)));
- return True;
- }
- }
-
- return False;
- }
-
- *pgid = group.gid;
- *name_type = group.sid_name_use;
-
- DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid),
- (unsigned int)*pgid));
-
- return True;
-}
-
-/**********************************************************************
- Marshall/unmarshall SAM_ACCOUNT structs.
- *********************************************************************/
-
-#define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
-#define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
-#define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
-
-/**********************************************************************
- Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
- *********************************************************************/
-
-BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
-{
- return(init_sam_from_buffer_v2(sampass, buf, buflen));
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_OK;
}
/**********************************************************************
- Intialize a BYTE buffer from a SAM_ACCOUNT struct
+ Marshall/unmarshall struct samu structs.
*********************************************************************/
-uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
-{
- return(init_buffer_from_sam_v2(buf, sampass, size_only));
-}
-
-
-BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
-{
-
- /* times are stored as 32bit integer
- take care on system with 64bit wide time_t
- --SSS */
- uint32 logon_time,
- logoff_time,
- kickoff_time,
- pass_last_set_time,
- pass_can_change_time,
- pass_must_change_time;
- char *username = NULL;
- char *domain = NULL;
- char *nt_username = NULL;
- char *dir_drive = NULL;
- char *unknown_str = NULL;
- char *munged_dial = NULL;
- char *fullname = NULL;
- char *homedir = NULL;
- char *logon_script = NULL;
- char *profile_path = NULL;
- char *acct_desc = NULL;
- char *workstations = NULL;
- uint32 username_len, domain_len, nt_username_len,
- dir_drive_len, unknown_str_len, munged_dial_len,
- fullname_len, homedir_len, logon_script_len,
- profile_path_len, acct_desc_len, workstations_len;
-
- uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
- uint16 acct_ctrl, logon_divs;
- uint16 bad_password_count, logon_count;
- uint8 *hours = NULL;
- uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
- uint32 len = 0;
- uint32 lm_pw_len, nt_pw_len, hourslen;
- BOOL ret = True;
-
- if(sampass == NULL || buf == NULL) {
- DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
- return False;
- }
-
-/* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
-
- /* unpack the buffer into variables */
- len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
- &logon_time, /* d */
- &logoff_time, /* d */
- &kickoff_time, /* d */
- &pass_last_set_time, /* d */
- &pass_can_change_time, /* d */
- &pass_must_change_time, /* d */
- &username_len, &username, /* B */
- &domain_len, &domain, /* B */
- &nt_username_len, &nt_username, /* B */
- &fullname_len, &fullname, /* B */
- &homedir_len, &homedir, /* B */
- &dir_drive_len, &dir_drive, /* B */
- &logon_script_len, &logon_script, /* B */
- &profile_path_len, &profile_path, /* B */
- &acct_desc_len, &acct_desc, /* B */
- &workstations_len, &workstations, /* B */
- &unknown_str_len, &unknown_str, /* B */
- &munged_dial_len, &munged_dial, /* B */
- &user_rid, /* d */
- &group_rid, /* d */
- &lm_pw_len, &lm_pw_ptr, /* B */
- &nt_pw_len, &nt_pw_ptr, /* B */
- &acct_ctrl, /* w */
- &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
- &logon_divs, /* w */
- &hours_len, /* d */
- &hourslen, &hours, /* B */
- &bad_password_count, /* w */
- &logon_count, /* w */
- &unknown_6); /* d */
-
- if (len == (uint32) -1) {
- ret = False;
- goto done;
- }
-
- pdb_set_logon_time(sampass, logon_time, PDB_SET);
- pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
- pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
- pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
- pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
- pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
-
- pdb_set_username(sampass, username, PDB_SET);
- pdb_set_domain(sampass, domain, PDB_SET);
- pdb_set_nt_username(sampass, nt_username, PDB_SET);
- pdb_set_fullname(sampass, fullname, PDB_SET);
-
- if (homedir) {
- pdb_set_homedir(sampass, homedir, PDB_SET);
- }
- else {
- pdb_set_homedir(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
- PDB_DEFAULT);
- }
-
- if (dir_drive)
- pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
- else {
- pdb_set_dir_drive(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
- PDB_DEFAULT);
- }
-
- if (logon_script)
- pdb_set_logon_script(sampass, logon_script, PDB_SET);
- else {
- pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
- PDB_DEFAULT);
- }
-
- if (profile_path) {
- pdb_set_profile_path(sampass, profile_path, PDB_SET);
- } else {
- pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
- PDB_DEFAULT);
- }
-
- pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
- pdb_set_workstations(sampass, workstations, PDB_SET);
- pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
-
- if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
- if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
- ret = False;
- goto done;
- }
- }
-
- if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
- if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
- ret = False;
- goto done;
- }
- }
-
- pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
- 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);
- pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
- pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
- pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
- pdb_set_hours(sampass, hours, PDB_SET);
-
-done:
-
- SAFE_FREE(username);
- SAFE_FREE(domain);
- SAFE_FREE(nt_username);
- SAFE_FREE(fullname);
- SAFE_FREE(homedir);
- SAFE_FREE(dir_drive);
- SAFE_FREE(logon_script);
- SAFE_FREE(profile_path);
- SAFE_FREE(acct_desc);
- SAFE_FREE(workstations);
- SAFE_FREE(munged_dial);
- SAFE_FREE(unknown_str);
- SAFE_FREE(lm_pw_ptr);
- SAFE_FREE(nt_pw_ptr);
- SAFE_FREE(hours);
-
- return ret;
-}
-
-BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
-{
-
- /* times are stored as 32bit integer
- take care on system with 64bit wide time_t
- --SSS */
- uint32 logon_time,
- logoff_time,
- kickoff_time,
- bad_password_time,
- pass_last_set_time,
- pass_can_change_time,
- pass_must_change_time;
- char *username = NULL;
- char *domain = NULL;
- char *nt_username = NULL;
- char *dir_drive = NULL;
- char *unknown_str = NULL;
- char *munged_dial = NULL;
- char *fullname = NULL;
- char *homedir = NULL;
- char *logon_script = NULL;
- char *profile_path = NULL;
- char *acct_desc = NULL;
- char *workstations = NULL;
- uint32 username_len, domain_len, nt_username_len,
- dir_drive_len, unknown_str_len, munged_dial_len,
- fullname_len, homedir_len, logon_script_len,
- profile_path_len, acct_desc_len, workstations_len;
-
- uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
- uint16 acct_ctrl, logon_divs;
- uint16 bad_password_count, logon_count;
- uint8 *hours = NULL;
- uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
- uint32 len = 0;
- uint32 lm_pw_len, nt_pw_len, hourslen;
- BOOL ret = True;
-
- if(sampass == NULL || buf == NULL) {
- DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
- return False;
- }
-
-/* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
-
- /* unpack the buffer into variables */
- len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
- &logon_time, /* d */
- &logoff_time, /* d */
- &kickoff_time, /* d */
- /* Change from V0 is addition of bad_password_time field. */
- &bad_password_time, /* d */
- &pass_last_set_time, /* d */
- &pass_can_change_time, /* d */
- &pass_must_change_time, /* d */
- &username_len, &username, /* B */
- &domain_len, &domain, /* B */
- &nt_username_len, &nt_username, /* B */
- &fullname_len, &fullname, /* B */
- &homedir_len, &homedir, /* B */
- &dir_drive_len, &dir_drive, /* B */
- &logon_script_len, &logon_script, /* B */
- &profile_path_len, &profile_path, /* B */
- &acct_desc_len, &acct_desc, /* B */
- &workstations_len, &workstations, /* B */
- &unknown_str_len, &unknown_str, /* B */
- &munged_dial_len, &munged_dial, /* B */
- &user_rid, /* d */
- &group_rid, /* d */
- &lm_pw_len, &lm_pw_ptr, /* B */
- &nt_pw_len, &nt_pw_ptr, /* B */
- &acct_ctrl, /* w */
- &remove_me, /* d */
- &logon_divs, /* w */
- &hours_len, /* d */
- &hourslen, &hours, /* B */
- &bad_password_count, /* w */
- &logon_count, /* w */
- &unknown_6); /* d */
-
- if (len == (uint32) -1) {
- ret = False;
- goto done;
- }
-
- pdb_set_logon_time(sampass, logon_time, PDB_SET);
- pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
- pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
-
- /* Change from V0 is addition of bad_password_time field. */
- pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
- pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
- pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
- pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
-
- pdb_set_username(sampass, username, PDB_SET);
- pdb_set_domain(sampass, domain, PDB_SET);
- pdb_set_nt_username(sampass, nt_username, PDB_SET);
- pdb_set_fullname(sampass, fullname, PDB_SET);
-
- if (homedir) {
- pdb_set_homedir(sampass, homedir, PDB_SET);
- }
- else {
- pdb_set_homedir(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
- PDB_DEFAULT);
- }
-
- if (dir_drive)
- pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
- else {
- pdb_set_dir_drive(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
- PDB_DEFAULT);
- }
-
- if (logon_script)
- pdb_set_logon_script(sampass, logon_script, PDB_SET);
- else {
- pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
- PDB_DEFAULT);
- }
-
- if (profile_path) {
- pdb_set_profile_path(sampass, profile_path, PDB_SET);
- } else {
- pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
- PDB_DEFAULT);
- }
-
- pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
- pdb_set_workstations(sampass, workstations, PDB_SET);
- pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
-
- if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
- if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
- ret = False;
- goto done;
- }
- }
-
- if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
- if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
- ret = False;
- goto done;
- }
- }
-
- pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
-
- 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);
- pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
- pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
- pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
- pdb_set_hours(sampass, hours, PDB_SET);
-
-done:
-
- SAFE_FREE(username);
- SAFE_FREE(domain);
- SAFE_FREE(nt_username);
- SAFE_FREE(fullname);
- SAFE_FREE(homedir);
- SAFE_FREE(dir_drive);
- SAFE_FREE(logon_script);
- SAFE_FREE(profile_path);
- SAFE_FREE(acct_desc);
- SAFE_FREE(workstations);
- SAFE_FREE(munged_dial);
- SAFE_FREE(unknown_str);
- SAFE_FREE(lm_pw_ptr);
- SAFE_FREE(nt_pw_ptr);
- SAFE_FREE(hours);
-
- return ret;
-}
+#define TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
+/*********************************************************************
+*********************************************************************/
-BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+BOOL init_sam_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
{
/* times are stored as 32bit integer
@@ -1741,8 +846,8 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
fullname_len, homedir_len, logon_script_len,
profile_path_len, acct_desc_len, workstations_len;
- uint32 user_rid, group_rid, hours_len, unknown_6;
- uint16 acct_ctrl, logon_divs;
+ uint32 user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
+ uint16 logon_divs;
uint16 bad_password_count, logon_count;
uint8 *hours = NULL;
uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
@@ -1754,14 +859,14 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
BOOL expand_explicit = lp_passdb_expand_explicit();
if(sampass == NULL || buf == NULL) {
- DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
+ DEBUG(0, ("init_sam_from_buffer_v3: NULL parameters found!\n"));
return False;
}
-/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
+/* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
/* unpack the buffer into variables */
- len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V3,
&logon_time, /* d */
&logoff_time, /* d */
&kickoff_time, /* d */
@@ -1787,7 +892,8 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
&nt_pw_len, &nt_pw_ptr, /* B */
/* Change from V1 is addition of password history field. */
&nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
- &acct_ctrl, /* w */
+ /* Change from V2 is the uint32 acb_mask */
+ &acct_ctrl, /* d */
/* Also "remove_me" field was removed. */
&logon_divs, /* w */
&hours_len, /* d */
@@ -1824,7 +930,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
}
else {
pdb_set_homedir(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, lp_logon_home()),
PDB_DEFAULT);
}
@@ -1843,7 +949,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
}
else {
pdb_set_logon_script(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, lp_logon_script()),
PDB_DEFAULT);
}
@@ -1857,7 +963,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
}
else {
pdb_set_profile_path(sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
+ talloc_sub_basic(sampass, username, lp_logon_path()),
PDB_DEFAULT);
}
@@ -1879,7 +985,6 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *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);
@@ -1909,11 +1014,11 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *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);
pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ /* Change from V2 is the uint32 acct_ctrl */
pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
pdb_set_hours(sampass, hours, PDB_SET);
@@ -1940,7 +1045,10 @@ done:
return ret;
}
-uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
+/*********************************************************************
+*********************************************************************/
+
+uint32 init_buffer_from_sam_v3 (uint8 **buf, struct samu *sampass, BOOL size_only)
{
size_t len, buflen;
@@ -1982,9 +1090,9 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
uint32 nt_pw_hist_len;
uint32 pwHistLen = 0;
- /* do we have a valid SAM_ACCOUNT pointer? */
+ /* do we have a valid struct samu pointer? */
if (sampass == NULL) {
- DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n"));
+ DEBUG(0, ("init_buffer_from_sam: struct samu is NULL!\n"));
return -1;
}
@@ -2120,10 +1228,10 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
munged_dial_len = 0;
}
-/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
+/* TDB_FORMAT_STRING_V3 "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
/* one time to get the size needed */
- len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V2,
+ len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V3,
logon_time, /* d */
logoff_time, /* d */
kickoff_time, /* d */
@@ -2148,7 +1256,7 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
lm_pw_len, lm_pw, /* B */
nt_pw_len, nt_pw, /* B */
nt_pw_hist_len, nt_pw_hist, /* B */
- pdb_get_acct_ctrl(sampass), /* w */
+ pdb_get_acct_ctrl(sampass), /* d */
pdb_get_logon_divs(sampass), /* w */
pdb_get_hours_len(sampass), /* d */
MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
@@ -2162,12 +1270,12 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
/* malloc the space needed */
if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
- DEBUG(0,("init_buffer_from_sam_v2: Unable to malloc() memory for buffer!\n"));
+ DEBUG(0,("init_buffer_from_sam_v3: Unable to malloc() memory for buffer!\n"));
return (-1);
}
/* now for the real call to tdb_pack() */
- buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V2,
+ buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V3,
logon_time, /* d */
logoff_time, /* d */
kickoff_time, /* d */
@@ -2192,7 +1300,7 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
lm_pw_len, lm_pw, /* B */
nt_pw_len, nt_pw, /* B */
nt_pw_hist_len, nt_pw_hist, /* B */
- pdb_get_acct_ctrl(sampass), /* w */
+ pdb_get_acct_ctrl(sampass), /* d */
pdb_get_logon_divs(sampass), /* w */
pdb_get_hours_len(sampass), /* d */
MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */
@@ -2202,7 +1310,7 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
/* check to make sure we got it correct */
if (buflen != len) {
- DEBUG(0, ("init_buffer_from_sam_v2: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
+ DEBUG(0, ("init_buffer_from_sam_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
(unsigned long)buflen, (unsigned long)len));
/* error */
SAFE_FREE (*buf);
@@ -2212,78 +1320,40 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
return (buflen);
}
-BOOL pdb_copy_sam_account(const SAM_ACCOUNT *src, SAM_ACCOUNT **dst)
+
+/*********************************************************************
+*********************************************************************/
+
+BOOL pdb_copy_sam_account(struct samu *dst, struct samu *src )
{
BOOL result;
uint8 *buf;
int len;
- if ((*dst == NULL) && (!NT_STATUS_IS_OK(pdb_init_sam(dst))))
+ if ( !dst )
return False;
- len = init_buffer_from_sam_v2(&buf, src, False);
+ len = init_buffer_from_sam_v3(&buf, src, False);
if (len == -1)
return False;
- result = init_sam_from_buffer_v2(*dst, buf, len);
- (*dst)->methods = src->methods;
+ result = init_sam_from_buffer_v3( dst, buf, len );
+ dst->methods = src->methods;
+
+ if ( src->unix_pw )
+ dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
free(buf);
return result;
}
-/**********************************************************************
-**********************************************************************/
-
-static BOOL get_free_ugid_range(uint32 *low, uint32 *high)
-{
- uid_t u_low, u_high;
- gid_t g_low, g_high;
-
- if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) {
- return False;
- }
-
- *low = (u_low < g_low) ? u_low : g_low;
- *high = (u_high < g_high) ? u_high : g_high;
-
- return True;
-}
-
-/******************************************************************
- Get the the non-algorithmic RID range if idmap range are defined
-******************************************************************/
-
-BOOL get_free_rid_range(uint32 *low, uint32 *high)
-{
- uint32 id_low, id_high;
-
- if (!lp_enable_rid_algorithm()) {
- *low = BASE_RID;
- *high = (uint32)-1;
- }
-
- if (!get_free_ugid_range(&id_low, &id_high)) {
- return False;
- }
-
- *low = algorithmic_pdb_uid_to_user_rid(id_low);
- if (algorithmic_pdb_user_rid_to_uid((uint32)-1) < id_high) {
- *high = (uint32)-1;
- } else {
- *high = algorithmic_pdb_uid_to_user_rid(id_high);
- }
-
- return True;
-}
-
/*********************************************************************
Update the bad password count checking the AP_RESET_COUNT_TIME
*********************************************************************/
-BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated)
+BOOL pdb_update_bad_password_count(struct samu *sampass, BOOL *updated)
{
time_t LastBadPassword;
uint16 BadPasswordCount;
@@ -2326,7 +1396,7 @@ BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated)
Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION
*********************************************************************/
-BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated)
+BOOL pdb_update_autolock_flag(struct samu *sampass, BOOL *updated)
{
uint32 duration;
time_t LastBadPassword;
@@ -2379,7 +1449,7 @@ bad password time. Leaving locked out.\n",
Increment the bad_password_count
*********************************************************************/
-BOOL pdb_increment_bad_password_count(SAM_ACCOUNT *sampass)
+BOOL pdb_increment_bad_password_count(struct samu *sampass)
{
uint32 account_policy_lockout;
BOOL autolock_updated = False, badpw_updated = False;
diff --git a/source/passdb/pdb_compat.c b/source/passdb/pdb_compat.c
index abd572a7c14..788663f27a4 100644
--- a/source/passdb/pdb_compat.c
+++ b/source/passdb/pdb_compat.c
@@ -1,6 +1,6 @@
/*
Unix SMB/CIFS implementation.
- SAM_ACCOUNT access routines
+ struct samu access routines
Copyright (C) Jeremy Allison 1996-2001
Copyright (C) Luke Kenneth Casson Leighton 1996-1998
Copyright (C) Gerald (Jerry) Carter 2000-2001
@@ -27,7 +27,7 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
-uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass)
+uint32 pdb_get_user_rid (const struct samu *sampass)
{
uint32 u_rid;
@@ -38,7 +38,7 @@ uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass)
return (0);
}
-uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass)
+uint32 pdb_get_group_rid (struct samu *sampass)
{
uint32 g_rid;
@@ -48,7 +48,7 @@ uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass)
return (0);
}
-BOOL pdb_set_user_sid_from_rid (SAM_ACCOUNT *sampass, uint32 rid, enum pdb_value_state flag)
+BOOL pdb_set_user_sid_from_rid (struct samu *sampass, uint32 rid, enum pdb_value_state flag)
{
DOM_SID u_sid;
const DOM_SID *global_sam_sid;
@@ -75,7 +75,7 @@ BOOL pdb_set_user_sid_from_rid (SAM_ACCOUNT *sampass, uint32 rid, enum pdb_value
return True;
}
-BOOL pdb_set_group_sid_from_rid (SAM_ACCOUNT *sampass, uint32 grid, enum pdb_value_state flag)
+BOOL pdb_set_group_sid_from_rid (struct samu *sampass, uint32 grid, enum pdb_value_state flag)
{
DOM_SID g_sid;
const DOM_SID *global_sam_sid;
diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c
index 783e9e23fa3..5cb72e7f863 100644
--- a/source/passdb/pdb_get_set.c
+++ b/source/passdb/pdb_get_set.c
@@ -1,6 +1,6 @@
/*
Unix SMB/CIFS implementation.
- SAM_ACCOUNT access routines
+ struct samu access routines
Copyright (C) Jeremy Allison 1996-2001
Copyright (C) Luke Kenneth Casson Leighton 1996-1998
Copyright (C) Gerald (Jerry) Carter 2000-2001
@@ -37,126 +37,126 @@
#define PDB_NOT_QUITE_NULL ""
/*********************************************************************
- Collection of get...() functions for SAM_ACCOUNT.
+ Collection of get...() functions for struct samu.
********************************************************************/
-uint16 pdb_get_acct_ctrl (const SAM_ACCOUNT *sampass)
+uint32 pdb_get_acct_ctrl (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.acct_ctrl);
+ return (sampass->acct_ctrl);
else
return (ACB_DISABLED);
}
-time_t pdb_get_logon_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_logon_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.logon_time);
+ return (sampass->logon_time);
else
return (0);
}
-time_t pdb_get_logoff_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_logoff_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.logoff_time);
+ return (sampass->logoff_time);
else
return (-1);
}
-time_t pdb_get_kickoff_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_kickoff_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.kickoff_time);
+ return (sampass->kickoff_time);
else
return (-1);
}
-time_t pdb_get_bad_password_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_bad_password_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.bad_password_time);
+ return (sampass->bad_password_time);
else
return (-1);
}
-time_t pdb_get_pass_last_set_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_pass_last_set_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.pass_last_set_time);
+ return (sampass->pass_last_set_time);
else
return (-1);
}
-time_t pdb_get_pass_can_change_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_pass_can_change_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.pass_can_change_time);
+ return (sampass->pass_can_change_time);
else
return (-1);
}
-time_t pdb_get_pass_must_change_time (const SAM_ACCOUNT *sampass)
+time_t pdb_get_pass_must_change_time (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.pass_must_change_time);
+ return (sampass->pass_must_change_time);
else
return (-1);
}
-uint16 pdb_get_logon_divs (const SAM_ACCOUNT *sampass)
+uint16 pdb_get_logon_divs (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.logon_divs);
+ return (sampass->logon_divs);
else
return (-1);
}
-uint32 pdb_get_hours_len (const SAM_ACCOUNT *sampass)
+uint32 pdb_get_hours_len (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.hours_len);
+ return (sampass->hours_len);
else
return (-1);
}
-const uint8* pdb_get_hours (const SAM_ACCOUNT *sampass)
+const uint8* pdb_get_hours (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.hours);
+ return (sampass->hours);
else
return (NULL);
}
-const uint8* pdb_get_nt_passwd (const SAM_ACCOUNT *sampass)
+const uint8* pdb_get_nt_passwd (const struct samu *sampass)
{
if (sampass) {
- SMB_ASSERT((!sampass->private_u.nt_pw.data)
- || sampass->private_u.nt_pw.length == NT_HASH_LEN);
- return ((uint8*)sampass->private_u.nt_pw.data);
+ SMB_ASSERT((!sampass->nt_pw.data)
+ || sampass->nt_pw.length == NT_HASH_LEN);
+ return ((uint8*)sampass->nt_pw.data);
}
else
return (NULL);
}
-const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass)
+const uint8* pdb_get_lanman_passwd (const struct samu *sampass)
{
if (sampass) {
- SMB_ASSERT((!sampass->private_u.lm_pw.data)
- || sampass->private_u.lm_pw.length == LM_HASH_LEN);
- return ((uint8*)sampass->private_u.lm_pw.data);
+ SMB_ASSERT((!sampass->lm_pw.data)
+ || sampass->lm_pw.length == LM_HASH_LEN);
+ return ((uint8*)sampass->lm_pw.data);
}
else
return (NULL);
}
-const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_hist_len)
+const uint8* pdb_get_pw_history (const struct samu *sampass, uint32 *current_hist_len)
{
if (sampass) {
- SMB_ASSERT((!sampass->private_u.nt_pw_his.data)
- || ((sampass->private_u.nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0));
- *current_hist_len = sampass->private_u.nt_pw_his.length / PW_HISTORY_ENTRY_LEN;
- return ((uint8*)sampass->private_u.nt_pw_his.data);
+ SMB_ASSERT((!sampass->nt_pw_his.data)
+ || ((sampass->nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0));
+ *current_hist_len = sampass->nt_pw_his.length / PW_HISTORY_ENTRY_LEN;
+ return ((uint8*)sampass->nt_pw_his.data);
} else {
*current_hist_len = 0;
return (NULL);
@@ -169,49 +169,114 @@ const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_his
Used to pass the plaintext to passdb backends that might
want to store more than just the NTLM hashes.
*/
-const char* pdb_get_plaintext_passwd (const SAM_ACCOUNT *sampass)
+const char* pdb_get_plaintext_passwd (const struct samu *sampass)
{
if (sampass) {
- return (sampass->private_u.plaintext_pw);
+ return (sampass->plaintext_pw);
}
else
return (NULL);
}
-const DOM_SID *pdb_get_user_sid(const SAM_ACCOUNT *sampass)
+const DOM_SID *pdb_get_user_sid(const struct samu *sampass)
{
if (sampass)
- return &sampass->private_u.user_sid;
- else
- return (NULL);
+ return &sampass->user_sid;
+
+ return NULL;
}
-const DOM_SID *pdb_get_group_sid(const SAM_ACCOUNT *sampass)
+const DOM_SID *pdb_get_group_sid(struct samu *sampass)
{
- if (sampass)
- return &sampass->private_u.group_sid;
- else
- return (NULL);
+ DOM_SID *gsid;
+ struct passwd *pwd;
+
+ /* sanity check */
+
+ if ( !sampass ) {
+ return NULL;
+ }
+
+ /* Return the cached group SID if we have that */
+
+ if ( sampass->group_sid ) {
+ return sampass->group_sid;
+ }
+
+ /* generate the group SID from the user's primary Unix group */
+
+ if ( !(gsid = TALLOC_P( sampass, DOM_SID )) ) {
+ return NULL;
+ }
+
+ /* No algorithmic mapping, meaning that we have to figure out the
+ primary group SID according to group mapping and the user SID must
+ be a newly allocated one. We rely on the user's Unix primary gid.
+ We have no choice but to fail if we can't find it. */
+
+ if ( sampass->unix_pw )
+ pwd = sampass->unix_pw;
+ else
+ pwd = getpwnam_alloc( sampass, pdb_get_username(sampass) );
+
+ if ( !pwd ) {
+ DEBUG(0,("pdb_get_group_sid: Failed to find Unix account for %s\n", pdb_get_username(sampass) ));
+ return NULL;
+ }
+
+ if ( pdb_gid_to_sid(pwd->pw_gid, gsid) ) {
+ enum SID_NAME_USE type = SID_NAME_UNKNOWN;
+ TALLOC_CTX *mem_ctx = talloc_init("pdb_get_group_sid");
+ BOOL lookup_ret;
+
+ if (!mem_ctx) {
+ return NULL;
+ }
+
+ /* Now check that it's actually a domain group and not something else */
+
+ lookup_ret = lookup_sid(mem_ctx, gsid, NULL, NULL, &type);
+
+ TALLOC_FREE( mem_ctx );
+
+ if ( lookup_ret && (type == SID_NAME_DOM_GRP) ) {
+ sampass->group_sid = gsid;
+ return sampass->group_sid;
+ }
+
+ DEBUG(3, ("Primary group for user %s is a %s and not a domain group\n",
+ pwd->pw_name, sid_type_lookup(type)));
+ }
+
+ /* Just set it to the 'Domain Users' RID of 512 which will
+ always resolve to a name */
+
+ sid_copy( gsid, get_global_sam_sid() );
+ sid_append_rid( gsid, DOMAIN_GROUP_RID_USERS );
+
+ sampass->group_sid = gsid;
+
+ return sampass->group_sid;
}
/**
- * Get flags showing what is initalised in the SAM_ACCOUNT
- * @param sampass the SAM_ACCOUNT in question
+ * Get flags showing what is initalised in the struct samu
+ * @param sampass the struct samu in question
* @return the flags indicating the members initialised in the struct.
**/
-enum pdb_value_state pdb_get_init_flags (const SAM_ACCOUNT *sampass, enum pdb_elements element)
+enum pdb_value_state pdb_get_init_flags (const struct samu *sampass, enum pdb_elements element)
{
enum pdb_value_state ret = PDB_DEFAULT;
- if (!sampass || !sampass->private_u.change_flags || !sampass->private_u.set_flags)
+ if (!sampass || !sampass->change_flags || !sampass->set_flags)
return ret;
- if (bitmap_query(sampass->private_u.set_flags, element)) {
+ if (bitmap_query(sampass->set_flags, element)) {
DEBUG(11, ("element %d: SET\n", element));
ret = PDB_SET;
}
- if (bitmap_query(sampass->private_u.change_flags, element)) {
+ if (bitmap_query(sampass->change_flags, element)) {
DEBUG(11, ("element %d: CHANGED\n", element));
ret = PDB_CHANGED;
}
@@ -223,270 +288,270 @@ enum pdb_value_state pdb_get_init_flags (const SAM_ACCOUNT *sampass, enum pdb_el
return ret;
}
-const char* pdb_get_username (const SAM_ACCOUNT *sampass)
+const char* pdb_get_username (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.username);
+ return (sampass->username);
else
return (NULL);
}
-const char* pdb_get_domain (const SAM_ACCOUNT *sampass)
+const char* pdb_get_domain (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.domain);
+ return (sampass->domain);
else
return (NULL);
}
-const char* pdb_get_nt_username (const SAM_ACCOUNT *sampass)
+const char* pdb_get_nt_username (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.nt_username);
+ return (sampass->nt_username);
else
return (NULL);
}
-const char* pdb_get_fullname (const SAM_ACCOUNT *sampass)
+const char* pdb_get_fullname (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.full_name);
+ return (sampass->full_name);
else
return (NULL);
}
-const char* pdb_get_homedir (const SAM_ACCOUNT *sampass)
+const char* pdb_get_homedir (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.home_dir);
+ return (sampass->home_dir);
else
return (NULL);
}
-const char* pdb_get_unix_homedir (const SAM_ACCOUNT *sampass)
+const char* pdb_get_unix_homedir (const struct samu *sampass)
{
- if (sampass)
- return (sampass->private_u.unix_home_dir);
- else
- return (NULL);
+ if ( sampass && sampass->unix_pw )
+ return ( sampass->unix_pw->pw_dir );
+
+ return (NULL);
}
-const char* pdb_get_dir_drive (const SAM_ACCOUNT *sampass)
+const char* pdb_get_dir_drive (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.dir_drive);
+ return (sampass->dir_drive);
else
return (NULL);
}
-const char* pdb_get_logon_script (const SAM_ACCOUNT *sampass)
+const char* pdb_get_logon_script (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.logon_script);
+ return (sampass->logon_script);
else
return (NULL);
}
-const char* pdb_get_profile_path (const SAM_ACCOUNT *sampass)
+const char* pdb_get_profile_path (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.profile_path);
+ return (sampass->profile_path);
else
return (NULL);
}
-const char* pdb_get_acct_desc (const SAM_ACCOUNT *sampass)
+const char* pdb_get_acct_desc (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.acct_desc);
+ return (sampass->acct_desc);
else
return (NULL);
}
-const char* pdb_get_workstations (const SAM_ACCOUNT *sampass)
+const char* pdb_get_workstations (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.workstations);
+ return (sampass->workstations);
else
return (NULL);
}
-const char* pdb_get_unknown_str (const SAM_ACCOUNT *sampass)
+const char* pdb_get_unknown_str (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.unknown_str);
+ return (sampass->unknown_str);
else
return (NULL);
}
-const char* pdb_get_munged_dial (const SAM_ACCOUNT *sampass)
+const char* pdb_get_munged_dial (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.munged_dial);
+ return (sampass->munged_dial);
else
return (NULL);
}
-uint16 pdb_get_bad_password_count(const SAM_ACCOUNT *sampass)
+uint16 pdb_get_bad_password_count(const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.bad_password_count);
+ return (sampass->bad_password_count);
else
return 0;
}
-uint16 pdb_get_logon_count(const SAM_ACCOUNT *sampass)
+uint16 pdb_get_logon_count(const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.logon_count);
+ return (sampass->logon_count);
else
return 0;
}
-uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass)
+uint32 pdb_get_unknown_6 (const struct samu *sampass)
{
if (sampass)
- return (sampass->private_u.unknown_6);
+ return (sampass->unknown_6);
else
return (-1);
}
-void *pdb_get_backend_private_data (const SAM_ACCOUNT *sampass, const struct pdb_methods *my_methods)
+void *pdb_get_backend_private_data (const struct samu *sampass, const struct pdb_methods *my_methods)
{
- if (sampass && my_methods == sampass->private_u.backend_private_methods)
- return sampass->private_u.backend_private_data;
+ if (sampass && my_methods == sampass->backend_private_methods)
+ return sampass->backend_private_data;
else
return NULL;
}
/*********************************************************************
- Collection of set...() functions for SAM_ACCOUNT.
+ Collection of set...() functions for struct samu.
********************************************************************/
-BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 acct_ctrl, enum pdb_value_state flag)
+BOOL pdb_set_acct_ctrl (struct samu *sampass, uint32 acct_ctrl, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.acct_ctrl = acct_ctrl;
+ sampass->acct_ctrl = acct_ctrl;
return pdb_set_init_flags(sampass, PDB_ACCTCTRL, flag);
}
-BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+BOOL pdb_set_logon_time (struct samu *sampass, time_t mytime, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.logon_time = mytime;
+ sampass->logon_time = mytime;
return pdb_set_init_flags(sampass, PDB_LOGONTIME, flag);
}
-BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+BOOL pdb_set_logoff_time (struct samu *sampass, time_t mytime, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.logoff_time = mytime;
+ sampass->logoff_time = mytime;
return pdb_set_init_flags(sampass, PDB_LOGOFFTIME, flag);
}
-BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+BOOL pdb_set_kickoff_time (struct samu *sampass, time_t mytime, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.kickoff_time = mytime;
+ sampass->kickoff_time = mytime;
return pdb_set_init_flags(sampass, PDB_KICKOFFTIME, flag);
}
-BOOL pdb_set_bad_password_time (SAM_ACCOUNT *sampass, time_t mytime,
+BOOL pdb_set_bad_password_time (struct samu *sampass, time_t mytime,
enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.bad_password_time = mytime;
+ sampass->bad_password_time = mytime;
return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_TIME, flag);
}
-BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+BOOL pdb_set_pass_can_change_time (struct samu *sampass, time_t mytime, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.pass_can_change_time = mytime;
+ sampass->pass_can_change_time = mytime;
return pdb_set_init_flags(sampass, PDB_CANCHANGETIME, flag);
}
-BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+BOOL pdb_set_pass_must_change_time (struct samu *sampass, time_t mytime, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.pass_must_change_time = mytime;
+ sampass->pass_must_change_time = mytime;
return pdb_set_init_flags(sampass, PDB_MUSTCHANGETIME, flag);
}
-BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+BOOL pdb_set_pass_last_set_time (struct samu *sampass, time_t mytime, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.pass_last_set_time = mytime;
+ sampass->pass_last_set_time = mytime;
return pdb_set_init_flags(sampass, PDB_PASSLASTSET, flag);
}
-BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len, enum pdb_value_state flag)
+BOOL pdb_set_hours_len (struct samu *sampass, uint32 len, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.hours_len = len;
+ sampass->hours_len = len;
return pdb_set_init_flags(sampass, PDB_HOURSLEN, flag);
}
-BOOL pdb_set_logon_divs (SAM_ACCOUNT *sampass, uint16 hours, enum pdb_value_state flag)
+BOOL pdb_set_logon_divs (struct samu *sampass, uint16 hours, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.logon_divs = hours;
+ sampass->logon_divs = hours;
return pdb_set_init_flags(sampass, PDB_LOGONDIVS, flag);
}
/**
- * Set flags showing what is initalised in the SAM_ACCOUNT
- * @param sampass the SAM_ACCOUNT in question
+ * Set flags showing what is initalised in the struct samu
+ * @param sampass the struct samu in question
* @param flag The *new* flag to be set. Old flags preserved
* this flag is only added.
**/
-BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum pdb_value_state value_flag)
+BOOL pdb_set_init_flags (struct samu *sampass, enum pdb_elements element, enum pdb_value_state value_flag)
{
- if (!sampass || !sampass->mem_ctx)
+ if (!sampass || !sampass)
return False;
- if (!sampass->private_u.set_flags) {
- if ((sampass->private_u.set_flags =
- bitmap_talloc(sampass->mem_ctx,
+ if (!sampass->set_flags) {
+ if ((sampass->set_flags =
+ bitmap_talloc(sampass,
PDB_COUNT))==NULL) {
DEBUG(0,("bitmap_talloc failed\n"));
return False;
}
}
- if (!sampass->private_u.change_flags) {
- if ((sampass->private_u.change_flags =
- bitmap_talloc(sampass->mem_ctx,
+ if (!sampass->change_flags) {
+ if ((sampass->change_flags =
+ bitmap_talloc(sampass,
PDB_COUNT))==NULL) {
DEBUG(0,("bitmap_talloc failed\n"));
return False;
@@ -495,22 +560,22 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p
switch(value_flag) {
case PDB_CHANGED:
- if (!bitmap_set(sampass->private_u.change_flags, element)) {
+ if (!bitmap_set(sampass->change_flags, element)) {
DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
return False;
}
- if (!bitmap_set(sampass->private_u.set_flags, element)) {
+ if (!bitmap_set(sampass->set_flags, element)) {
DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
return False;
}
DEBUG(11, ("element %d -> now CHANGED\n", element));
break;
case PDB_SET:
- if (!bitmap_clear(sampass->private_u.change_flags, element)) {
+ if (!bitmap_clear(sampass->change_flags, element)) {
DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
return False;
}
- if (!bitmap_set(sampass->private_u.set_flags, element)) {
+ if (!bitmap_set(sampass->set_flags, element)) {
DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
return False;
}
@@ -518,11 +583,11 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p
break;
case PDB_DEFAULT:
default:
- if (!bitmap_clear(sampass->private_u.change_flags, element)) {
+ if (!bitmap_clear(sampass->change_flags, element)) {
DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
return False;
}
- if (!bitmap_clear(sampass->private_u.set_flags, element)) {
+ if (!bitmap_clear(sampass->set_flags, element)) {
DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
return False;
}
@@ -533,20 +598,20 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p
return True;
}
-BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, const DOM_SID *u_sid, enum pdb_value_state flag)
+BOOL pdb_set_user_sid (struct samu *sampass, const DOM_SID *u_sid, enum pdb_value_state flag)
{
if (!sampass || !u_sid)
return False;
- sid_copy(&sampass->private_u.user_sid, u_sid);
+ sid_copy(&sampass->user_sid, u_sid);
DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n",
- sid_string_static(&sampass->private_u.user_sid)));
+ sid_string_static(&sampass->user_sid)));
return pdb_set_init_flags(sampass, PDB_USERSID, flag);
}
-BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb_value_state flag)
+BOOL pdb_set_user_sid_from_string (struct samu *sampass, fstring u_sid, enum pdb_value_state flag)
{
DOM_SID new_sid;
@@ -562,69 +627,70 @@ BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb
}
if (!pdb_set_user_sid(sampass, &new_sid, flag)) {
- DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", u_sid));
+ DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on struct samu!\n", u_sid));
return False;
}
return True;
}
-BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, const DOM_SID *g_sid, enum pdb_value_state flag)
-{
- if (!sampass || !g_sid)
- return False;
-
- sid_copy(&sampass->private_u.group_sid, g_sid);
-
- DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n",
- sid_string_static(&sampass->private_u.group_sid)));
-
- return pdb_set_init_flags(sampass, PDB_GROUPSID, flag);
-}
+/********************************************************************
+ We never fill this in from a passdb backend but rather set is
+ based on the user's primary group membership. However, the
+ struct samu* is overloaded and reused in domain memship code
+ as well and built from the NET_USER_INFO_3 or PAC so we
+ have to allow the explicitly setting of a group SID here.
+********************************************************************/
-BOOL pdb_set_group_sid_from_string (SAM_ACCOUNT *sampass, fstring g_sid, enum pdb_value_state flag)
+BOOL pdb_set_group_sid (struct samu *sampass, const DOM_SID *g_sid, enum pdb_value_state flag)
{
- DOM_SID new_sid;
+ gid_t gid;
+
if (!sampass || !g_sid)
return False;
- DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n",
- g_sid));
-
- if (!string_to_sid(&new_sid, g_sid)) {
- DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid));
+ if ( !(sampass->group_sid = TALLOC_P( sampass, DOM_SID )) ) {
return False;
}
-
- if (!pdb_set_group_sid(sampass, &new_sid, flag)) {
- DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", g_sid));
- return False;
+
+ /* if we cannot resolve the SID to gid, then just ignore it and
+ store DOMAIN_USERS as the primary groupSID */
+
+ if ( sid_to_gid( g_sid, &gid ) ) {
+ sid_copy(sampass->group_sid, g_sid);
+ } else {
+ sid_copy( sampass->group_sid, get_global_sam_sid() );
+ sid_append_rid( sampass->group_sid, DOMAIN_GROUP_RID_USERS );
}
- return True;
+
+ DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n",
+ sid_string_static(sampass->group_sid)));
+
+ return pdb_set_init_flags(sampass, PDB_GROUPSID, flag);
}
/*********************************************************************
Set the user's UNIX name.
********************************************************************/
-BOOL pdb_set_username(SAM_ACCOUNT *sampass, const char *username, enum pdb_value_state flag)
+BOOL pdb_set_username(struct samu *sampass, const char *username, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (username) {
DEBUG(10, ("pdb_set_username: setting username %s, was %s\n", username,
- (sampass->private_u.username)?(sampass->private_u.username):"NULL"));
+ (sampass->username)?(sampass->username):"NULL"));
- sampass->private_u.username = talloc_strdup(sampass->mem_ctx, username);
+ sampass->username = talloc_strdup(sampass, username);
- if (!sampass->private_u.username) {
+ if (!sampass->username) {
DEBUG(0, ("pdb_set_username: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.username = PDB_NOT_QUITE_NULL;
+ sampass->username = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_USERNAME, flag);
@@ -634,24 +700,24 @@ BOOL pdb_set_username(SAM_ACCOUNT *sampass, const char *username, enum pdb_value
Set the domain name.
********************************************************************/
-BOOL pdb_set_domain(SAM_ACCOUNT *sampass, const char *domain, enum pdb_value_state flag)
+BOOL pdb_set_domain(struct samu *sampass, const char *domain, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (domain) {
DEBUG(10, ("pdb_set_domain: setting domain %s, was %s\n", domain,
- (sampass->private_u.domain)?(sampass->private_u.domain):"NULL"));
+ (sampass->domain)?(sampass->domain):"NULL"));
- sampass->private_u.domain = talloc_strdup(sampass->mem_ctx, domain);
+ sampass->domain = talloc_strdup(sampass, domain);
- if (!sampass->private_u.domain) {
+ if (!sampass->domain) {
DEBUG(0, ("pdb_set_domain: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.domain = PDB_NOT_QUITE_NULL;
+ sampass->domain = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_DOMAIN, flag);
@@ -661,24 +727,24 @@ BOOL pdb_set_domain(SAM_ACCOUNT *sampass, const char *domain, enum pdb_value_sta
Set the user's NT name.
********************************************************************/
-BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, const char *nt_username, enum pdb_value_state flag)
+BOOL pdb_set_nt_username(struct samu *sampass, const char *nt_username, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (nt_username) {
DEBUG(10, ("pdb_set_nt_username: setting nt username %s, was %s\n", nt_username,
- (sampass->private_u.nt_username)?(sampass->private_u.nt_username):"NULL"));
+ (sampass->nt_username)?(sampass->nt_username):"NULL"));
- sampass->private_u.nt_username = talloc_strdup(sampass->mem_ctx, nt_username);
+ sampass->nt_username = talloc_strdup(sampass, nt_username);
- if (!sampass->private_u.nt_username) {
+ if (!sampass->nt_username) {
DEBUG(0, ("pdb_set_nt_username: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.nt_username = PDB_NOT_QUITE_NULL;
+ sampass->nt_username = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_NTUSERNAME, flag);
@@ -688,24 +754,24 @@ BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, const char *nt_username, enum pdb
Set the user's full name.
********************************************************************/
-BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, const char *full_name, enum pdb_value_state flag)
+BOOL pdb_set_fullname(struct samu *sampass, const char *full_name, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (full_name) {
DEBUG(10, ("pdb_set_full_name: setting full name %s, was %s\n", full_name,
- (sampass->private_u.full_name)?(sampass->private_u.full_name):"NULL"));
+ (sampass->full_name)?(sampass->full_name):"NULL"));
- sampass->private_u.full_name = talloc_strdup(sampass->mem_ctx, full_name);
+ sampass->full_name = talloc_strdup(sampass, full_name);
- if (!sampass->private_u.full_name) {
+ if (!sampass->full_name) {
DEBUG(0, ("pdb_set_fullname: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.full_name = PDB_NOT_QUITE_NULL;
+ sampass->full_name = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_FULLNAME, flag);
@@ -715,24 +781,24 @@ BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, const char *full_name, enum pdb_valu
Set the user's logon script.
********************************************************************/
-BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, enum pdb_value_state flag)
+BOOL pdb_set_logon_script(struct samu *sampass, const char *logon_script, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (logon_script) {
DEBUG(10, ("pdb_set_logon_script: setting logon script %s, was %s\n", logon_script,
- (sampass->private_u.logon_script)?(sampass->private_u.logon_script):"NULL"));
+ (sampass->logon_script)?(sampass->logon_script):"NULL"));
- sampass->private_u.logon_script = talloc_strdup(sampass->mem_ctx, logon_script);
+ sampass->logon_script = talloc_strdup(sampass, logon_script);
- if (!sampass->private_u.logon_script) {
+ if (!sampass->logon_script) {
DEBUG(0, ("pdb_set_logon_script: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.logon_script = PDB_NOT_QUITE_NULL;
+ sampass->logon_script = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_LOGONSCRIPT, flag);
@@ -742,24 +808,24 @@ BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, enum p
Set the user's profile path.
********************************************************************/
-BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, enum pdb_value_state flag)
+BOOL pdb_set_profile_path (struct samu *sampass, const char *profile_path, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (profile_path) {
DEBUG(10, ("pdb_set_profile_path: setting profile path %s, was %s\n", profile_path,
- (sampass->private_u.profile_path)?(sampass->private_u.profile_path):"NULL"));
+ (sampass->profile_path)?(sampass->profile_path):"NULL"));
- sampass->private_u.profile_path = talloc_strdup(sampass->mem_ctx, profile_path);
+ sampass->profile_path = talloc_strdup(sampass, profile_path);
- if (!sampass->private_u.profile_path) {
+ if (!sampass->profile_path) {
DEBUG(0, ("pdb_set_profile_path: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.profile_path = PDB_NOT_QUITE_NULL;
+ sampass->profile_path = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_PROFILE, flag);
@@ -769,24 +835,24 @@ BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, enum
Set the user's directory drive.
********************************************************************/
-BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, enum pdb_value_state flag)
+BOOL pdb_set_dir_drive (struct samu *sampass, const char *dir_drive, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (dir_drive) {
DEBUG(10, ("pdb_set_dir_drive: setting dir drive %s, was %s\n", dir_drive,
- (sampass->private_u.dir_drive)?(sampass->private_u.dir_drive):"NULL"));
+ (sampass->dir_drive)?(sampass->dir_drive):"NULL"));
- sampass->private_u.dir_drive = talloc_strdup(sampass->mem_ctx, dir_drive);
+ sampass->dir_drive = talloc_strdup(sampass, dir_drive);
- if (!sampass->private_u.dir_drive) {
+ if (!sampass->dir_drive) {
DEBUG(0, ("pdb_set_dir_drive: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.dir_drive = PDB_NOT_QUITE_NULL;
+ sampass->dir_drive = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_DRIVE, flag);
@@ -796,76 +862,48 @@ BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, enum pdb_va
Set the user's home directory.
********************************************************************/
-BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, enum pdb_value_state flag)
+BOOL pdb_set_homedir (struct samu *sampass, const char *home_dir, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (home_dir) {
DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", home_dir,
- (sampass->private_u.home_dir)?(sampass->private_u.home_dir):"NULL"));
+ (sampass->home_dir)?(sampass->home_dir):"NULL"));
- sampass->private_u.home_dir = talloc_strdup(sampass->mem_ctx, home_dir);
+ sampass->home_dir = talloc_strdup(sampass, home_dir);
- if (!sampass->private_u.home_dir) {
+ if (!sampass->home_dir) {
DEBUG(0, ("pdb_set_home_dir: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.home_dir = PDB_NOT_QUITE_NULL;
+ sampass->home_dir = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_SMBHOME, flag);
}
/*********************************************************************
- Set the user's unix home directory.
- ********************************************************************/
-
-BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir, enum pdb_value_state flag)
-{
- if (!sampass)
- return False;
-
- if (unix_home_dir) {
- DEBUG(10, ("pdb_set_unix_homedir: setting home dir %s, was %s\n", unix_home_dir,
- (sampass->private_u.unix_home_dir)?(sampass->private_u.unix_home_dir):"NULL"));
-
- sampass->private_u.unix_home_dir = talloc_strdup(sampass->mem_ctx,
- unix_home_dir);
-
- if (!sampass->private_u.unix_home_dir) {
- DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n"));
- return False;
- }
-
- } else {
- sampass->private_u.unix_home_dir = PDB_NOT_QUITE_NULL;
- }
-
- return pdb_set_init_flags(sampass, PDB_UNIXHOMEDIR, flag);
-}
-
-/*********************************************************************
Set the user's account description.
********************************************************************/
-BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, const char *acct_desc, enum pdb_value_state flag)
+BOOL pdb_set_acct_desc (struct samu *sampass, const char *acct_desc, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (acct_desc) {
- sampass->private_u.acct_desc = talloc_strdup(sampass->mem_ctx, acct_desc);
+ sampass->acct_desc = talloc_strdup(sampass, acct_desc);
- if (!sampass->private_u.acct_desc) {
+ if (!sampass->acct_desc) {
DEBUG(0, ("pdb_set_acct_desc: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.acct_desc = PDB_NOT_QUITE_NULL;
+ sampass->acct_desc = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_ACCTDESC, flag);
@@ -875,24 +913,24 @@ BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, const char *acct_desc, enum pdb_va
Set the user's workstation allowed list.
********************************************************************/
-BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, const char *workstations, enum pdb_value_state flag)
+BOOL pdb_set_workstations (struct samu *sampass, const char *workstations, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (workstations) {
DEBUG(10, ("pdb_set_workstations: setting workstations %s, was %s\n", workstations,
- (sampass->private_u.workstations)?(sampass->private_u.workstations):"NULL"));
+ (sampass->workstations)?(sampass->workstations):"NULL"));
- sampass->private_u.workstations = talloc_strdup(sampass->mem_ctx, workstations);
+ sampass->workstations = talloc_strdup(sampass, workstations);
- if (!sampass->private_u.workstations) {
+ if (!sampass->workstations) {
DEBUG(0, ("pdb_set_workstations: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.workstations = PDB_NOT_QUITE_NULL;
+ sampass->workstations = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_WORKSTATIONS, flag);
@@ -902,21 +940,21 @@ BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, const char *workstations, enum
Set the user's 'unknown_str', whatever the heck this actually is...
********************************************************************/
-BOOL pdb_set_unknown_str (SAM_ACCOUNT *sampass, const char *unknown_str, enum pdb_value_state flag)
+BOOL pdb_set_unknown_str (struct samu *sampass, const char *unknown_str, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (unknown_str) {
- sampass->private_u.unknown_str = talloc_strdup(sampass->mem_ctx, unknown_str);
+ sampass->unknown_str = talloc_strdup(sampass, unknown_str);
- if (!sampass->private_u.unknown_str) {
+ if (!sampass->unknown_str) {
DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.unknown_str = PDB_NOT_QUITE_NULL;
+ sampass->unknown_str = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
@@ -926,21 +964,21 @@ BOOL pdb_set_unknown_str (SAM_ACCOUNT *sampass, const char *unknown_str, enum pd
Set the user's dial string.
********************************************************************/
-BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, const char *munged_dial, enum pdb_value_state flag)
+BOOL pdb_set_munged_dial (struct samu *sampass, const char *munged_dial, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (munged_dial) {
- sampass->private_u.munged_dial = talloc_strdup(sampass->mem_ctx, munged_dial);
+ sampass->munged_dial = talloc_strdup(sampass, munged_dial);
- if (!sampass->private_u.munged_dial) {
+ if (!sampass->munged_dial) {
DEBUG(0, ("pdb_set_munged_dial: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.munged_dial = PDB_NOT_QUITE_NULL;
+ sampass->munged_dial = PDB_NOT_QUITE_NULL;
}
return pdb_set_init_flags(sampass, PDB_MUNGEDDIAL, flag);
@@ -950,17 +988,18 @@ BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, const char *munged_dial, enum pd
Set the user's NT hash.
********************************************************************/
-BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum pdb_value_state flag)
+BOOL pdb_set_nt_passwd (struct samu *sampass, const uint8 pwd[NT_HASH_LEN], enum pdb_value_state flag)
{
if (!sampass)
return False;
- data_blob_clear_free(&sampass->private_u.nt_pw);
+ data_blob_clear_free(&sampass->nt_pw);
if (pwd) {
- sampass->private_u.nt_pw = data_blob(pwd, NT_HASH_LEN);
+ sampass->nt_pw =
+ data_blob_talloc(sampass, pwd, NT_HASH_LEN);
} else {
- sampass->private_u.nt_pw = data_blob(NULL, 0);
+ sampass->nt_pw = data_blob(NULL, 0);
}
return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag);
@@ -970,17 +1009,18 @@ BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum
Set the user's LM hash.
********************************************************************/
-BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], enum pdb_value_state flag)
+BOOL pdb_set_lanman_passwd (struct samu *sampass, const uint8 pwd[LM_HASH_LEN], enum pdb_value_state flag)
{
if (!sampass)
return False;
- data_blob_clear_free(&sampass->private_u.lm_pw);
+ data_blob_clear_free(&sampass->lm_pw);
if (pwd) {
- sampass->private_u.lm_pw = data_blob(pwd, LM_HASH_LEN);
+ sampass->lm_pw =
+ data_blob_talloc(sampass, pwd, LM_HASH_LEN);
} else {
- sampass->private_u.lm_pw = data_blob(NULL, 0);
+ sampass->lm_pw = data_blob(NULL, 0);
}
return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag);
@@ -993,20 +1033,20 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN],
in pwd.
********************************************************************/
-BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag)
+BOOL pdb_set_pw_history (struct samu *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (historyLen && pwd){
- sampass->private_u.nt_pw_his = data_blob_talloc(sampass->mem_ctx,
+ sampass->nt_pw_his = data_blob_talloc(sampass,
pwd, historyLen*PW_HISTORY_ENTRY_LEN);
- if (!sampass->private_u.nt_pw_his.length) {
+ if (!sampass->nt_pw_his.length) {
DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n"));
return False;
}
} else {
- sampass->private_u.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0);
+ sampass->nt_pw_his = data_blob_talloc(sampass, NULL, 0);
}
return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag);
@@ -1017,75 +1057,75 @@ BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyL
below)
********************************************************************/
-BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const char *password, enum pdb_value_state flag)
+BOOL pdb_set_plaintext_pw_only (struct samu *sampass, const char *password, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (password) {
- if (sampass->private_u.plaintext_pw!=NULL)
- memset(sampass->private_u.plaintext_pw,'\0',strlen(sampass->private_u.plaintext_pw)+1);
+ if (sampass->plaintext_pw!=NULL)
+ memset(sampass->plaintext_pw,'\0',strlen(sampass->plaintext_pw)+1);
- sampass->private_u.plaintext_pw = talloc_strdup(sampass->mem_ctx, password);
+ sampass->plaintext_pw = talloc_strdup(sampass, password);
- if (!sampass->private_u.plaintext_pw) {
+ if (!sampass->plaintext_pw) {
DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
return False;
}
} else {
- sampass->private_u.plaintext_pw = NULL;
+ sampass->plaintext_pw = NULL;
}
return pdb_set_init_flags(sampass, PDB_PLAINTEXT_PW, flag);
}
-BOOL pdb_set_bad_password_count(SAM_ACCOUNT *sampass, uint16 bad_password_count, enum pdb_value_state flag)
+BOOL pdb_set_bad_password_count(struct samu *sampass, uint16 bad_password_count, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.bad_password_count = bad_password_count;
+ sampass->bad_password_count = bad_password_count;
return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag);
}
-BOOL pdb_set_logon_count(SAM_ACCOUNT *sampass, uint16 logon_count, enum pdb_value_state flag)
+BOOL pdb_set_logon_count(struct samu *sampass, uint16 logon_count, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.logon_count = logon_count;
+ sampass->logon_count = logon_count;
return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag);
}
-BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag)
+BOOL pdb_set_unknown_6 (struct samu *sampass, uint32 unkn, enum pdb_value_state flag)
{
if (!sampass)
return False;
- sampass->private_u.unknown_6 = unkn;
+ sampass->unknown_6 = unkn;
return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
}
-BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
+BOOL pdb_set_hours (struct samu *sampass, const uint8 *hours, enum pdb_value_state flag)
{
if (!sampass)
return False;
if (!hours) {
- memset ((char *)sampass->private_u.hours, 0, MAX_HOURS_LEN);
+ memset ((char *)sampass->hours, 0, MAX_HOURS_LEN);
return True;
}
- memcpy (sampass->private_u.hours, hours, MAX_HOURS_LEN);
+ memcpy (sampass->hours, hours, MAX_HOURS_LEN);
return pdb_set_init_flags(sampass, PDB_HOURS, flag);
}
-BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data,
+BOOL pdb_set_backend_private_data (struct samu *sampass, void *private_data,
void (*free_fn)(void **),
const struct pdb_methods *my_methods,
enum pdb_value_state flag)
@@ -1093,13 +1133,15 @@ BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data,
if (!sampass)
return False;
- if (sampass->private_u.backend_private_data && sampass->private_u.backend_private_data_free_fn) {
- sampass->private_u.backend_private_data_free_fn(&sampass->private_u.backend_private_data);
+ if (sampass->backend_private_data &&
+ sampass->backend_private_data_free_fn) {
+ sampass->backend_private_data_free_fn(
+ &sampass->backend_private_data);
}
- sampass->private_u.backend_private_data = private_data;
- sampass->private_u.backend_private_data_free_fn = free_fn;
- sampass->private_u.backend_private_methods = my_methods;
+ sampass->backend_private_data = private_data;
+ sampass->backend_private_data_free_fn = free_fn;
+ sampass->backend_private_methods = my_methods;
return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag);
}
@@ -1112,7 +1154,7 @@ BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data,
password change.
********************************************************************/
-BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
+BOOL pdb_set_pass_changed_now (struct samu *sampass)
{
uint32 expire;
uint32 min_age;
@@ -1152,7 +1194,7 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
Also sets the last change time to NOW.
********************************************************************/
-BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
+BOOL pdb_set_plaintext_passwd (struct samu *sampass, const char *plaintext)
{
uchar new_lanman_p16[LM_HASH_LEN];
uchar new_nt_p16[NT_HASH_LEN];
@@ -1194,11 +1236,11 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
uint32 current_history_len;
/* We need to make sure we don't have a race condition here - the
account policy history length can change between when the pw_history
- was first loaded into the SAM_ACCOUNT struct and now.... JRA. */
+ was first loaded into the struct samu struct and now.... JRA. */
pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);
if (current_history_len != pwHistLen) {
- /* After closing and reopening SAM_ACCOUNT the history
+ /* After closing and reopening struct samu the history
values will sync up. We can't do this here. */
/* current_history_len > pwHistLen is not a problem - we
@@ -1206,8 +1248,12 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
if (current_history_len < pwHistLen) {
/* Ensure we have space for the needed history. */
- uchar *new_history = TALLOC(sampass->mem_ctx,
+ uchar *new_history = TALLOC(sampass,
pwHistLen*PW_HISTORY_ENTRY_LEN);
+ if (!new_history) {
+ return False;
+ }
+
/* And copy it into the new buffer. */
if (current_history_len) {
memcpy(new_history, pwhistory,
@@ -1247,7 +1293,7 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
}
/* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */
-uint32 pdb_build_fields_present (SAM_ACCOUNT *sampass)
+uint32 pdb_build_fields_present (struct samu *sampass)
{
/* value set to all for testing */
return 0x00ffffff;
diff --git a/source/passdb/pdb_guest.c b/source/passdb/pdb_guest.c
deleted file mode 100644
index 510cf6abc8b..00000000000
--- a/source/passdb/pdb_guest.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 'Guest' password backend for samba
- * Copyright (C) Jelmer Vernooij 2002
- * Copyright (C) Andrew Bartlett 2003
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 675
- * Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-
-/******************************************************************
- Lookup a name in the SAM database
- ******************************************************************/
-
-static NTSTATUS guestsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *sam_account, const char *sname)
-{
- const char *guest_account = lp_guestaccount();
-
- if (!sam_account || !sname) {
- DEBUG(0,("invalid name specified"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!(guest_account && *guest_account)) {
- DEBUG(1, ("NULL guest account!?!?\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!methods) {
- DEBUG(0,("invalid methods\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
- if (!strequal(guest_account, sname)) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- pdb_fill_default_sam(sam_account);
-
- if (!pdb_set_username(sam_account, guest_account, PDB_SET))
- return NT_STATUS_UNSUCCESSFUL;
-
- if (!pdb_set_fullname(sam_account, guest_account, PDB_SET))
- return NT_STATUS_UNSUCCESSFUL;
-
- if (!pdb_set_domain(sam_account, get_global_sam_name(), PDB_DEFAULT))
- return NT_STATUS_UNSUCCESSFUL;
-
- if (!pdb_set_acct_ctrl(sam_account, ACB_NORMAL, PDB_DEFAULT))
- return NT_STATUS_UNSUCCESSFUL;
-
- if (!pdb_set_user_sid_from_rid(sam_account, DOMAIN_USER_RID_GUEST, PDB_SET))
- return NT_STATUS_UNSUCCESSFUL;
-
- if (!pdb_set_group_sid_from_rid(sam_account, DOMAIN_GROUP_RID_GUESTS, PDB_DEFAULT))
- return NT_STATUS_UNSUCCESSFUL;
-
- return NT_STATUS_OK;
-}
-
-
-/***************************************************************************
- Search by rid
- **************************************************************************/
-
-static NTSTATUS guestsam_getsampwrid (struct pdb_methods *methods,
- SAM_ACCOUNT *sam_account, uint32 rid)
-{
- if (rid != DOMAIN_USER_RID_GUEST) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- if (!sam_account) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return guestsam_getsampwnam (methods, sam_account, lp_guestaccount());
-}
-
-static NTSTATUS guestsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
-{
- uint32 rid;
- if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
- return NT_STATUS_NO_SUCH_USER;
-
- return guestsam_getsampwrid(my_methods, user, rid);
-}
-
-
-/***************************************************************************
- Updates a SAM_ACCOUNT
-
- This isn't a particulary practical option for pdb_guest. We certainly don't
- want to twidde the filesystem, so what should we do?
-
- Current plan is to transparently add the account. It should appear
- as if the pdb_guest version was modified, but its actually stored somehwere.
- ****************************************************************************/
-
-static NTSTATUS guestsam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
-{
-#if 1 /* JERRY */
-
- /* apparently thr build farm relies upon this heavior :-( */
-
- return methods->parent->pdb_add_sam_account(methods->parent, newpwd);
-#else
- /* I don't think we should allow any modification of
- the guest account as SID will could messed up with
- the smbpasswd backend --jerry */
-
- return NT_STATUS_NOT_IMPLEMENTED;
-#endif
-}
-
-NTSTATUS pdb_init_guestsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
-{
- NTSTATUS nt_status;
-
- if (!pdb_context) {
- DEBUG(0, ("invalid pdb_context specified\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
- return nt_status;
- }
-
- (*pdb_method)->name = "guestsam";
-
- (*pdb_method)->getsampwnam = guestsam_getsampwnam;
- (*pdb_method)->getsampwsid = guestsam_getsampwsid;
- (*pdb_method)->update_sam_account = guestsam_update_sam_account;
-
- /* we should do no group mapping here */
- (*pdb_method)->getgrsid = pdb_nop_getgrsid;
- (*pdb_method)->getgrgid = pdb_nop_getgrgid;
- (*pdb_method)->getgrnam = pdb_nop_getgrnam;
- (*pdb_method)->add_group_mapping_entry = pdb_nop_add_group_mapping_entry;
- (*pdb_method)->update_group_mapping_entry = pdb_nop_update_group_mapping_entry;
- (*pdb_method)->delete_group_mapping_entry = pdb_nop_delete_group_mapping_entry;
- (*pdb_method)->enum_group_mapping = pdb_nop_enum_group_mapping;
-
-
- /* There's not very much to initialise here */
- return NT_STATUS_OK;
-}
-
-NTSTATUS pdb_guest_init(void)
-{
- return smb_register_passdb(PASSDB_INTERFACE_VERSION, "guest", pdb_init_guestsam);
-}
-
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index 875e264bf01..b3522e33a7f 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Bartlett 2002
Copyright (C) Jelmer Vernooij 2002
Copyright (C) Simo Sorce 2003
+ 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
@@ -25,6 +26,10 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
+/* Cache of latest SAM lookup query */
+
+static struct samu *csamuser = NULL;
+
static struct pdb_init_function_entry *backends = NULL;
static void lazy_initialize_passdb(void)
@@ -35,8 +40,10 @@ static void lazy_initialize_passdb(void)
initialized = True;
}
-static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name);
-
+static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
+ const char **name,
+ enum SID_NAME_USE *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
@@ -46,7 +53,7 @@ static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name);
time, such LDAP with a missing attribute would produce.
********************************************************************/
-static void pdb_force_pw_initialization(SAM_ACCOUNT *pass)
+static void pdb_force_pw_initialization(struct samu *pass)
{
const uint8 *lm_pwd, *nt_pwd;
@@ -108,7 +115,7 @@ NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function in
return NT_STATUS_OK;
}
-static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name)
+struct pdb_init_function_entry *pdb_find_backend_entry(const char *name)
{
struct pdb_init_function_entry *entry = backends;
@@ -120,1334 +127,1164 @@ static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name)
return NULL;
}
-static NTSTATUS context_setsampwent(struct pdb_context *context, BOOL update, uint16 acb_mask)
+/******************************************************************
+ Make a pdb_methods from scratch
+ *******************************************************************/
+
+NTSTATUS make_pdb_method_name(struct pdb_methods **methods, const char *selected)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ char *module_name = smb_xstrdup(selected);
+ char *module_location = NULL, *p;
+ struct pdb_init_function_entry *entry;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- if (!context) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
+ lazy_initialize_passdb();
- context->pwent_methods = context->pdb_methods;
+ p = strchr(module_name, ':');
- if (!context->pwent_methods) {
- /* No passdbs at all */
- return ret;
+ if (p) {
+ *p = 0;
+ module_location = p+1;
+ trim_char(module_location, ' ', ' ');
}
- while (NT_STATUS_IS_ERR(ret = context->pwent_methods->setsampwent(context->pwent_methods, update, acb_mask))) {
- context->pwent_methods = context->pwent_methods->next;
- if (context->pwent_methods == NULL)
- return NT_STATUS_UNSUCCESSFUL;
- }
- return ret;
-}
+ trim_char(module_name, ' ', ' ');
-static void context_endsampwent(struct pdb_context *context)
-{
- if ((!context)){
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return;
- }
- if (context->pwent_methods && context->pwent_methods->endsampwent)
- context->pwent_methods->endsampwent(context->pwent_methods);
+ DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
- /* So we won't get strange data when calling getsampwent now */
- context->pwent_methods = NULL;
-}
+ entry = pdb_find_backend_entry(module_name);
+
+ /* Try to find a module that contains this module */
+ if (!entry) {
+ DEBUG(2,("No builtin backend found, trying to load plugin\n"));
+ if(NT_STATUS_IS_OK(smb_probe_module("pdb", module_name)) && !(entry = pdb_find_backend_entry(module_name))) {
+ DEBUG(0,("Plugin is available, but doesn't register passdb backend %s\n", module_name));
+ SAFE_FREE(module_name);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* No such backend found */
+ if(!entry) {
+ DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name));
+ SAFE_FREE(module_name);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
-static NTSTATUS context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ DEBUG(5,("Found pdb backend %s\n", module_name));
- if ((!context) || (!context->pwent_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !NT_STATUS_IS_OK( nt_status = entry->init(methods, module_location) ) ) {
+ DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n",
+ selected, nt_errstr(nt_status)));
+ SAFE_FREE(module_name);
+ return nt_status;
}
- /* Loop until we find something useful */
- while (NT_STATUS_IS_ERR(ret = context->pwent_methods->getsampwent(context->pwent_methods, user))) {
- context->pwent_methods->endsampwent(context->pwent_methods);
+ SAFE_FREE(module_name);
- context->pwent_methods = context->pwent_methods->next;
+ DEBUG(5,("pdb backend %s has a valid init\n", selected));
- /* All methods are checked now. There are no more entries */
- if (context->pwent_methods == NULL)
- return ret;
-
- context->pwent_methods->setsampwent(context->pwent_methods, False, 0);
- }
- user->methods = context->pwent_methods;
- pdb_force_pw_initialization(user);
- return ret;
+ return nt_status;
}
-static NTSTATUS context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
+/******************************************************************
+ Return an already initialised pdn_methods structure
+*******************************************************************/
+
+static struct pdb_methods *pdb_get_methods_reload( BOOL reload )
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ static struct pdb_methods *pdb = NULL;
- struct pdb_methods *curmethods;
- if ((!context)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( pdb && reload ) {
+ pdb->free_private_data( &(pdb->private_data) );
+ if ( !NT_STATUS_IS_OK( make_pdb_method_name( &pdb, lp_passdb_backend() ) ) ) {
+ return NULL;
+ }
}
- curmethods = context->pdb_methods;
- while (curmethods){
- if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) {
- pdb_force_pw_initialization(sam_acct);
- sam_acct->methods = curmethods;
- return ret;
+
+ if ( !pdb ) {
+ if ( !NT_STATUS_IS_OK( make_pdb_method_name( &pdb, lp_passdb_backend() ) ) ) {
+ return NULL;
}
- curmethods = curmethods->next;
}
- return ret;
+ return pdb;
}
-static NTSTATUS context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
+static struct pdb_methods *pdb_get_methods(void)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ return pdb_get_methods_reload(False);
+}
- struct pdb_methods *curmethods;
- if ((!context)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
-
- curmethods = context->pdb_methods;
+/******************************************************************
+ Backward compatibility functions for the original passdb interface
+*******************************************************************/
- while (curmethods){
- if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) {
- pdb_force_pw_initialization(sam_acct);
- sam_acct->methods = curmethods;
- return ret;
- }
- curmethods = curmethods->next;
+BOOL pdb_setsampwent(BOOL update, uint16 acb_mask)
+{
+ struct pdb_methods *pdb = pdb_get_methods();
+
+ if ( !pdb ) {
+ return False;
}
- return ret;
+ return NT_STATUS_IS_OK(pdb->setsampwent(pdb, update, acb_mask));
}
-static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+void pdb_endsampwent(void)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- const uint8 *lm_pw, *nt_pw;
- uint16 acb_flags;
-
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
+ struct pdb_methods *pdb = pdb_get_methods();
- /* disable acccounts with no passwords (that has not
- been allowed by the ACB_PWNOTREQ bit */
-
- lm_pw = pdb_get_lanman_passwd( sam_acct );
- nt_pw = pdb_get_nt_passwd( sam_acct );
- acb_flags = pdb_get_acct_ctrl( sam_acct );
- if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) {
- acb_flags |= ACB_DISABLED;
- pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_CHANGED );
+ if ( !pdb ) {
+ return;
}
-
- /** @todo This is where a 're-read on add' should be done */
- /* We now add a new account to the first database listed.
- * Should we? */
- return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct);
+ pdb->endsampwent(pdb);
}
-static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+BOOL pdb_getsampwent(struct samu *user)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- const uint8 *lm_pw, *nt_pw;
- uint16 acb_flags;
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!context) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return False;
}
- if (!sam_acct || !sam_acct->methods){
- DEBUG(0, ("invalid sam_acct specified\n"));
- return ret;
+ if ( !NT_STATUS_IS_OK(pdb->getsampwent(pdb, user) ) ) {
+ return False;
}
- /* disable acccounts with no passwords (that has not
- been allowed by the ACB_PWNOTREQ bit */
-
- lm_pw = pdb_get_lanman_passwd( sam_acct );
- nt_pw = pdb_get_nt_passwd( sam_acct );
- acb_flags = pdb_get_acct_ctrl( sam_acct );
- if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) {
- acb_flags |= ACB_DISABLED;
- pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_CHANGED );
- }
-
- /** @todo This is where a 're-read on update' should be done */
+ pdb_force_pw_initialization( user );
- return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct);
+ return True;
}
-static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+BOOL pdb_getsampwnam(struct samu *sam_acct, const char *username)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- struct pdb_methods *pdb_selected;
- if (!context) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return False;
}
- if (!sam_acct->methods){
- pdb_selected = context->pdb_methods;
- /* There's no passdb backend specified for this account.
- * Try to delete it in every passdb available
- * Needed to delete accounts in smbpasswd that are not
- * in /etc/passwd.
- */
- while (pdb_selected){
- if (NT_STATUS_IS_OK(ret = pdb_selected->delete_sam_account(pdb_selected, sam_acct))) {
- return ret;
- }
- pdb_selected = pdb_selected->next;
- }
- return ret;
+ if (!NT_STATUS_IS_OK(pdb->getsampwnam(pdb, sam_acct, username))) {
+ return False;
}
- if (!sam_acct->methods->delete_sam_account){
- DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n"));
- return ret;
+ if ( csamuser ) {
+ TALLOC_FREE(csamuser);
}
+
+ pdb_force_pw_initialization( sam_acct );
- return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
+ if ( (csamuser = samu_new( NULL )) != NULL ) {
+ pdb_copy_sam_account(csamuser, sam_acct);
+ }
+
+ return True;
}
-static NTSTATUS context_rename_sam_account(struct pdb_context *context, SAM_ACCOUNT *oldname, const char *newname)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+/**********************************************************************
+**********************************************************************/
- struct pdb_methods *pdb_selected;
- if (!context) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+BOOL guest_user_info( struct samu *user )
+{
+ struct passwd *pwd;
+ NTSTATUS result;
+ const char *guestname = lp_guestaccount();
+
+ if ( !(pwd = getpwnam_alloc( NULL, guestname ) ) ) {
+ DEBUG(0,("guest_user_info: Unable to locate guest account [%s]!\n",
+ guestname));
+ return False;
}
+
+ result = samu_set_unix(user, pwd );
- if (!oldname->methods){
- pdb_selected = context->pdb_methods;
- /* There's no passdb backend specified for this account.
- * Try to delete it in every passdb available
- * Needed to delete accounts in smbpasswd that are not
- * in /etc/passwd.
- */
- while (pdb_selected){
- if (NT_STATUS_IS_OK(ret = pdb_selected->rename_sam_account(pdb_selected, oldname, newname))) {
- return ret;
- }
- pdb_selected = pdb_selected->next;
- }
- return ret;
- }
+ TALLOC_FREE( pwd );
- if (!oldname->methods->rename_sam_account){
- DEBUG(0,("invalid oldname->methods->rename_sam_account\n"));
- return ret;
- }
-
- return oldname->methods->rename_sam_account(oldname->methods, oldname, newname);
+ return NT_STATUS_IS_OK( result );
}
+/**********************************************************************
+**********************************************************************/
-static NTSTATUS context_update_login_attempts(struct pdb_context *context,
- SAM_ACCOUNT *sam_acct, BOOL success)
+BOOL pdb_getsampwsid(struct samu *sam_acct, const DOM_SID *sid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- if (!context) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
+ struct pdb_methods *pdb;
+ uint32 rid;
- if (!sam_acct || !sam_acct->methods){
- DEBUG(0, ("invalid sam_acct specified\n"));
- return ret;
+ if ( !(pdb = pdb_get_methods()) ) {
+ return False;
}
- return sam_acct->methods->update_login_attempts(sam_acct->methods, sam_acct, success);
-}
+ /* hard code the Guest RID of 501 */
-static NTSTATUS context_getgrsid(struct pdb_context *context,
- GROUP_MAP *map, DOM_SID sid)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ if ( !sid_peek_check_rid( get_global_sam_sid(), sid, &rid ) )
+ return False;
- struct pdb_methods *curmethods;
- if ((!context)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
- curmethods = context->pdb_methods;
- while (curmethods){
- ret = curmethods->getgrsid(curmethods, map, sid);
- if (NT_STATUS_IS_OK(ret)) {
- map->methods = curmethods;
- return ret;
- }
- curmethods = curmethods->next;
+ if ( rid == DOMAIN_USER_RID_GUEST ) {
+ DEBUG(6,("pdb_getsampwsid: Building guest account\n"));
+ return guest_user_info( sam_acct );
}
+
+ /* check the cache first */
+
+ if ( csamuser && sid_equal(sid, pdb_get_user_sid(csamuser) ) )
+ return pdb_copy_sam_account(sam_acct, csamuser);
- return ret;
+ return NT_STATUS_IS_OK(pdb->getsampwsid(pdb, sam_acct, sid));
}
-static NTSTATUS context_getgrgid(struct pdb_context *context,
- GROUP_MAP *map, gid_t gid)
+static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
+ TALLOC_CTX *tmp_ctx, const char *name,
+ uint32 acb_info, uint32 *rid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct samu *sam_pass;
+ NTSTATUS status;
+ struct passwd *pwd;
- struct pdb_methods *curmethods;
- if ((!context)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
- curmethods = context->pdb_methods;
- while (curmethods){
- ret = curmethods->getgrgid(curmethods, map, gid);
- if (NT_STATUS_IS_OK(ret)) {
- map->methods = curmethods;
- return ret;
- }
- curmethods = curmethods->next;
+ if ((sam_pass = samu_new(tmp_ctx)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- return ret;
-}
+ if ( !(pwd = Get_Pwnam_alloc(tmp_ctx, name)) ) {
+ pstring add_script;
+ int add_ret;
-static NTSTATUS context_getgrnam(struct pdb_context *context,
- GROUP_MAP *map, const char *name)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ if ((acb_info & ACB_NORMAL) && name[strlen(name)-1] != '$') {
+ pstrcpy(add_script, lp_adduser_script());
+ } else {
+ pstrcpy(add_script, lp_addmachine_script());
+ }
- struct pdb_methods *curmethods;
- if ((!context)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
- curmethods = context->pdb_methods;
- while (curmethods){
- ret = curmethods->getgrnam(curmethods, map, name);
- if (NT_STATUS_IS_OK(ret)) {
- map->methods = curmethods;
- return ret;
+ if (add_script[0] == '\0') {
+ DEBUG(3, ("Could not find user %s and no add script "
+ "defined\n", name));
+ return NT_STATUS_NO_SUCH_USER;
}
- curmethods = curmethods->next;
+
+ all_string_sub(add_script, "%u", name, sizeof(add_script));
+ add_ret = smbrun(add_script,NULL);
+ DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the command `%s' gave %d\n",
+ add_script, add_ret));
+ flush_pwnam_cache();
+
+ pwd = Get_Pwnam_alloc(tmp_ctx, name);
}
- return ret;
-}
+ /* we have a valid SID coming out of this call */
-static NTSTATUS context_add_group_mapping_entry(struct pdb_context *context,
- GROUP_MAP *map)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ status = samu_alloc_rid_unix( sam_pass, pwd );
+
+ TALLOC_FREE( pwd );
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("pdb_default_create_user: failed to create a new user structure: %s\n", nt_errstr(status)));
+ return status;
}
- return context->pdb_methods->add_group_mapping_entry(context->pdb_methods,
- map);
-}
+ if (!sid_peek_check_rid(get_global_sam_sid(),
+ pdb_get_user_sid(sam_pass), rid)) {
+ DEBUG(0, ("Could not get RID of fresh user\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
-static NTSTATUS context_update_group_mapping_entry(struct pdb_context *context,
- GROUP_MAP *map)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ /* Disable the account on creation, it does not have a reasonable password yet. */
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
+ acb_info |= ACB_DISABLED;
- return context->
- pdb_methods->update_group_mapping_entry(context->pdb_methods, map);
-}
+ pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
-static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context,
- DOM_SID sid)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ status = pdb_add_sam_account(sam_pass);
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
- }
+ TALLOC_FREE(sam_pass);
- return context->
- pdb_methods->delete_group_mapping_entry(context->pdb_methods, sid);
+ return status;
}
-static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
- enum SID_NAME_USE sid_name_use,
- GROUP_MAP **pp_rmap, size_t *p_num_entries,
- BOOL unix_only)
+NTSTATUS pdb_create_user(TALLOC_CTX *mem_ctx, const char *name, uint32 flags,
+ uint32 *rid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return context->pdb_methods->enum_group_mapping(context->pdb_methods,
- sid_name_use, pp_rmap,
- p_num_entries, unix_only);
+ return pdb->create_user(pdb, mem_ctx, name, flags, rid);
}
-static NTSTATUS context_enum_group_members(struct pdb_context *context,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *group,
- uint32 **pp_member_rids,
- size_t *p_num_members)
+/****************************************************************************
+ Delete a UNIX user on demand.
+****************************************************************************/
+
+static int smb_delete_user(const char *unix_user)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ pstring del_script;
+ int ret;
+
+ /* safety check */
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( strequal( unix_user, "root" ) ) {
+ DEBUG(0,("smb_delete_user: Refusing to delete local system root account!\n"));
+ return -1;
}
- return context->pdb_methods->enum_group_members(context->pdb_methods,
- mem_ctx, group,
- pp_member_rids,
- p_num_members);
+ pstrcpy(del_script, lp_deluser_script());
+ if (! *del_script)
+ return -1;
+ all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
+ ret = smbrun(del_script,NULL);
+ flush_pwnam_cache();
+ DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
+
+ return ret;
}
-static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
- const char *username,
- gid_t primary_gid,
- DOM_SID **pp_sids, gid_t **pp_gids,
- size_t *p_num_groups)
+static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ struct samu *sam_acct)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS status;
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ status = pdb_delete_sam_account(sam_acct);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- return context->pdb_methods->
- enum_group_memberships(context->pdb_methods, username,
- primary_gid, pp_sids, pp_gids, p_num_groups);
+ /*
+ * Now delete the unix side ....
+ * note: we don't check if the delete really happened as the script is
+ * not necessary present and maybe the sysadmin doesn't want to delete
+ * the unix side
+ */
+ smb_delete_user( pdb_get_username(sam_acct) );
+
+ return status;
}
-static NTSTATUS context_find_alias(struct pdb_context *context,
- const char *name, DOM_SID *sid)
+NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, struct samu *sam_acct)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
+ uid_t uid = -1;
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return context->pdb_methods->find_alias(context->pdb_methods,
- name, sid);
-}
+ /* sanity check to make sure we don't delete root */
-static NTSTATUS context_create_alias(struct pdb_context *context,
- const char *name, uint32 *rid)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ if ( !sid_to_uid( pdb_get_user_sid(sam_acct), &uid ) ) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( uid == 0 ) {
+ return NT_STATUS_ACCESS_DENIED;
}
- return context->pdb_methods->create_alias(context->pdb_methods,
- name, rid);
+ return pdb->delete_user(pdb, mem_ctx, sam_acct);
}
-static NTSTATUS context_delete_alias(struct pdb_context *context,
- const DOM_SID *sid)
+NTSTATUS pdb_add_sam_account(struct samu *sam_acct)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
-
- return context->pdb_methods->delete_alias(context->pdb_methods, sid);
+
+ return pdb->add_sam_account(pdb, sam_acct);
}
-static NTSTATUS context_get_aliasinfo(struct pdb_context *context,
- const DOM_SID *sid,
- struct acct_info *info)
+NTSTATUS pdb_update_sam_account(struct samu *sam_acct)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
+
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if (csamuser != NULL) {
+ TALLOC_FREE(csamuser);
+ csamuser = NULL;
}
- return context->pdb_methods->get_aliasinfo(context->pdb_methods,
- sid, info);
+ return pdb->update_sam_account(pdb, sam_acct);
}
-static NTSTATUS context_set_aliasinfo(struct pdb_context *context,
- const DOM_SID *sid,
- struct acct_info *info)
+NTSTATUS pdb_delete_sam_account(struct samu *sam_acct)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (csamuser != NULL) {
+ TALLOC_FREE(csamuser);
+ csamuser = NULL;
}
- return context->pdb_methods->set_aliasinfo(context->pdb_methods,
- sid, info);
+ return pdb->delete_sam_account(pdb, sam_acct);
}
-static NTSTATUS context_add_aliasmem(struct pdb_context *context,
- const DOM_SID *alias,
- const DOM_SID *member)
+NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
+ uid_t uid;
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return NT_STATUS_NOT_IMPLEMENTED;
}
- return context->pdb_methods->add_aliasmem(context->pdb_methods,
- alias, member);
-}
-
-static NTSTATUS context_del_aliasmem(struct pdb_context *context,
- const DOM_SID *alias,
- const DOM_SID *member)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if (csamuser != NULL) {
+ TALLOC_FREE(csamuser);
+ csamuser = NULL;
}
- return context->pdb_methods->del_aliasmem(context->pdb_methods,
- alias, member);
-}
-
-static NTSTATUS context_enum_aliasmem(struct pdb_context *context,
- const DOM_SID *alias, DOM_SID **pp_members,
- size_t *p_num)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ /* sanity check to make sure we don't rename root */
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !sid_to_uid( pdb_get_user_sid(oldname), &uid ) ) {
+ return NT_STATUS_NO_SUCH_USER;
}
- return context->pdb_methods->enum_aliasmem(context->pdb_methods,
- alias, pp_members, p_num);
-}
-
-static NTSTATUS context_enum_alias_memberships(struct pdb_context *context,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *domain_sid,
- const DOM_SID *members,
- size_t num_members,
- uint32 **pp_alias_rids,
- size_t *p_num_alias_rids)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( uid == 0 ) {
+ return NT_STATUS_ACCESS_DENIED;
}
- return context->pdb_methods->
- enum_alias_memberships(context->pdb_methods, mem_ctx,
- domain_sid, members, num_members,
- pp_alias_rids, p_num_alias_rids);
+ return pdb->rename_sam_account(pdb, oldname, newname);
}
-static NTSTATUS context_lookup_rids(struct pdb_context *context,
- const DOM_SID *domain_sid,
- size_t num_rids,
- uint32 *rids,
- const char **pp_names,
- uint32 *pp_attrs)
+NTSTATUS pdb_update_login_attempts(struct samu *sam_acct, BOOL success)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return NT_STATUS_NOT_IMPLEMENTED;
}
- return context->pdb_methods->lookup_rids(context->pdb_methods,
- domain_sid, num_rids,
- rids, pp_names, pp_attrs);
+ return pdb->update_login_attempts(pdb, sam_acct, success);
}
-static NTSTATUS context_get_account_policy(struct pdb_context *context,
- int policy_index, uint32 *value)
+BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return False;
}
- return context->pdb_methods->get_account_policy(context->pdb_methods,
- policy_index, value);
+ return NT_STATUS_IS_OK(pdb->getgrsid(pdb, map, sid));
}
-static NTSTATUS context_set_account_policy(struct pdb_context *context,
- int policy_index, uint32 value)
+BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return False;
}
- return context->pdb_methods->set_account_policy(context->pdb_methods,
- policy_index, value);
+ return NT_STATUS_IS_OK(pdb->getgrgid(pdb, map, gid));
}
-static NTSTATUS context_get_seq_num(struct pdb_context *context, time_t *seq_num)
+BOOL pdb_getgrnam(GROUP_MAP *map, const char *name)
{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ struct pdb_methods *pdb = pdb_get_methods();
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return ret;
+ if ( !pdb ) {
+ return False;
}
- return context->pdb_methods->get_seq_num(context->pdb_methods, seq_num);
+ return NT_STATUS_IS_OK(pdb->getgrnam(pdb, map, name));
}
-
-/******************************************************************
- Free and cleanup a pdb context, any associated data and anything
- that the attached modules might have associated.
- *******************************************************************/
-static void free_pdb_context(struct pdb_context **context)
+static NTSTATUS pdb_default_create_dom_group(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const char *name,
+ uint32 *rid)
{
- struct pdb_methods *pdb_selected = (*context)->pdb_methods;
+ DOM_SID group_sid;
+ struct group *grp;
- while (pdb_selected){
- if(pdb_selected->free_private_data)
- pdb_selected->free_private_data(&(pdb_selected->private_data));
- pdb_selected = pdb_selected->next;
- }
+ grp = getgrnam(name);
- talloc_destroy((*context)->mem_ctx);
- *context = NULL;
-}
+ if (grp == NULL) {
+ gid_t gid;
-static BOOL context_search_users(struct pdb_context *context,
- struct pdb_search *search, uint16 acct_flags)
-{
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return False;
+ if (smb_create_group(name, &gid) != 0) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ grp = getgrgid(gid);
}
- return context->pdb_methods->search_users(context->pdb_methods,
- search, acct_flags);
-}
+ if (grp == NULL) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
-static BOOL context_search_groups(struct pdb_context *context,
- struct pdb_search *search)
-{
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return False;
+ if (pdb_rid_algorithm()) {
+ *rid = pdb_gid_to_group_rid( grp->gr_gid );
+ } else {
+ if (!pdb_new_rid(rid)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
}
- return context->pdb_methods->search_groups(context->pdb_methods,
- search);
+ sid_compose(&group_sid, get_global_sam_sid(), *rid);
+
+ return add_initial_entry(grp->gr_gid, sid_string_static(&group_sid),
+ SID_NAME_DOM_GRP, name, NULL);
}
-static BOOL context_search_aliases(struct pdb_context *context,
- struct pdb_search *search,
- const DOM_SID *sid)
+NTSTATUS pdb_create_dom_group(TALLOC_CTX *mem_ctx, const char *name,
+ uint32 *rid)
{
- if ((!context) || (!context->pdb_methods)) {
- DEBUG(0, ("invalid pdb_context specified!\n"));
- return False;
+ struct pdb_methods *pdb = pdb_get_methods();
+
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return context->pdb_methods->search_aliases(context->pdb_methods,
- search, sid);
+ return pdb->create_dom_group(pdb, mem_ctx, name, rid);
}
-/******************************************************************
- Make a pdb_methods from scratch
- *******************************************************************/
-
-static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
+static NTSTATUS pdb_default_delete_dom_group(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ uint32 rid)
{
- char *module_name = smb_xstrdup(selected);
- char *module_location = NULL, *p;
- struct pdb_init_function_entry *entry;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-
- lazy_initialize_passdb();
+ DOM_SID group_sid;
+ GROUP_MAP map;
+ NTSTATUS status;
+ struct group *grp;
+ const char *grp_name;
- p = strchr(module_name, ':');
+ sid_compose(&group_sid, get_global_sam_sid(), rid);
- if (p) {
- *p = 0;
- module_location = p+1;
- trim_char(module_location, ' ', ' ');
+ if (!get_domain_group_from_sid(group_sid, &map)) {
+ DEBUG(10, ("Could not find group for rid %d\n", rid));
+ return NT_STATUS_NO_SUCH_GROUP;
}
- trim_char(module_name, ' ', ' ');
+ /* We need the group name for the smb_delete_group later on */
-
- DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
-
- entry = pdb_find_backend_entry(module_name);
-
- /* Try to find a module that contains this module */
- if (!entry) {
- DEBUG(2,("No builtin backend found, trying to load plugin\n"));
- if(NT_STATUS_IS_OK(smb_probe_module("pdb", module_name)) && !(entry = pdb_find_backend_entry(module_name))) {
- DEBUG(0,("Plugin is available, but doesn't register passdb backend %s\n", module_name));
- SAFE_FREE(module_name);
- return NT_STATUS_UNSUCCESSFUL;
- }
- }
-
- /* No such backend found */
- if(!entry) {
- DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name));
- SAFE_FREE(module_name);
- return NT_STATUS_INVALID_PARAMETER;
+ if (map.gid == (gid_t)-1) {
+ return NT_STATUS_NO_SUCH_GROUP;
}
- DEBUG(5,("Found pdb backend %s\n", module_name));
- nt_status = entry->init(context, methods, module_location);
- if (NT_STATUS_IS_OK(nt_status)) {
- DEBUG(5,("pdb backend %s has a valid init\n", selected));
- } else {
- DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
+ grp = getgrgid(map.gid);
+ if (grp == NULL) {
+ return NT_STATUS_NO_SUCH_GROUP;
}
- SAFE_FREE(module_name);
- return nt_status;
-}
-/******************************************************************
- Make a pdb_context from scratch.
- *******************************************************************/
+ /* Copy the name, no idea what pdb_delete_group_mapping_entry does.. */
-static NTSTATUS make_pdb_context(struct pdb_context **context)
-{
- TALLOC_CTX *mem_ctx;
-
- mem_ctx = talloc_init("pdb_context internal allocation context");
-
- if (!mem_ctx) {
- DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
+ grp_name = talloc_strdup(mem_ctx, grp->gr_name);
+ if (grp_name == NULL) {
return NT_STATUS_NO_MEMORY;
- }
+ }
- *context = TALLOC_P(mem_ctx, struct pdb_context);
- if (!*context) {
- DEBUG(0, ("make_pdb_context: talloc failed!\n"));
- return NT_STATUS_NO_MEMORY;
+ status = pdb_delete_group_mapping_entry(group_sid);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- ZERO_STRUCTP(*context);
-
- (*context)->mem_ctx = mem_ctx;
-
- (*context)->pdb_setsampwent = context_setsampwent;
- (*context)->pdb_endsampwent = context_endsampwent;
- (*context)->pdb_getsampwent = context_getsampwent;
- (*context)->pdb_getsampwnam = context_getsampwnam;
- (*context)->pdb_getsampwsid = context_getsampwsid;
- (*context)->pdb_add_sam_account = context_add_sam_account;
- (*context)->pdb_update_sam_account = context_update_sam_account;
- (*context)->pdb_delete_sam_account = context_delete_sam_account;
- (*context)->pdb_rename_sam_account = context_rename_sam_account;
- (*context)->pdb_update_login_attempts = context_update_login_attempts;
- (*context)->pdb_getgrsid = context_getgrsid;
- (*context)->pdb_getgrgid = context_getgrgid;
- (*context)->pdb_getgrnam = context_getgrnam;
- (*context)->pdb_add_group_mapping_entry = context_add_group_mapping_entry;
- (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
- (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
- (*context)->pdb_enum_group_mapping = context_enum_group_mapping;
- (*context)->pdb_enum_group_members = context_enum_group_members;
- (*context)->pdb_enum_group_memberships = context_enum_group_memberships;
-
- (*context)->pdb_find_alias = context_find_alias;
- (*context)->pdb_create_alias = context_create_alias;
- (*context)->pdb_delete_alias = context_delete_alias;
- (*context)->pdb_get_aliasinfo = context_get_aliasinfo;
- (*context)->pdb_set_aliasinfo = context_set_aliasinfo;
- (*context)->pdb_add_aliasmem = context_add_aliasmem;
- (*context)->pdb_del_aliasmem = context_del_aliasmem;
- (*context)->pdb_enum_aliasmem = context_enum_aliasmem;
- (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
- (*context)->pdb_lookup_rids = context_lookup_rids;
-
- (*context)->pdb_get_account_policy = context_get_account_policy;
- (*context)->pdb_set_account_policy = context_set_account_policy;
-
- (*context)->pdb_get_seq_num = context_get_seq_num;
-
- (*context)->pdb_search_users = context_search_users;
- (*context)->pdb_search_groups = context_search_groups;
- (*context)->pdb_search_aliases = context_search_aliases;
-
- (*context)->free_fn = free_pdb_context;
+ /* Don't check the result of smb_delete_group */
+
+ smb_delete_group(grp_name);
return NT_STATUS_OK;
}
+NTSTATUS pdb_delete_dom_group(TALLOC_CTX *mem_ctx, uint32 rid)
+{
+ struct pdb_methods *pdb = pdb_get_methods();
-/******************************************************************
- Make a pdb_context, given an array of strings
- *******************************************************************/
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
-NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected)
+ return pdb->delete_dom_group(pdb, mem_ctx, rid);
+}
+
+NTSTATUS pdb_add_group_mapping_entry(GROUP_MAP *map)
{
- int i = 0;
- struct pdb_methods *curmethods, *tmpmethods;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- BOOL have_guest = False;
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
- return nt_status;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- if (!selected) {
- DEBUG(0, ("ERROR: empty passdb backend list!\n"));
- return nt_status;
- }
+ return pdb->add_group_mapping_entry(pdb, map);
+}
- while (selected[i]){
- if (strcmp(selected[i], "guest") == 0) {
- have_guest = True;
- }
- /* Try to initialise pdb */
- DEBUG(5,("Trying to load: %s\n", selected[i]));
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
- DEBUG(1, ("Loading %s failed!\n", selected[i]));
- free_pdb_context(context);
- return nt_status;
- }
- curmethods->parent = *context;
- DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
- i++;
+NTSTATUS pdb_update_group_mapping_entry(GROUP_MAP *map)
+{
+ struct pdb_methods *pdb = pdb_get_methods();
+
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- if (have_guest)
- return NT_STATUS_OK;
+ return pdb->update_group_mapping_entry(pdb, map);
+}
- if ( (lp_guestaccount() == NULL) ||
- (*lp_guestaccount() == '\0') ) {
- /* We explicitly don't want guest access. No idea what
- else that breaks, but be it that way. */
- return NT_STATUS_OK;
- }
+NTSTATUS pdb_delete_group_mapping_entry(DOM_SID sid)
+{
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods,
- *context,
- "guest"))) {
- DEBUG(1, ("Loading guest module failed!\n"));
- free_pdb_context(context);
- return nt_status;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- curmethods->parent = *context;
- DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
-
- return NT_STATUS_OK;
+ return pdb->delete_group_mapping_entry(pdb, sid);
}
-/******************************************************************
- Make a pdb_context, given a text string.
- *******************************************************************/
-
-NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected)
+BOOL pdb_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)
{
- NTSTATUS ret;
- char **newsel = str_list_make(selected, NULL);
- ret = make_pdb_context_list(context, (const char **)newsel);
- str_list_free(&newsel);
- return ret;
-}
+ struct pdb_methods *pdb = pdb_get_methods();
-/******************************************************************
- Return an already initialised pdb_context, to facilitate backward
- compatibility (see functions below).
-*******************************************************************/
+ if ( !pdb ) {
+ return False;
+ }
-static struct pdb_context *pdb_get_static_context(BOOL reload)
+ return NT_STATUS_IS_OK(pdb-> enum_group_mapping(pdb, sid, sid_name_use,
+ pp_rmap, p_num_entries, unix_only));
+}
+
+NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ uint32 **pp_member_rids,
+ size_t *p_num_members)
{
- static struct pdb_context *pdb_context = NULL;
+ struct pdb_methods *pdb = pdb_get_methods();
+ NTSTATUS result;
- if ((pdb_context) && (reload)) {
- pdb_context->free_fn(&pdb_context);
- if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
- return NULL;
- }
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- if (!pdb_context) {
- if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
- return NULL;
+ result = pdb->enum_group_members(pdb, mem_ctx,
+ sid, pp_member_rids, p_num_members);
+
+ /* special check for rid 513 */
+
+ if ( !NT_STATUS_IS_OK( result ) ) {
+ uint32 rid;
+
+ sid_peek_rid( sid, &rid );
+
+ if ( rid == DOMAIN_GROUP_RID_USERS ) {
+ *p_num_members = 0;
+ *pp_member_rids = NULL;
+
+ return NT_STATUS_OK;
}
}
-
- return pdb_context;
+
+ return result;
}
-/******************************************************************
- Backward compatibility functions for the original passdb interface
-*******************************************************************/
-
-BOOL pdb_setsampwent(BOOL update, uint16 acb_mask)
+NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, struct samu *user,
+ DOM_SID **pp_sids, gid_t **pp_gids,
+ size_t *p_num_groups)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_setsampwent(pdb_context, update, acb_mask));
+ return pdb->enum_group_memberships(
+ pdb, mem_ctx, user,
+ pp_sids, pp_gids, p_num_groups);
}
-void pdb_endsampwent(void)
+static NTSTATUS pdb_default_set_unix_primary_group(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ struct samu *sampass)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct group *grp;
+ gid_t gid;
- if (!pdb_context) {
- return;
+ if (!sid_to_gid(pdb_get_group_sid(sampass), &gid) ||
+ (grp = getgrgid(gid)) == NULL) {
+ return NT_STATUS_INVALID_PRIMARY_GROUP;
}
- pdb_context->pdb_endsampwent(pdb_context);
+ if (smb_set_primary_group(grp->gr_name,
+ pdb_get_username(sampass)) != 0) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
}
-BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+NTSTATUS pdb_set_unix_primary_group(TALLOC_CTX *mem_ctx, struct samu *user)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_getsampwent(pdb_context, user));
+ return pdb->set_unix_primary_group(pdb, mem_ctx, user);
}
-static SAM_ACCOUNT *sam_account_cache = NULL;
+/*
+ * Helper function to see whether a user is in a group. We can't use
+ * user_in_group_sid here because this creates dependencies only smbd can
+ * fulfil.
+ */
-BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
+static BOOL pdb_user_in_group(TALLOC_CTX *mem_ctx, struct samu *account,
+ const DOM_SID *group_sid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ DOM_SID *sids;
+ gid_t *gids;
+ size_t i, num_groups;
- if (!pdb_context) {
+ if (!NT_STATUS_IS_OK(pdb_enum_group_memberships(mem_ctx, account,
+ &sids, &gids,
+ &num_groups))) {
return False;
}
- if (!NT_STATUS_IS_OK(pdb_context->pdb_getsampwnam(pdb_context,
- sam_acct, username)))
- return False;
-
- if (sam_account_cache != NULL) {
- pdb_free_sam(&sam_account_cache);
- sam_account_cache = NULL;
+ for (i=0; i<num_groups; i++) {
+ if (sid_equal(group_sid, &sids[i])) {
+ return True;
+ }
}
-
- pdb_copy_sam_account(sam_acct, &sam_account_cache);
- return True;
+ return False;
}
-BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
+static NTSTATUS pdb_default_add_groupmem(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid,
+ uint32 member_rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ DOM_SID group_sid, member_sid;
+ struct samu *account = NULL;
+ GROUP_MAP map;
+ struct group *grp;
+ struct passwd *pwd;
+ const char *group_name;
+ uid_t uid;
- if (!pdb_context) {
- return False;
+ sid_compose(&group_sid, get_global_sam_sid(), group_rid);
+ sid_compose(&member_sid, get_global_sam_sid(), member_rid);
+
+ if (!get_domain_group_from_sid(group_sid, &map) ||
+ (map.gid == (gid_t)-1) ||
+ ((grp = getgrgid(map.gid)) == NULL)) {
+ return NT_STATUS_NO_SUCH_GROUP;
}
- if ((sam_account_cache != NULL) &&
- (sid_equal(sid, pdb_get_user_sid(sam_account_cache))))
- return pdb_copy_sam_account(sam_account_cache, &sam_acct);
+ group_name = talloc_strdup(mem_ctx, grp->gr_name);
+ if (group_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- return NT_STATUS_IS_OK(pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid));
-}
+ if ( !(account = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
-BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct)
-{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ if (!pdb_getsampwsid(account, &member_sid) ||
+ !sid_to_uid(&member_sid, &uid) ||
+ ((pwd = getpwuid_alloc(mem_ctx, uid)) == NULL)) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
- if (!pdb_context) {
- return False;
+ if (pdb_user_in_group(mem_ctx, account, &group_sid)) {
+ return NT_STATUS_MEMBER_IN_GROUP;
}
-
- return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
-}
-BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
-{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ /*
+ * ok, the group exist, the user exist, the user is not in the group,
+ * we can (finally) add it to the group !
+ */
- if (!pdb_context) {
- return False;
- }
+ smb_add_user_group(group_name, pwd->pw_name);
- if (sam_account_cache != NULL) {
- pdb_free_sam(&sam_account_cache);
- sam_account_cache = NULL;
+ if (!pdb_user_in_group(mem_ctx, account, &group_sid)) {
+ return NT_STATUS_ACCESS_DENIED;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
+ return NT_STATUS_OK;
}
-BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
+NTSTATUS pdb_add_groupmem(TALLOC_CTX *mem_ctx, uint32 group_rid,
+ uint32 member_rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
-
- if (!pdb_context) {
- return False;
- }
+ struct pdb_methods *pdb = pdb_get_methods();
- if (sam_account_cache != NULL) {
- pdb_free_sam(&sam_account_cache);
- sam_account_cache = NULL;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
+ return pdb->add_groupmem(pdb, mem_ctx, group_rid, member_rid);
}
-NTSTATUS pdb_rename_sam_account(SAM_ACCOUNT *oldname, const char *newname)
+static NTSTATUS pdb_default_del_groupmem(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid,
+ uint32 member_rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ DOM_SID group_sid, member_sid;
+ struct samu *account = NULL;
+ GROUP_MAP map;
+ struct group *grp;
+ struct passwd *pwd;
+ const char *group_name;
+ uid_t uid;
- if (!pdb_context) {
- return NT_STATUS_NOT_IMPLEMENTED;
+ sid_compose(&group_sid, get_global_sam_sid(), group_rid);
+ sid_compose(&member_sid, get_global_sam_sid(), member_rid);
+
+ if (!get_domain_group_from_sid(group_sid, &map) ||
+ (map.gid == (gid_t)-1) ||
+ ((grp = getgrgid(map.gid)) == NULL)) {
+ return NT_STATUS_NO_SUCH_GROUP;
}
- if (sam_account_cache != NULL) {
- pdb_free_sam(&sam_account_cache);
- sam_account_cache = NULL;
+ group_name = talloc_strdup(mem_ctx, grp->gr_name);
+ if (group_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- return pdb_context->pdb_rename_sam_account(pdb_context, oldname, newname);
-}
+ if ( !(account = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
-NTSTATUS pdb_update_login_attempts(SAM_ACCOUNT *sam_acct, BOOL success)
-{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ if (!pdb_getsampwsid(account, &member_sid) ||
+ !sid_to_uid(&member_sid, &uid) ||
+ ((pwd = getpwuid_alloc(mem_ctx, uid)) == NULL)) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
- if (!pdb_context) {
- return NT_STATUS_NOT_IMPLEMENTED;
+ if (!pdb_user_in_group(mem_ctx, account, &group_sid)) {
+ return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ }
+
+ /*
+ * ok, the group exist, the user exist, the user is in the group,
+ * we can (finally) delete it from the group!
+ */
+
+ smb_delete_user_group(group_name, pwd->pw_name);
+
+ if (pdb_user_in_group(mem_ctx, account, &group_sid)) {
+ return NT_STATUS_ACCESS_DENIED;
}
- return pdb_context->pdb_update_login_attempts(pdb_context, sam_acct, success);
+ return NT_STATUS_OK;
}
-BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid)
+NTSTATUS pdb_del_groupmem(TALLOC_CTX *mem_ctx, uint32 group_rid,
+ uint32 member_rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_getgrsid(pdb_context, map, sid));
+ return pdb->del_groupmem(pdb, mem_ctx, group_rid, member_rid);
}
-BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid)
+BOOL pdb_find_alias(const char *name, DOM_SID *sid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_getgrgid(pdb_context, map, gid));
+ return NT_STATUS_IS_OK(pdb->find_alias(pdb, name, sid));
}
-BOOL pdb_getgrnam(GROUP_MAP *map, const char *name)
+NTSTATUS pdb_create_alias(const char *name, uint32 *rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_NOT_IMPLEMENTED;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_getgrnam(pdb_context, map, name));
+ return pdb->create_alias(pdb, name, rid);
}
-BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
+BOOL pdb_delete_alias(const DOM_SID *sid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_add_group_mapping_entry(pdb_context, map));
+ return NT_STATUS_IS_OK(pdb->delete_alias(pdb, sid));
+
}
-BOOL pdb_update_group_mapping_entry(GROUP_MAP *map)
+BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_update_group_mapping_entry(pdb_context, map));
+ return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid, info));
}
-BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
+BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_delete_group_mapping_entry(pdb_context, sid));
+ return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid, info));
}
-BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap,
- size_t *p_num_entries, BOOL unix_only)
+NTSTATUS pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_enum_group_mapping(pdb_context, sid_name_use,
- pp_rmap, p_num_entries, unix_only));
+ return pdb->add_aliasmem(pdb, alias, member);
}
-NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx,
- const DOM_SID *sid,
- uint32 **pp_member_rids,
- size_t *p_num_members)
+NTSTATUS pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return NT_STATUS_UNSUCCESSFUL;
}
- return pdb_context->pdb_enum_group_members(pdb_context, mem_ctx, sid,
- pp_member_rids, p_num_members);
+ return pdb->del_aliasmem(pdb, alias, member);
}
-NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
- DOM_SID **pp_sids, gid_t **pp_gids,
- size_t *p_num_groups)
+NTSTATUS pdb_enum_aliasmem(const DOM_SID *alias,
+ DOM_SID **pp_members, size_t *p_num_members)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return NT_STATUS_UNSUCCESSFUL;
}
- return pdb_context->pdb_enum_group_memberships(pdb_context, username,
- primary_gid, pp_sids, pp_gids,
- p_num_groups);
+ return pdb->enum_aliasmem(pdb, alias,
+ pp_members, p_num_members);
}
-BOOL pdb_find_alias(const char *name, DOM_SID *sid)
+NTSTATUS pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ const DOM_SID *members, size_t num_members,
+ uint32 **pp_alias_rids,
+ size_t *p_num_alias_rids)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_NOT_IMPLEMENTED;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_find_alias(pdb_context,
- name, sid));
+ return pdb->enum_alias_memberships(pdb, mem_ctx,
+ domain_sid,
+ members, num_members,
+ pp_alias_rids,
+ p_num_alias_rids);
}
-NTSTATUS pdb_create_alias(const char *name, uint32 *rid)
+NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char **names,
+ uint32 *attrs)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return NT_STATUS_NOT_IMPLEMENTED;
}
- return pdb_context->pdb_create_alias(pdb_context, name, rid);
+ return pdb->lookup_rids(pdb, domain_sid,
+ num_rids, rids, names, attrs);
}
-BOOL pdb_delete_alias(const DOM_SID *sid)
+NTSTATUS pdb_lookup_names(const DOM_SID *domain_sid,
+ int num_names,
+ const char **names,
+ uint32 *rids,
+ uint32 *attrs)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return False;
+ if ( !pdb ) {
+ return NT_STATUS_NOT_IMPLEMENTED;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_delete_alias(pdb_context,
- sid));
-
+ return pdb->lookup_names(pdb, domain_sid,
+ num_names, names, rids, attrs);
}
-BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info)
+BOOL pdb_get_account_policy(int policy_index, uint32 *value)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_get_aliasinfo(pdb_context, sid,
- info));
+ return NT_STATUS_IS_OK(pdb->get_account_policy(pdb, policy_index, value));
}
-BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
+BOOL pdb_set_account_policy(int policy_index, uint32 value)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_set_aliasinfo(pdb_context, sid,
- info));
+ return NT_STATUS_IS_OK(pdb->set_account_policy(pdb, policy_index, value));
}
-BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+BOOL pdb_get_seq_num(time_t *seq_num)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_add_aliasmem(pdb_context, alias, member));
+ return NT_STATUS_IS_OK(pdb->get_seq_num(pdb, seq_num));
}
-BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+BOOL pdb_uid_to_rid(uid_t uid, uint32 *rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_del_aliasmem(pdb_context, alias, member));
+ return pdb->uid_to_rid(pdb, uid, rid);
}
-BOOL pdb_enum_aliasmem(const DOM_SID *alias,
- DOM_SID **pp_members, size_t *p_num_members)
+BOOL pdb_gid_to_sid(gid_t gid, DOM_SID *sid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_enum_aliasmem(pdb_context, alias,
- pp_members, p_num_members));
+ return pdb->gid_to_sid(pdb, gid, sid);
}
-BOOL pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
- const DOM_SID *members, size_t num_members,
- uint32 **pp_alias_rids, size_t *p_num_alias_rids)
+BOOL pdb_sid_to_id(const DOM_SID *sid, union unid_t *id,
+ enum SID_NAME_USE *type)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_enum_alias_memberships(pdb_context, mem_ctx,
- domain_sid,
- members, num_members,
- pp_alias_rids,
- p_num_alias_rids));
+ return pdb->sid_to_id(pdb, sid, id, type);
}
-NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid,
- int num_rids,
- uint32 *rids,
- const char **names,
- uint32 *attrs)
+BOOL pdb_rid_algorithm(void)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
- if (!pdb_context) {
- return NT_STATUS_NOT_IMPLEMENTED;
+ if ( !pdb ) {
+ return False;
}
- return pdb_context->pdb_lookup_rids(pdb_context, domain_sid,
- num_rids, rids, names, attrs);
+ return pdb->rid_algorithm(pdb);
}
-BOOL pdb_get_account_policy(int policy_index, uint32 *value)
+/********************************************************************
+ Allocate a new RID from the passdb backend. Verify that it is free
+ by calling lookup_global_sam_rid() to verify that the RID is not
+ in use. This handles servers that have existing users or groups
+ with add RIDs (assigned from previous algorithmic mappings)
+********************************************************************/
+
+BOOL pdb_new_rid(uint32 *rid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
+ const char *name = NULL;
+ enum SID_NAME_USE type;
+ uint32 allocated_rid = 0;
+ int i;
+ TALLOC_CTX *ctx;
- if (!pdb_context) {
+ if ( !pdb ) {
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_get_account_policy(pdb_context, policy_index, value));
-}
+ if (pdb_rid_algorithm()) {
+ DEBUG(0, ("Trying to allocate a RID when algorithmic RIDs "
+ "are active\n"));
+ return False;
+ }
-BOOL pdb_set_account_policy(int policy_index, uint32 value)
-{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ if (algorithmic_rid_base() != BASE_RID) {
+ DEBUG(0, ("'algorithmic rid base' is set but a passdb backend "
+ "without algorithmic RIDs is chosen.\n"));
+ DEBUGADD(0, ("Please map all used groups using 'net groupmap "
+ "add', set the maximum used RID using\n"));
+ DEBUGADD(0, ("'net setmaxrid' and remove the parameter\n"));
+ return False;
+ }
- if (!pdb_context) {
+ if ( (ctx = talloc_init("pdb_new_rid")) == NULL ) {
+ DEBUG(0,("pdb_new_rid: Talloc initialization failure\n"));
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_set_account_policy(pdb_context, policy_index, value));
-}
+ /* Attempt to get an unused RID (max tires is 250...yes that it is
+ and arbitrary number I pulkled out of my head). -- jerry */
-BOOL pdb_get_seq_num(time_t *seq_num)
-{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ for ( i=0; allocated_rid==0 && i<250; i++ ) {
+ /* get a new RID */
+
+ if ( !pdb->new_rid(pdb, &allocated_rid) ) {
+ return False;
+ }
+
+ /* validate that the RID is not in use */
+
+ if ( lookup_global_sam_rid( ctx, allocated_rid, &name, &type, NULL ) ) {
+ allocated_rid = 0;
+ }
+ }
+
+ TALLOC_FREE( ctx );
- if (!pdb_context) {
+ if ( allocated_rid == 0 ) {
+ DEBUG(0,("pdb_new_rid: Failed to find unused RID\n"));
return False;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_get_seq_num(pdb_context, seq_num));
+ *rid = allocated_rid;
+
+ return True;
}
+
/***************************************************************
Initialize the static context (at smbd startup etc).
@@ -1456,7 +1293,7 @@ BOOL pdb_get_seq_num(time_t *seq_num)
BOOL initialize_password_db(BOOL reload)
{
- return (pdb_get_static_context(reload) != NULL);
+ return (pdb_get_methods_reload(reload) != NULL);
}
@@ -1464,48 +1301,47 @@ BOOL initialize_password_db(BOOL reload)
Default implementations of some functions.
****************************************************************************/
-static NTSTATUS pdb_default_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname)
+static NTSTATUS pdb_default_getsampwnam (struct pdb_methods *methods, struct samu *user, const char *sname)
{
return NT_STATUS_NO_SUCH_USER;
}
-static NTSTATUS pdb_default_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
+static NTSTATUS pdb_default_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
{
return NT_STATUS_NO_SUCH_USER;
}
-static NTSTATUS pdb_default_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
+static NTSTATUS pdb_default_add_sam_account (struct pdb_methods *methods, struct samu *newpwd)
{
- DEBUG(0,("this backend (%s) should not be listed as the first passdb backend! You can't add users to it.\n", methods->name));
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS pdb_default_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
+static NTSTATUS pdb_default_update_sam_account (struct pdb_methods *methods, struct samu *newpwd)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *pwd)
+static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, struct samu *pwd)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS pdb_default_rename_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *pwd, const char *newname)
+static NTSTATUS pdb_default_rename_sam_account (struct pdb_methods *methods, struct samu *pwd, const char *newname)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS pdb_default_update_login_attempts (struct pdb_methods *methods, SAM_ACCOUNT *newpwd, BOOL success)
+static NTSTATUS pdb_default_update_login_attempts (struct pdb_methods *methods, struct samu *newpwd, BOOL success)
{
return NT_STATUS_OK;
}
-static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask)
+static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, BOOL update, uint32 acb_mask)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
-static NTSTATUS pdb_default_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *user)
+static NTSTATUS pdb_default_getsampwent(struct pdb_methods *methods, struct samu *user)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
@@ -1531,6 +1367,116 @@ 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)
+{
+ struct samu *sampw = NULL;
+ struct passwd *unix_pw;
+ BOOL ret;
+
+ unix_pw = sys_getpwuid( uid );
+
+ if ( !unix_pw ) {
+ DEBUG(4,("pdb_default_uid_to_rid: host has no idea of uid "
+ "%lu\n", (unsigned long)uid));
+ return False;
+ }
+
+ if ( !(sampw = samu_new( NULL )) ) {
+ DEBUG(0,("pdb_default_uid_to_rid: samu_new() failed!\n"));
+ return False;
+ }
+
+ become_root();
+ ret = NT_STATUS_IS_OK(
+ methods->getsampwnam(methods, sampw, unix_pw->pw_name ));
+ unbecome_root();
+
+ if (!ret) {
+ DEBUG(5, ("pdb_default_uid_to_rid: Did not find user "
+ "%s (%d)\n", unix_pw->pw_name, uid));
+ TALLOC_FREE(sampw);
+ return False;
+ }
+
+ ret = sid_peek_check_rid(get_global_sam_sid(),
+ pdb_get_user_sid(sampw), rid);
+
+ if (!ret) {
+ DEBUG(1, ("Could not peek rid out of sid %s\n",
+ sid_string_static(pdb_get_user_sid(sampw))));
+ }
+
+ TALLOC_FREE(sampw);
+ return ret;
+}
+
+static BOOL pdb_default_gid_to_sid(struct pdb_methods *methods, gid_t gid,
+ DOM_SID *sid)
+{
+ GROUP_MAP map;
+
+ if (!NT_STATUS_IS_OK(methods->getgrgid(methods, &map, gid))) {
+ return False;
+ }
+
+ sid_copy(sid, &map.sid);
+ return True;
+}
+
+static BOOL pdb_default_sid_to_id(struct pdb_methods *methods,
+ const DOM_SID *sid,
+ union unid_t *id, enum SID_NAME_USE *type)
+{
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = False;
+ const char *name;
+ uint32 rid;
+
+ mem_ctx = talloc_new(NULL);
+
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ if (sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
+ /* Here we might have users as well as groups and aliases */
+ ret = lookup_global_sam_rid(mem_ctx, rid, &name, type, id);
+ goto done;
+ }
+
+ if (sid_peek_check_rid(&global_sid_Builtin, sid, &rid)) {
+ /* Here we only have aliases */
+ GROUP_MAP map;
+ if (!NT_STATUS_IS_OK(methods->getgrsid(methods, &map, *sid))) {
+ DEBUG(10, ("Could not find map for sid %s\n",
+ sid_string_static(sid)));
+ goto done;
+ }
+ if ((map.sid_name_use != SID_NAME_ALIAS) &&
+ (map.sid_name_use != SID_NAME_WKN_GRP)) {
+ DEBUG(10, ("Map for sid %s is a %s, expected an "
+ "alias\n", sid_string_static(sid),
+ sid_type_lookup(map.sid_name_use)));
+ goto done;
+ }
+
+ id->gid = map.gid;
+ *type = SID_NAME_ALIAS;
+ ret = True;
+ goto done;
+ }
+
+ DEBUG(5, ("Sid %s is neither ours nor builtin, don't know it\n",
+ sid_string_static(sid)));
+
+ done:
+
+ TALLOC_FREE(mem_ctx);
+ return ret;
+}
+
static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
uid_t uid, uid_t **pp_uids, size_t *p_num)
{
@@ -1554,31 +1500,36 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
{
struct group *grp;
char **gr;
- struct sys_pwent *userlist, *user;
+ struct passwd *pwd;
+ char *winbindd_env;
*pp_uids = NULL;
*p_num = 0;
/* We only look at our own sam, so don't care about imported stuff */
+ winbindd_env = getenv(WINBINDD_DONT_ENV);
winbind_off();
if ((grp = getgrgid(gid)) == NULL) {
- winbind_on();
+ /* allow winbindd lookups, but only if they weren't already disabled */
+ if ( !(winbindd_env && strequal(winbindd_env, "1")) ) {
+ winbind_on();
+ }
+
return False;
}
/* Primary group members */
- userlist = getpwent_list();
-
- for (user = userlist; user != NULL; user = user->next) {
- if (user->pw_gid != gid)
- continue;
- add_uid_to_array_unique(mem_ctx, user->pw_uid, pp_uids, p_num);
+ setpwent();
+ while ((pwd = getpwent()) != NULL) {
+ if (pwd->pw_gid == gid) {
+ add_uid_to_array_unique(mem_ctx, pwd->pw_uid,
+ pp_uids, p_num);
+ }
}
-
- pwent_free(userlist);
+ endpwent();
/* Secondary group members */
@@ -1590,7 +1541,11 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
add_uid_to_array_unique(mem_ctx, pw->pw_uid, pp_uids, p_num);
}
- winbind_on();
+ /* allow winbindd lookups, but only if they weren't already disabled */
+
+ if ( !(winbindd_env && strequal(winbindd_env, "1")) ) {
+ winbind_on();
+ }
return True;
}
@@ -1608,7 +1563,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
*pp_member_rids = NULL;
*p_num_members = 0;
- if (!NT_STATUS_IS_OK(sid_to_gid(group, &gid)))
+ if (!sid_to_gid(group, &gid))
return NT_STATUS_NO_SUCH_GROUP;
if(!get_memberuids(mem_ctx, gid, &uids, &num_uids))
@@ -1622,13 +1577,10 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
for (i=0; i<num_uids; i++) {
DOM_SID sid;
- if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
- DEBUG(1, ("Could not map member uid to SID\n"));
- continue;
- }
+ uid_to_sid(&sid, uids[i]);
if (!sid_check_is_in_our_domain(&sid)) {
- DEBUG(1, ("Inconsistent SAM -- group member uid not "
+ DEBUG(5, ("Inconsistent SAM -- group member uid not "
"in our domain\n"));
continue;
}
@@ -1640,6 +1592,140 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
return NT_STATUS_OK;
}
+NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user,
+ DOM_SID **pp_sids,
+ gid_t **pp_gids,
+ size_t *p_num_groups)
+{
+ size_t i;
+ gid_t gid;
+ struct passwd *pw;
+ const char *username = pdb_get_username(user);
+
+
+ /* Ignore the primary group SID. Honor the real Unix primary group.
+ The primary group SID is only of real use to Windows clients */
+
+ if ( !(pw = getpwnam_alloc(mem_ctx, username)) ) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ gid = pw->pw_gid;
+
+ TALLOC_FREE( pw );
+
+ if (!getgroups_unix_user(mem_ctx, username, gid, pp_gids, p_num_groups)) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (*p_num_groups == 0) {
+ smb_panic("primary group missing");
+ }
+
+ *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups);
+
+ if (*pp_sids == NULL) {
+ TALLOC_FREE(*pp_gids);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<*p_num_groups; i++) {
+ gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Look up a rid in the SAM we're responsible for (i.e. passdb)
+ ********************************************************************/
+
+static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
+ const char **name,
+ enum SID_NAME_USE *psid_name_use,
+ union unid_t *unix_id)
+{
+ struct samu *sam_account = NULL;
+ GROUP_MAP map;
+ BOOL ret;
+ DOM_SID sid;
+
+ *psid_name_use = SID_NAME_UNKNOWN;
+
+ DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n",
+ (unsigned int)rid));
+
+ sid_copy(&sid, get_global_sam_sid());
+ sid_append_rid(&sid, rid);
+
+ /* see if the passdb can help us with the name of the user */
+
+ if ( !(sam_account = samu_new( NULL )) ) {
+ return False;
+ }
+
+ /* BEING ROOT BLLOCK */
+ become_root();
+ if (pdb_getsampwsid(sam_account, &sid)) {
+ struct passwd *pw;
+
+ unbecome_root(); /* -----> EXIT BECOME_ROOT() */
+ *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
+ *psid_name_use = SID_NAME_USER;
+
+ TALLOC_FREE(sam_account);
+
+ if (unix_id == NULL) {
+ return True;
+ }
+
+ pw = Get_Pwnam(*name);
+ if (pw == NULL) {
+ return False;
+ }
+ unix_id->uid = pw->pw_uid;
+ return True;
+ }
+ TALLOC_FREE(sam_account);
+
+ ret = pdb_getgrsid(&map, sid);
+ unbecome_root();
+ /* END BECOME_ROOT BLOCK */
+
+ /* do not resolve SIDs to a name unless there is a valid
+ gid associated with it */
+
+ if ( ret && (map.gid != (gid_t)-1) ) {
+ *name = talloc_strdup(mem_ctx, map.nt_name);
+ *psid_name_use = map.sid_name_use;
+
+ if ( unix_id ) {
+ unix_id->gid = map.gid;
+ }
+
+ return True;
+ }
+
+ /* Windows will always map RID 513 to something. On a non-domain
+ controller, this gets mapped to SERVER\None. */
+
+ if ( unix_id ) {
+ DEBUG(5, ("Can't find a unix id for an unmapped group\n"));
+ return False;
+ }
+
+ if ( rid == DOMAIN_GROUP_RID_USERS ) {
+ *name = talloc_strdup(mem_ctx, "None" );
+ *psid_name_use = SID_NAME_DOM_GRP;
+
+ return True;
+ }
+
+ return False;
+}
+
NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
const DOM_SID *domain_sid,
int num_rids,
@@ -1655,14 +1741,11 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
if (sid_check_is_builtin(domain_sid)) {
for (i=0; i<num_rids; i++) {
- fstring name;
+ const char *name;
- if (lookup_builtin_rid(rids[i], name)) {
+ if (lookup_builtin_rid(names, rids[i], &name)) {
attrs[i] = SID_NAME_ALIAS;
- names[i] = talloc_strdup(names, name);
- if (names[i] == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ names[i] = name;
DEBUG(5,("lookup_rids: %s:%d\n",
names[i], attrs[i]));
have_mapped = True;
@@ -1680,14 +1763,14 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
}
for (i = 0; i < num_rids; i++) {
- fstring tmpname;
- enum SID_NAME_USE type;
+ const char *name;
- if (lookup_global_sam_rid(rids[i], tmpname, &type)) {
- attrs[i] = (uint32)type;
- names[i] = talloc_strdup(names, tmpname);
- if (names[i] == NULL)
+ if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i],
+ NULL)) {
+ if (name == NULL) {
return NT_STATUS_NO_MEMORY;
+ }
+ names[i] = name;
DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i]));
have_mapped = True;
} else {
@@ -1706,6 +1789,63 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
return result;
}
+NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
+ const DOM_SID *domain_sid,
+ int num_names,
+ const char **names,
+ uint32 *rids,
+ uint32 *attrs)
+{
+ int i;
+ NTSTATUS result;
+ BOOL have_mapped = False;
+ BOOL have_unmapped = False;
+
+ if (sid_check_is_builtin(domain_sid)) {
+
+ for (i=0; i<num_names; i++) {
+ uint32 rid;
+
+ if (lookup_builtin_name(names[i], &rid)) {
+ attrs[i] = SID_NAME_ALIAS;
+ rids[i] = rid;
+ DEBUG(5,("lookup_rids: %s:%d\n",
+ names[i], attrs[i]));
+ have_mapped = True;
+ } else {
+ have_unmapped = True;
+ attrs[i] = SID_NAME_UNKNOWN;
+ }
+ }
+ goto done;
+ }
+
+ /* Should not happen, but better check once too many */
+ if (!sid_check_is_domain(domain_sid)) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ for (i = 0; i < num_names; i++) {
+ if (lookup_global_sam_name(names[i], 0, &rids[i], &attrs[i])) {
+ DEBUG(5,("lookup_names: %s-> %d:%d\n", names[i],
+ rids[i], attrs[i]));
+ have_mapped = True;
+ } else {
+ have_unmapped = True;
+ attrs[i] = SID_NAME_UNKNOWN;
+ }
+ }
+
+ done:
+
+ result = NT_STATUS_NONE_MAPPED;
+
+ if (have_mapped)
+ result = have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK;
+
+ return result;
+}
+
static struct pdb_search *pdb_search_init(enum pdb_search_type type)
{
TALLOC_CTX *mem_ctx;
@@ -1772,24 +1912,22 @@ static BOOL next_entry_users(struct pdb_search *s,
struct samr_displayentry *entry)
{
struct user_search *state = s->private_data;
- SAM_ACCOUNT *user = NULL;
- NTSTATUS status;
+ struct samu *user = NULL;
next:
- status = pdb_init_sam(&user);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Could not pdb_init_sam\n"));
+ if ( !(user = samu_new( NULL )) ) {
+ DEBUG(0, ("next_entry_users: samu_new() failed!\n"));
return False;
}
if (!pdb_getsampwent(user)) {
- pdb_free_sam(&user);
+ TALLOC_FREE(user);
return False;
}
if ((state->acct_flags != 0) &&
((pdb_get_acct_ctrl(user) & state->acct_flags) == 0)) {
- pdb_free_sam(&user);
+ TALLOC_FREE(user);
goto next;
}
@@ -1798,7 +1936,7 @@ static BOOL next_entry_users(struct pdb_search *s,
pdb_get_fullname(user), pdb_get_acct_desc(user),
entry);
- pdb_free_sam(&user);
+ TALLOC_FREE(user);
return True;
}
@@ -1810,7 +1948,7 @@ static void search_end_users(struct pdb_search *search)
static BOOL pdb_default_search_users(struct pdb_methods *methods,
struct pdb_search *search,
- uint16 acct_flags)
+ uint32 acct_flags)
{
struct user_search *state;
@@ -1871,7 +2009,7 @@ static void search_end_groups(struct pdb_search *search)
}
static BOOL pdb_search_grouptype(struct pdb_search *search,
- enum SID_NAME_USE type)
+ const DOM_SID *sid, enum SID_NAME_USE type)
{
struct group_search *state;
@@ -1881,7 +2019,7 @@ static BOOL pdb_search_grouptype(struct pdb_search *search,
return False;
}
- if (!pdb_enum_group_mapping(type, &state->groups, &state->num_groups,
+ if (!pdb_enum_group_mapping(sid, type, &state->groups, &state->num_groups,
True)) {
DEBUG(0, ("Could not enum groups\n"));
return False;
@@ -1897,7 +2035,7 @@ static BOOL pdb_search_grouptype(struct pdb_search *search,
static BOOL pdb_default_search_groups(struct pdb_methods *methods,
struct pdb_search *search)
{
- return pdb_search_grouptype(search, SID_NAME_DOM_GRP);
+ return pdb_search_grouptype(search, get_global_sam_sid(), SID_NAME_DOM_GRP);
}
static BOOL pdb_default_search_aliases(struct pdb_methods *methods,
@@ -1905,14 +2043,7 @@ static BOOL pdb_default_search_aliases(struct pdb_methods *methods,
const DOM_SID *sid)
{
- if (sid_equal(sid, get_global_sam_sid()))
- return pdb_search_grouptype(search, SID_NAME_ALIAS);
-
- if (sid_equal(sid, &global_sid_Builtin))
- return pdb_search_grouptype(search, SID_NAME_WKN_GRP);
-
- DEBUG(3, ("unknown domain sid: %s\n", sid_string_static(sid)));
- return False;
+ return pdb_search_grouptype(search, sid, SID_NAME_ALIAS);
}
static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search,
@@ -1941,17 +2072,17 @@ static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search,
return (search->num_entries > idx) ? &search->cache[idx] : NULL;
}
-struct pdb_search *pdb_search_users(uint16 acct_flags)
+struct pdb_search *pdb_search_users(uint32 acct_flags)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
struct pdb_search *result;
- if (pdb_context == NULL) return NULL;
+ if (pdb == NULL) return NULL;
result = pdb_search_init(PDB_USER_SEARCH);
if (result == NULL) return NULL;
- if (!pdb_context->pdb_search_users(pdb_context, result, acct_flags)) {
+ if (!pdb->search_users(pdb, result, acct_flags)) {
talloc_destroy(result->mem_ctx);
return NULL;
}
@@ -1960,15 +2091,15 @@ struct pdb_search *pdb_search_users(uint16 acct_flags)
struct pdb_search *pdb_search_groups(void)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
struct pdb_search *result;
- if (pdb_context == NULL) return NULL;
+ if (pdb == NULL) return NULL;
result = pdb_search_init(PDB_GROUP_SEARCH);
if (result == NULL) return NULL;
- if (!pdb_context->pdb_search_groups(pdb_context, result)) {
+ if (!pdb->search_groups(pdb, result)) {
talloc_destroy(result->mem_ctx);
return NULL;
}
@@ -1977,15 +2108,15 @@ struct pdb_search *pdb_search_groups(void)
struct pdb_search *pdb_search_aliases(const DOM_SID *sid)
{
- struct pdb_context *pdb_context = pdb_get_static_context(False);
+ struct pdb_methods *pdb = pdb_get_methods();
struct pdb_search *result;
- if (pdb_context == NULL) return NULL;
+ if (pdb == NULL) return NULL;
result = pdb_search_init(PDB_ALIAS_SEARCH);
if (result == NULL) return NULL;
- if (!pdb_context->pdb_search_aliases(pdb_context, result, sid)) {
+ if (!pdb->search_aliases(pdb, result, sid)) {
talloc_destroy(result->mem_ctx);
return NULL;
}
@@ -2026,21 +2157,28 @@ void pdb_search_destroy(struct pdb_search *search)
talloc_destroy(search->mem_ctx);
}
-NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
+/*******************************************************************
+ Create a pdb_methods structure and initialize it with the default
+ operations. In this way a passdb module can simply implement
+ the functionality it cares about. However, normally this is done
+ in groups of related functions.
+*******************************************************************/
+
+NTSTATUS make_pdb_method( struct pdb_methods **methods )
{
- *methods = TALLOC_P(mem_ctx, struct pdb_methods);
+ /* allocate memory for the structure as its own talloc CTX */
- if (!*methods) {
+ if ( !(*methods = TALLOC_ZERO_P(NULL, struct pdb_methods) ) ) {
return NT_STATUS_NO_MEMORY;
}
- ZERO_STRUCTP(*methods);
-
(*methods)->setsampwent = pdb_default_setsampwent;
(*methods)->endsampwent = pdb_default_endsampwent;
(*methods)->getsampwent = pdb_default_getsampwent;
(*methods)->getsampwnam = pdb_default_getsampwnam;
(*methods)->getsampwsid = pdb_default_getsampwsid;
+ (*methods)->create_user = pdb_default_create_user;
+ (*methods)->delete_user = pdb_default_delete_user;
(*methods)->add_sam_account = pdb_default_add_sam_account;
(*methods)->update_sam_account = pdb_default_update_sam_account;
(*methods)->delete_sam_account = pdb_default_delete_sam_account;
@@ -2050,12 +2188,17 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->getgrsid = pdb_default_getgrsid;
(*methods)->getgrgid = pdb_default_getgrgid;
(*methods)->getgrnam = pdb_default_getgrnam;
+ (*methods)->create_dom_group = pdb_default_create_dom_group;
+ (*methods)->delete_dom_group = pdb_default_delete_dom_group;
(*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
(*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
(*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
(*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
(*methods)->enum_group_members = pdb_default_enum_group_members;
(*methods)->enum_group_memberships = pdb_default_enum_group_memberships;
+ (*methods)->set_unix_primary_group = pdb_default_set_unix_primary_group;
+ (*methods)->add_groupmem = pdb_default_add_groupmem;
+ (*methods)->del_groupmem = pdb_default_del_groupmem;
(*methods)->find_alias = pdb_default_find_alias;
(*methods)->create_alias = pdb_default_create_alias;
(*methods)->delete_alias = pdb_default_delete_alias;
@@ -2069,6 +2212,9 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->get_account_policy = pdb_default_get_account_policy;
(*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)->gid_to_sid = pdb_default_gid_to_sid;
+ (*methods)->sid_to_id = pdb_default_sid_to_id;
(*methods)->search_users = pdb_default_search_users;
(*methods)->search_groups = pdb_default_search_groups;
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 05fc8943829..1e3a5fdb6f0 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -1,11 +1,12 @@
/*
Unix SMB/CIFS implementation.
LDAP protocol helper functions for SAMBA
- Copyright (C) Jean François Micouleau 1998
+ Copyright (C) Jean François Micouleau 1998
Copyright (C) Gerald Carter 2001-2003
Copyright (C) Shahms King 2001
Copyright (C) Andrew Bartlett 2002-2003
Copyright (C) Stefan (metze) Metzmacher 2002-2003
+ 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
@@ -30,7 +31,7 @@
* Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
*
* Other LDAP based login attributes: accountExpires, etc.
-* (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
+* (should be the domain of Samba proper, but the sam_password/struct samu
* structures don't have fields for some of these attributes)
*
* SSL is done, but can't get the certificate based authentication to work
@@ -77,20 +78,15 @@
#endif
-#ifndef SAM_ACCOUNT
-#define SAM_ACCOUNT struct sam_passwd
-#endif
-
#include "smbldap.h"
/**********************************************************************
- Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
+ Simple helper function to make stuff better readable
**********************************************************************/
-
-void private_data_free_fn(void **result)
+
+static LDAP *priv2ld(struct ldapsam_privates *priv)
{
- ldap_msgfree(*result);
- *result = NULL;
+ return priv->smbldap_state->ldap_struct;
}
/**********************************************************************
@@ -117,14 +113,14 @@ static const char* get_userattr_key2string( int schema_ver, int key )
Return the list of attribute names given a user schema version.
**********************************************************************/
-const char** get_userattr_list( int schema_ver )
+const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
- return get_attr_list( attrib_map_v22 );
+ return get_attr_list( mem_ctx, attrib_map_v22 );
case SCHEMAVER_SAMBASAMACCOUNT:
- return get_attr_list( attrib_map_v30 );
+ return get_attr_list( mem_ctx, attrib_map_v30 );
default:
DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
break;
@@ -137,14 +133,17 @@ const char** get_userattr_list( int schema_ver )
Return the list of attribute names to delete given a user schema version.
**************************************************************************/
-static const char** get_userattr_delete_list( int schema_ver )
+static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
+ int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
- return get_attr_list( attrib_map_to_delete_v22 );
+ return get_attr_list( mem_ctx,
+ attrib_map_to_delete_v22 );
case SCHEMAVER_SAMBASAMACCOUNT:
- return get_attr_list( attrib_map_to_delete_v30 );
+ return get_attr_list( mem_ctx,
+ attrib_map_to_delete_v30 );
default:
DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
break;
@@ -250,13 +249,6 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_
LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
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,("ldapsam_get_seq_num: Failed search for suffix: %s, error: %s (%s)\n",
- suffix,ldap_err2string(rc), ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
goto done;
}
@@ -399,58 +391,37 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
object found in search_result depending on lp_ldap_delete_dn
******************************************************************/
-static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
- LDAPMessage *result,
- const char *objectclass,
- const char **attrs)
+static int ldapsam_delete_entry(struct ldapsam_privates *priv,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *entry,
+ const char *objectclass,
+ const char **attrs)
{
- int rc;
- LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
- char *name, *dn;
+ char *name;
+ const char *dn;
BerElement *ptr = NULL;
- rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
- if (rc != 1) {
- DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
- return NT_STATUS_UNSUCCESSFUL;
+ dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
+ if (dn == NULL) {
+ return LDAP_NO_MEMORY;
}
if (lp_ldap_delete_dn()) {
- NTSTATUS ret = NT_STATUS_OK;
- rc = smbldap_delete(ldap_state->smbldap_state, dn);
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn));
- ret = NT_STATUS_UNSUCCESSFUL;
- }
- SAFE_FREE(dn);
- return ret;
+ return smbldap_delete(priv->smbldap_state, dn);
}
/* Ok, delete only the SAM attributes */
- for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
+ for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
name != NULL;
- name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
+ name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
const char **attrib;
/* We are only allowed to delete the attributes that
really exist. */
for (attrib = attrs; *attrib != NULL; attrib++) {
- /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
- if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
- LDAP_ATTR_MOD_TIMESTAMP))) {
- continue;
- }
if (strequal(*attrib, name)) {
DEBUG(10, ("ldapsam_delete_entry: deleting "
"attribute %s\n", name));
@@ -458,96 +429,20 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
NULL);
}
}
-
ldap_memfree(name);
}
-
+
if (ptr != NULL) {
ber_free(ptr, 0);
}
smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
-
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- ldap_mods_free(mods, True);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
-
- DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n",
- dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
- SAFE_FREE(dn);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- SAFE_FREE(dn);
- return NT_STATUS_OK;
-}
-
-/* New Interface is being implemented here */
-
-#if 0 /* JERRY - not uesed anymore */
-
-/**********************************************************************
-Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
-*********************************************************************/
-static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
- SAM_ACCOUNT * sampass,
- LDAPMessage * entry,
- gid_t *gid)
-{
- pstring homedir;
- pstring temp;
- char **ldap_values;
- char **values;
-
- if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) {
- DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
- return False;
- }
-
- for (values=ldap_values;*values;values++) {
- if (strequal(*values, LDAP_OBJ_POSIXACCOUNT )) {
- break;
- }
- }
-
- if (!*values) { /*end of array, no posixAccount */
- DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
- ldap_value_free(ldap_values);
- return False;
- }
- ldap_value_free(ldap_values);
-
- if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) )
- {
- return False;
- }
-
- if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
- {
- return False;
- }
-
- *gid = (gid_t)atol(temp);
-
- pdb_set_unix_homedir(sampass, homedir, PDB_SET);
+ talloc_autofree_ldapmod(mem_ctx, mods);
- DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
-
- return True;
+ return smbldap_modify(priv->smbldap_state, dn, mods);
}
-
-#endif
-
-static time_t ldapsam_get_entry_timestamp(
- struct ldapsam_privates *ldap_state,
- LDAPMessage * entry)
+
+static time_t ldapsam_get_entry_timestamp( struct ldapsam_privates *ldap_state, LDAPMessage * entry)
{
pstring temp;
struct tm tm;
@@ -563,12 +458,12 @@ static time_t ldapsam_get_entry_timestamp(
}
/**********************************************************************
- Initialize SAM_ACCOUNT from an LDAP query.
+ Initialize struct samu from an LDAP query.
(Based on init_sam_from_buffer in pdb_tdb.c)
*********************************************************************/
static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
- SAM_ACCOUNT * sampass,
+ struct samu * sampass,
LDAPMessage * entry)
{
time_t logon_time,
@@ -594,8 +489,8 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
uint8 smblmpwd[LM_HASH_LEN],
smbntpwd[NT_HASH_LEN];
BOOL use_samba_attrs = True;
- uint16 acct_ctrl = 0,
- logon_divs;
+ uint32 acct_ctrl = 0;
+ uint16 logon_divs;
uint16 bad_password_count = 0,
logon_count = 0;
uint32 hours_len;
@@ -627,13 +522,16 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
return False;
}
- if (ldap_state->smbldap_state->ldap_struct == NULL) {
- DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
+ if (priv2ld(ldap_state) == NULL) {
+ DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
+ "ldap_struct is NULL!\n"));
return False;
}
- if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
- DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n"));
+ if (!smbldap_get_single_pstring(priv2ld(ldap_state), entry, "uid",
+ username)) {
+ DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
+ "this user!\n"));
return False;
}
@@ -655,36 +553,12 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) {
pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
}
-
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) {
- pdb_set_group_sid_from_string(sampass, temp, PDB_SET);
- } else {
- pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
- }
} else {
if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) {
user_rid = (uint32)atol(temp);
pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
}
-
- if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) {
- pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
- } else {
- uint32 group_rid;
-
- group_rid = (uint32)atol(temp);
-
- /* for some reason, we often have 0 as a primary group RID.
- Make sure that we treat this just as a 'default' value */
-
- if ( group_rid > 0 )
- pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
- else
- pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
- }
}
if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
@@ -773,7 +647,7 @@ 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->mem_ctx, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, lp_logon_home()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, homedir );
@@ -788,7 +662,7 @@ 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->mem_ctx, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, lp_logon_script()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, logon_script );
@@ -803,7 +677,7 @@ 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->mem_ctx, username, lp_logon_path()),
+ talloc_sub_basic( sampass, username, lp_logon_path()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, profile_path );
@@ -992,6 +866,15 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
ZERO_STRUCT(hours);
}
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ if (smbldap_get_single_pstring(priv2ld(ldap_state), entry,
+ "uidNumber", temp)) {
+ /* We've got a uid, feed the cache */
+ uid_t uid = strtoul(temp, NULL, 10);
+ store_uid_sid_cache(pdb_get_user_sid(sampass), uid);
+ }
+ }
+
/* check the timestamp of the cache vs ldap entry */
if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state,
entry)))
@@ -1033,14 +916,14 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
}
/**********************************************************************
- Initialize the ldap db from a SAM_ACCOUNT. Called on update.
+ Initialize the ldap db from a struct samu. Called on update.
(Based on init_buffer_from_sam in pdb_tdb.c)
*********************************************************************/
static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
LDAPMessage *existing,
- LDAPMod *** mods, SAM_ACCOUNT * sampass,
- BOOL (*need_update)(const SAM_ACCOUNT *,
+ LDAPMod *** mods, struct samu * sampass,
+ BOOL (*need_update)(const struct samu *,
enum pdb_elements))
{
pstring temp;
@@ -1057,9 +940,16 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
* took out adding "objectclass: sambaAccount"
* do this on a per-mod basis
*/
- if (need_update(sampass, PDB_USERNAME))
+ if (need_update(sampass, PDB_USERNAME)) {
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
"uid", pdb_get_username(sampass));
+ if (ldap_state->is_nds_ldap) {
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+ "cn", pdb_get_username(sampass));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+ "sn", pdb_get_username(sampass));
+ }
+ }
DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
@@ -1354,7 +1244,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
Connect to LDAP server for password enumeration.
*********************************************************************/
-static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
+static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
@@ -1380,10 +1270,10 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update,
DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n",
acb_mask, suffix));
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &ldap_state->result);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
@@ -1421,10 +1311,12 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods)
Get the next entry in the LDAP password database.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
+static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
+ struct samu *user)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
BOOL bret = False;
while (!bret) {
@@ -1434,14 +1326,15 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT
ldap_state->index++;
bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
- ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->entry);
+ ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
+ ldap_state->entry);
}
return NT_STATUS_OK;
}
-static void append_attr(const char ***attr_list, const char *new_attr)
+static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
+ const char *new_attr)
{
int i;
@@ -1453,17 +1346,18 @@ static void append_attr(const char ***attr_list, const char *new_attr)
;
}
- (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *, i+2);
+ (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
+ const char *, i+2);
SMB_ASSERT((*attr_list) != NULL);
- (*attr_list)[i] = SMB_STRDUP(new_attr);
+ (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
(*attr_list)[i+1] = NULL;
}
/**********************************************************************
-Get SAM_ACCOUNT entry from LDAP by username.
+Get struct samu entry from LDAP by username.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
+static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu *user, const char *sname)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
@@ -1473,10 +1367,14 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
const char ** attr_list;
int rc;
- attr_list = get_userattr_list( ldap_state->schema_ver );
- append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
- rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
- free_attr_list( attr_list );
+ attr_list = get_userattr_list( user, ldap_state->schema_ver );
+ append_attr(user, &attr_list,
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP));
+ append_attr(user, &attr_list, "uidNumber");
+ rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
+ attr_list);
+ TALLOC_FREE( attr_list );
if ( rc != LDAP_SUCCESS )
return NT_STATUS_NO_SUCH_USER;
@@ -1500,9 +1398,9 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_USER;
}
- pdb_set_backend_private_data(user, result,
- private_data_free_fn,
+ pdb_set_backend_private_data(user, result, NULL,
my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(user, result);
ret = NT_STATUS_OK;
} else {
ldap_msgfree(result);
@@ -1518,24 +1416,37 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
uint32 rid;
switch ( ldap_state->schema_ver ) {
- case SCHEMAVER_SAMBASAMACCOUNT:
- attr_list = get_userattr_list(ldap_state->schema_ver);
- append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
- rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
- free_attr_list( attr_list );
+ case SCHEMAVER_SAMBASAMACCOUNT: {
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return LDAP_NO_MEMORY;
+ }
+
+ attr_list = get_userattr_list(tmp_ctx,
+ ldap_state->schema_ver);
+ append_attr(tmp_ctx, &attr_list,
+ get_userattr_key2string(
+ ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP));
+ append_attr(tmp_ctx, &attr_list, "uidNumber");
+ rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
+ result, attr_list);
+ TALLOC_FREE(tmp_ctx);
if ( rc != LDAP_SUCCESS )
return rc;
break;
+ }
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
return rc;
}
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL,
+ ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if ( rc != LDAP_SUCCESS )
return rc;
@@ -1545,10 +1456,10 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
}
/**********************************************************************
- Get SAM_ACCOUNT entry from LDAP by SID.
+ Get struct samu entry from LDAP by SID.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
+static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
LDAPMessage *result = NULL;
@@ -1588,9 +1499,9 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT
return NT_STATUS_NO_SUCH_USER;
}
- pdb_set_backend_private_data(user, result,
- private_data_free_fn,
+ pdb_set_backend_private_data(user, result, NULL,
my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(user, result);
return NT_STATUS_OK;
}
@@ -1605,14 +1516,14 @@ static BOOL ldapsam_can_pwchange_exop(struct smbldap_state *ldap_state)
**********************************************************************/
static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
- SAM_ACCOUNT *newpwd, char *dn,
+ struct samu *newpwd, char *dn,
LDAPMod **mods, int ldap_op,
- BOOL (*need_update)(const SAM_ACCOUNT *, enum pdb_elements))
+ BOOL (*need_update)(const struct samu *, enum pdb_elements))
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
- if (!my_methods || !newpwd || !dn) {
+ if (!newpwd || !dn) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -1621,10 +1532,16 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
/* may be password change below however */
} else {
switch(ldap_op) {
- case LDAP_MOD_ADD:
- smbldap_set_mod(&mods, LDAP_MOD_ADD,
- "objectclass",
- LDAP_OBJ_ACCOUNT);
+ case LDAP_MOD_ADD:
+ if (ldap_state->is_nds_ldap) {
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ "objectclass",
+ "inetOrgPerson");
+ } else {
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ "objectclass",
+ LDAP_OBJ_ACCOUNT);
+ }
rc = smbldap_add(ldap_state->smbldap_state,
dn, mods);
break;
@@ -1639,14 +1556,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
}
if (rc!=LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(1, ("ldapsam_modify_entry: Failed to %s user dn= %s with: %s\n\t%s\n",
- ldap_op == LDAP_MOD_ADD ? "add" : "modify",
- dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -1747,15 +1656,17 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
Delete entry from LDAP for username.
*********************************************************************/
-static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
+static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
+ struct samu * sam_acct)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)my_methods->private_data;
const char *sname;
int rc;
- LDAPMessage *result = NULL;
- NTSTATUS ret;
+ LDAPMessage *msg, *entry;
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
const char **attr_list;
- fstring objclass;
+ TALLOC_CTX *mem_ctx;
if (!sam_acct) {
DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
@@ -1764,35 +1675,42 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
sname = pdb_get_username(sam_acct);
- DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
+ DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
+ "LDAP.\n", sname));
- attr_list= get_userattr_delete_list( ldap_state->schema_ver );
- rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ goto done;
+ }
- if (rc != LDAP_SUCCESS) {
- free_attr_list( attr_list );
- return NT_STATUS_NO_SUCH_USER;
+ attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
+ if (attr_list == NULL) {
+ goto done;
}
-
- switch ( ldap_state->schema_ver ) {
- case SCHEMAVER_SAMBASAMACCOUNT:
- fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
- break;
-
- case SCHEMAVER_SAMBAACCOUNT:
- fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
- break;
- default:
- fstrcpy( objclass, "UNKNOWN" );
- DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
- break;
+
+ rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+ ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+ DEBUG(5, ("Could not find user %s\n", sname));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
}
+
+ rc = ldapsam_delete_entry(
+ priv, mem_ctx, entry,
+ priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
+ LDAP_OBJ_SAMBASAMACCOUNT : LDAP_OBJ_SAMBAACCOUNT,
+ attr_list);
- ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
- ldap_msgfree(result);
- free_attr_list( attr_list );
+ result = (rc == LDAP_SUCCESS) ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
- return ret;
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
}
/**********************************************************************
@@ -1800,17 +1718,17 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
we need LDAP modification.
*********************************************************************/
-static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
+static BOOL element_is_changed(const struct samu *sampass,
enum pdb_elements element)
{
return IS_SAM_CHANGED(sampass, element);
}
/**********************************************************************
- Update SAM_ACCOUNT.
+ Update struct samu.
*********************************************************************/
-static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
+static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
@@ -1823,13 +1741,15 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
result = pdb_get_backend_private_data(newpwd, my_methods);
if (!result) {
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
}
- pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
+ pdb_set_backend_private_data(newpwd, result, NULL,
+ my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(newpwd, result);
}
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
@@ -1866,12 +1786,6 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
SAFE_FREE(dn);
if (!NT_STATUS_IS_OK(ret)) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n",
- pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
return ret;
}
@@ -1881,12 +1795,12 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
}
/***************************************************************************
- Renames a SAM_ACCOUNT
+ Renames a struct samu
- The "rename user script" has full responsibility for changing everything
***************************************************************************/
static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
- SAM_ACCOUNT *old_acct,
+ struct samu *old_acct,
const char *newname)
{
const char *oldname;
@@ -1913,8 +1827,11 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n",
oldname, newname));
- pstring_sub(rename_script, "%unew", newname);
- pstring_sub(rename_script, "%uold", oldname);
+ /* we have to allow the account name to end with a '$' */
+ string_sub2(rename_script, "%unew", newname, sizeof(pstring),
+ True, False, True);
+ string_sub2(rename_script, "%uold", oldname, sizeof(pstring),
+ True, False, True);
rc = smbrun(rename_script, NULL);
DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n",
@@ -1931,7 +1848,7 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
we need LDAP modification.
*********************************************************************/
-static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
+static BOOL element_is_set_or_changed(const struct samu *sampass,
enum pdb_elements element)
{
return (IS_SAM_SET(sampass, element) ||
@@ -1939,10 +1856,10 @@ static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
}
/**********************************************************************
- Add SAM_ACCOUNT to LDAP.
+ Add struct samu to LDAP.
*********************************************************************/
-static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
+static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
@@ -1966,12 +1883,12 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
}
/* free this list after the second search or in case we exit on failure */
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
if (rc != LDAP_SUCCESS) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
@@ -1979,7 +1896,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n",
username));
ldap_msgfree(result);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
ldap_msgfree(result);
@@ -1992,7 +1909,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n",
sid_to_string(sid_string, sid)));
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2011,7 +1928,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
rc = smbldap_search_suffix(ldap_state->smbldap_state,
filter, attr_list, &result);
if ( rc != LDAP_SUCCESS ) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2019,7 +1936,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
if (num_result > 1) {
DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2033,7 +1950,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
if (!tmp) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2059,15 +1976,15 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
filter, attr_list, &result);
if ( rc != LDAP_SUCCESS ) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
if (num_result > 1) {
- DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
- free_attr_list( attr_list );
+ DEBUG (0, ("ldapsam_add_sam_account: More than one user with specified Sid exists: bailing out!\n"));
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2081,7 +1998,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
if (!tmp) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2090,7 +2007,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
}
}
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (num_result == 0) {
/* Check if we need to add an entry */
@@ -2155,23 +2072,11 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
int rc;
const char **attr_list;
- attr_list = get_attr_list(groupmap_attr_list);
+ attr_list = get_attr_list(NULL, groupmap_attr_list);
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_group_suffix (), scope,
filter, attr_list, 0, result);
- free_attr_list( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_search_one_group: "
- "Problem during the LDAP search: LDAP error: %s (%s)\n",
- ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
- DEBUGADD(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
- lp_ldap_group_suffix(), filter));
- SAFE_FREE(ld_error);
- }
+ TALLOC_FREE(attr_list);
return rc;
}
@@ -2245,39 +2150,10 @@ for gidNumber(%lu)\n",(unsigned long)map->gid));
}
fstrcpy(map->comment, temp);
- return True;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-static BOOL init_ldap_from_group(LDAP *ldap_struct,
- LDAPMessage *existing,
- LDAPMod ***mods,
- const GROUP_MAP *map)
-{
- pstring tmp;
-
- if (mods == NULL || map == NULL) {
- DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
- return False;
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ store_gid_sid_cache(&map->sid, map->gid);
}
- *mods = NULL;
-
- sid_to_string(tmp, &map->sid);
-
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
- pstr_sprintf(tmp, "%i", map->sid_name_use);
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
-
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
-
return True;
}
@@ -2299,7 +2175,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
return NT_STATUS_NO_SUCH_GROUP;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ count = ldap_count_entries(priv2ld(ldap_state), result);
if (count < 1) {
DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
@@ -2308,13 +2184,13 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
}
if (count > 1) {
- DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n",
- filter, count));
+ DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
+ "count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_GROUP;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
if (!entry) {
ldap_msgfree(result);
@@ -2322,8 +2198,8 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
}
if (!init_group_from_ldap(ldap_state, map, entry)) {
- DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n",
- filter));
+ DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
+ "group filter %s\n", filter));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_GROUP;
}
@@ -2448,216 +2324,256 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
struct smbldap_state *conn = ldap_state->smbldap_state;
- pstring filter;
- int rc, count;
- LDAPMessage *msg = NULL;
+ const char *id_attrs[] = { "memberUid", "gidNumber", NULL };
+ const char *sid_attrs[] = { "sambaSID", NULL };
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *result = NULL;
LDAPMessage *entry;
+ char *filter;
char **values = NULL;
char **memberuid;
- char *sid_filter = NULL;
- char *tmp;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_enum_group_members(methods, mem_ctx, group,
- pp_member_rids,
- p_num_members);
+ char *gidstr;
+ int rc, count;
*pp_member_rids = NULL;
*p_num_members = 0;
- pstr_sprintf(filter,
- "(&(objectClass=sambaSamAccount)"
- "(sambaPrimaryGroupSid=%s))",
- sid_string_static(group));
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)"
+ "(objectClass=%s)"
+ "(sambaSID=%s))",
+ LDAP_OBJ_POSIXGROUP,
+ LDAP_OBJ_GROUPMAP,
+ sid_string_static(group));
- {
- const char *attrs[] = { "sambaSID", NULL };
- rc = smbldap_search(conn, lp_ldap_user_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attrs, 0,
- &msg);
- }
+ rc = smbldap_search(conn, lp_ldap_group_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, id_attrs, 0,
+ &result);
if (rc != LDAP_SUCCESS)
goto done;
- for (entry = ldap_first_entry(conn->ldap_struct, msg);
- entry != NULL;
- entry = ldap_next_entry(conn->ldap_struct, entry))
- {
- uint32 rid;
-
- if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
- entry,
- get_global_sam_sid(),
- &rid)) {
- DEBUG(2, ("Could not find sid from ldap entry\n"));
- continue;
- }
-
- add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
- p_num_members);
- }
-
- if (msg != NULL)
- ldap_msgfree(msg);
-
- pstr_sprintf(filter,
- "(&(objectClass=sambaGroupMapping)"
- "(objectClass=posixGroup)"
- "(sambaSID=%s))",
- sid_string_static(group));
-
- {
- const char *attrs[] = { "memberUid", NULL };
- rc = smbldap_search(conn, lp_ldap_user_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attrs, 0,
- &msg);
- }
-
- if (rc != LDAP_SUCCESS)
- goto done;
+ talloc_autofree_ldapmsg(mem_ctx, result);
- count = ldap_count_entries(conn->ldap_struct, msg);
+ count = ldap_count_entries(conn->ldap_struct, result);
if (count > 1) {
DEBUG(1, ("Found more than one groupmap entry for %s\n",
sid_string_static(group)));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
}
if (count == 0) {
- result = NT_STATUS_OK;
+ ret = NT_STATUS_NO_SUCH_GROUP;
goto done;
}
- entry = ldap_first_entry(conn->ldap_struct, msg);
+ entry = ldap_first_entry(conn->ldap_struct, result);
if (entry == NULL)
goto done;
- values = ldap_get_values(conn->ldap_struct, msg, "memberUid");
- if (values == NULL) {
- result = NT_STATUS_OK;
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
+ if (!gidstr) {
+ DEBUG (0, ("ldapsam_enum_group_members: Unable to find the group's gid!\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
}
- sid_filter = SMB_STRDUP("(&(objectClass=sambaSamAccount)(|");
- if (sid_filter == NULL) {
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
+ values = ldap_get_values(conn->ldap_struct, entry, "memberUid");
+
+ if (values) {
- for (memberuid = values; *memberuid != NULL; memberuid += 1) {
- tmp = sid_filter;
- asprintf(&sid_filter, "%s(uid=%s)", tmp, *memberuid);
- free(tmp);
- if (sid_filter == NULL) {
- result = NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBAACCOUNT);
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
goto done;
}
- }
- tmp = sid_filter;
- asprintf(&sid_filter, "%s))", sid_filter);
- free(tmp);
- if (sid_filter == NULL) {
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
+ for (memberuid = values; *memberuid != NULL; memberuid += 1) {
+ filter = talloc_asprintf_append(filter, "(uid=%s)", *memberuid);
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+
+ filter = talloc_asprintf_append(filter, "))");
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
- {
- const char *attrs[] = { "sambaSID", NULL };
rc = smbldap_search(conn, lp_ldap_user_suffix(),
- LDAP_SCOPE_SUBTREE, sid_filter, attrs, 0,
- &msg);
+ LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
+ &result);
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ count = ldap_count_entries(conn->ldap_struct, result);
+ DEBUG(10,("ldapsam_enum_group_members: found %d accounts\n", count));
+
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ for (entry = ldap_first_entry(conn->ldap_struct, result);
+ entry != NULL;
+ entry = ldap_next_entry(conn->ldap_struct, entry))
+ {
+ char *sidstr;
+ DOM_SID sid;
+ uint32 rid;
+
+ sidstr = smbldap_talloc_single_attribute(conn->ldap_struct,
+ entry, "sambaSID",
+ mem_ctx);
+ if (!sidstr) {
+ DEBUG(0, ("Severe DB error, sambaSamAccount can't miss "
+ "the sambaSID attribute\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ if (!string_to_sid(&sid, sidstr))
+ goto done;
+
+ if (!sid_check_is_in_our_domain(&sid)) {
+ DEBUG(0, ("Inconsistent SAM -- group member uid not "
+ "in our domain\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ sid_peek_rid(&sid, &rid);
+
+ add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+ p_num_members);
+ }
}
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)"
+ "(gidNumber=%s))",
+ LDAP_OBJ_SAMBASAMACCOUNT,
+ gidstr);
+
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
+ &result);
+
if (rc != LDAP_SUCCESS)
goto done;
- for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ for (entry = ldap_first_entry(conn->ldap_struct, result);
entry != NULL;
entry = ldap_next_entry(conn->ldap_struct, entry))
{
- fstring str;
- DOM_SID sid;
uint32 rid;
- if (!smbldap_get_single_attribute(conn->ldap_struct,
- entry, "sambaSID",
- str, sizeof(str)-1))
- continue;
-
- if (!string_to_sid(&sid, str))
+ if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
+ entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(0, ("Severe DB error, sambaSamAccount can't miss "
+ "the sambaSID attribute\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
-
- if (!sid_check_is_in_our_domain(&sid)) {
- DEBUG(1, ("Inconsistent SAM -- group member uid not "
- "in our domain\n"));
- continue;
}
- sid_peek_rid(&sid, &rid);
-
add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
p_num_members);
}
- result = NT_STATUS_OK;
+ ret = NT_STATUS_OK;
done:
- SAFE_FREE(sid_filter);
- if (values != NULL)
+ if (values)
ldap_value_free(values);
- if (msg != NULL)
- ldap_msgfree(msg);
-
- return result;
+ return ret;
}
static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
- const char *username,
- gid_t primary_gid,
- DOM_SID **pp_sids, gid_t **pp_gids,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user,
+ DOM_SID **pp_sids,
+ gid_t **pp_gids,
size_t *p_num_groups)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
struct smbldap_state *conn = ldap_state->smbldap_state;
- pstring filter;
+ char *filter;
const char *attrs[] = { "gidNumber", "sambaSID", NULL };
char *escape_name;
- int rc;
- LDAPMessage *msg = NULL;
+ int rc, count;
+ LDAPMessage *result = NULL;
LDAPMessage *entry;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
size_t num_sids, num_gids;
-
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_enum_group_memberships(methods, username,
- primary_gid, pp_sids,
- pp_gids, p_num_groups);
+ char *gidstr;
+ gid_t primary_gid = -1;
*pp_sids = NULL;
num_sids = 0;
- escape_name = escape_ldap_string_alloc(username);
-
+ escape_name = escape_ldap_string_alloc(pdb_get_username(user));
if (escape_name == NULL)
return NT_STATUS_NO_MEMORY;
- pstr_sprintf(filter, "(&(objectClass=posixGroup)"
- "(|(memberUid=%s)(gidNumber=%d)))",
- username, primary_gid);
+ /* retrieve the users primary gid */
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)(uid=%s))",
+ LDAP_OBJ_SAMBASAMACCOUNT,
+ escape_name);
+
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ count = ldap_count_entries(priv2ld(ldap_state), result);
+
+ switch (count) {
+ case 0:
+ DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
+ ret = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ case 1:
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
+ if (!gidstr) {
+ DEBUG (1, ("Unable to find the member's gid!\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+ primary_gid = strtoul(gidstr, NULL, 10);
+ break;
+ default:
+ DEBUG(1, ("found more than one accoutn with the same user name ?!\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%d)))",
+ LDAP_OBJ_POSIXGROUP, escape_name, primary_gid);
rc = smbldap_search(conn, lp_ldap_group_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
if (rc != LDAP_SUCCESS)
goto done;
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
num_gids = 0;
*pp_gids = NULL;
@@ -2666,13 +2582,13 @@ 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(NULL, primary_gid, pp_gids, &num_gids);
+ add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids);
/* This sid will be replaced later */
- add_sid_to_array_unique(NULL, &global_sid_NULL, pp_sids, &num_sids);
+ add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
- for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ for (entry = ldap_first_entry(conn->ldap_struct, result);
entry != NULL;
entry = ldap_next_entry(conn->ldap_struct, entry))
{
@@ -2702,167 +2618,218 @@ 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(NULL, gid, pp_gids, &num_gids);
- add_sid_to_array_unique(NULL, &sid, pp_sids, &num_sids);
+ 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 (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
- DEBUG(3, ("primary group of [%s] not found\n", username));
+ DEBUG(3, ("primary group of [%s] not found\n",
+ pdb_get_username(user)));
goto done;
}
*p_num_groups = num_sids;
- result = NT_STATUS_OK;
+ ret = NT_STATUS_OK;
done:
SAFE_FREE(escape_name);
- if (msg != NULL)
- ldap_msgfree(msg);
-
- return result;
+ return ret;
}
/**********************************************************************
+ * Augment a posixGroup object with a sambaGroupMapping domgroup
*********************************************************************/
-static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
- gid_t gid,
- LDAPMessage **result)
+static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
+ struct ldapsam_privates *ldap_state,
+ GROUP_MAP *map)
{
- pstring filter;
+ const char *filter, *dn;
+ LDAPMessage *msg, *entry;
+ LDAPMod **mods;
+ int rc;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))",
- LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
- (unsigned long)gid);
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=posixGroup)(gidNumber=%u))",
+ map->gid);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- return ldapsam_search_one_group(ldap_state, filter, result);
-}
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
-/**********************************************************************
- *********************************************************************/
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+ ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
+ if (dn == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ mods = NULL;
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
+ "sambaGroupMapping");
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
+ sid_string_static(&map->sid));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
+ talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+ map->comment);
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
+}
static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
GROUP_MAP *map)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- LDAPMessage *result = NULL;
+ LDAPMessage *msg = NULL;
LDAPMod **mods = NULL;
- int count;
+ const char *attrs[] = { NULL };
+ char *filter;
- char *tmp;
- pstring dn;
- LDAPMessage *entry;
+ char *dn;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS result;
- GROUP_MAP dummy;
+ DOM_SID sid;
int rc;
- if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
- map->gid))) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_UNSUCCESSFUL;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
- if (rc != LDAP_SUCCESS) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
+ sid_string_static(&map->sid));
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
- if ( count == 0 ) {
- /* There's no posixGroup account, let's try to find an
- * appropriate idmap entry for aliases */
+ rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
- pstring suffix;
- pstring filter;
- const char **attr_list;
+ if ((rc == LDAP_SUCCESS) &&
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
- ldap_msgfree(result);
+ DEBUG(3, ("SID %s already present in LDAP, refusing to add "
+ "group mapping entry\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_GROUP_EXISTS;
+ goto done;
+ }
- pstrcpy( suffix, lp_ldap_idmap_suffix() );
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
- LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
- map->gid);
-
- attr_list = get_attr_list( sidmap_attr_list );
- rc = smbldap_search(ldap_state->smbldap_state, suffix,
- LDAP_SCOPE_SUBTREE, filter, attr_list,
- 0, &result);
+ switch (map->sid_name_use) {
- free_attr_list(attr_list);
+ case SID_NAME_DOM_GRP:
+ /* To map a domain group we need to have a posix group
+ to attach to. */
+ result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
+ goto done;
+ break;
- if (rc != LDAP_SUCCESS) {
- DEBUG(3,("Failure looking up entry (%s)\n",
- ldap_err2string(rc) ));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ case SID_NAME_ALIAS:
+ if (!sid_check_is_in_our_domain(&map->sid)
+ && !sid_check_is_in_builtin(&map->sid) )
+ {
+ DEBUG(3, ("Refusing to map sid %s as an alias, not in our domain\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- }
-
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
- if ( count == 0 ) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
- }
+ break;
- if (count > 1) {
- DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n",
- (unsigned long)map->gid));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ default:
+ DEBUG(3, ("Got invalid use '%s' for mapping\n",
+ sid_type_lookup(map->sid_name_use)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!tmp) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ /* Domain groups have been mapped in a separate routine, we have to
+ * create an alias now */
+
+ if (map->gid == -1) {
+ DEBUG(10, ("Refusing to map gid==-1\n"));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- pstrcpy(dn, tmp);
- SAFE_FREE(tmp);
- if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
- result, &mods, map)) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n"));
- ldap_mods_free(mods, True);
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_gid_to_sid(map->gid, &sid)) {
+ DEBUG(3, ("Gid %d is already mapped to SID %s, refusing to "
+ "add\n", map->gid, sid_string_static(&sid)));
+ result = NT_STATUS_GROUP_EXISTS;
+ goto done;
}
- ldap_msgfree(result);
+ /* Ok, enough checks done. It's still racy to go ahead now, but that's
+ * the best we can get out of LDAP. */
- if (mods == NULL) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n"));
- return NT_STATUS_UNSUCCESSFUL;
+ dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
+ sid_string_static(&map->sid),
+ lp_ldap_group_suffix());
+ if (dn == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
+ mods = NULL;
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- ldap_mods_free(mods, True);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+ "sambaSidEntry");
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+ "sambaGroupMapping");
- 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, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid,
- ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
- return NT_STATUS_UNSUCCESSFUL;
- }
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
+ sid_string_static(&map->sid));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
+ talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
+ map->comment);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
+ talloc_asprintf(mem_ctx, "%u", map->gid));
+ talloc_autofree_ldapmod(mem_ctx, mods);
- DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_OK;
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+
+ result = (rc == LDAP_SUCCESS) ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
}
/**********************************************************************
+ * Update a group mapping entry. We're quite strict about what can be changed:
+ * Only the description and displayname may be changed. It simply does not
+ * make any sense to change the SID, gid or the type in a mapping.
*********************************************************************/
static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
@@ -2871,63 +2838,81 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
int rc;
- char *dn = NULL;
- LDAPMessage *result = NULL;
+ const char *filter, *dn;
+ LDAPMessage *msg = NULL;
LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS result;
- rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_UNSUCCESSFUL;
+ /* Make 100% sure that sid, gid and type are not changed by looking up
+ * exactly the values we're given in LDAP. */
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)"
+ "(sambaSid=%s)(gidNumber=%u)"
+ "(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP,
+ sid_string_static(&map->sid), map->gid,
+ map->sid_name_use);
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
- DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n"));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+ ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+ result = NT_STATUS_NO_SUCH_GROUP;
+ goto done;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
- if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
- result, &mods, map)) {
- DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n"));
- ldap_msgfree(result);
- if (mods != NULL)
- ldap_mods_free(mods,True);
- return NT_STATUS_UNSUCCESSFUL;
+ if (dn == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
+ mods = NULL;
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+ map->comment);
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
if (mods == NULL) {
- DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n"));
- ldap_msgfree(result);
- return NT_STATUS_OK;
+ DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
+ "nothing to do\n"));
+ result = NT_STATUS_OK;
+ goto done;
}
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
- }
rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- SAFE_FREE(dn);
-
- ldap_mods_free(mods, True);
- ldap_msgfree(result);
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, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid,
- ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
- return NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_ACCESS_DENIED;
+ goto done;
}
- DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_OK;
+ DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
+ "group %lu in LDAP\n", (unsigned long)map->gid));
+
+ result = NT_STATUS_OK;
+
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
}
/**********************************************************************
@@ -2936,53 +2921,103 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
DOM_SID sid)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
- pstring sidstring, filter;
- LDAPMessage *result = NULL;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *msg, *entry;
int rc;
- NTSTATUS ret;
- const char **attr_list;
+ NTSTATUS result;
+ TALLOC_CTX *mem_ctx;
+ char *filter;
- sid_to_string(sidstring, &sid);
-
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
+ sid_string_static(&sid));
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ rc = smbldap_search_suffix(priv->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+ ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+ result = NT_STATUS_NO_SUCH_GROUP;
+ goto done;
+ }
- rc = ldapsam_search_one_group(ldap_state, filter, &result);
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
+ get_attr_list(mem_ctx,
+ groupmap_attr_list_to_delete));
+
+ if ((rc == LDAP_NAMING_VIOLATION) ||
+ (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+ const char *attrs[] = { "sambaGroupType", "description",
+ "displayName", "sambaSIDList",
+ NULL };
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_NO_SUCH_GROUP;
+ /* Second try. Don't delete the sambaSID attribute, this is
+ for "old" entries that are tacked on a winbind
+ sambaIdmapEntry. */
+
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+ LDAP_OBJ_GROUPMAP, attrs);
}
- attr_list = get_attr_list( groupmap_attr_list_to_delete );
- ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
- free_attr_list ( attr_list );
+ if ((rc == LDAP_NAMING_VIOLATION) ||
+ (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+ const char *attrs[] = { "sambaGroupType", "description",
+ "displayName", "sambaSIDList",
+ "gidNumber", NULL };
- ldap_msgfree(result);
+ /* Third try. This is a post-3.0.21 alias (containing only
+ * sambaSidEntry and sambaGroupMapping classes), we also have
+ * to delete the gidNumber attribute, only the sambaSidEntry
+ * remains */
- return ret;
-}
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+ LDAP_OBJ_GROUPMAP, attrs);
+ }
+
+ result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
+ }
/**********************************************************************
*********************************************************************/
-static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
+static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
+ BOOL update)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
fstring filter;
int rc;
const char **attr_list;
pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
- attr_list = get_attr_list( groupmap_attr_list );
+ attr_list = get_attr_list( NULL, groupmap_attr_list );
rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &ldap_state->result);
- free_attr_list( attr_list );
+ TALLOC_FREE(attr_list);
if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc)));
- DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
+ DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
+ ldap_err2string(rc)));
+ DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
+ lp_ldap_group_suffix(), filter));
ldap_msgfree(ldap_state->result);
ldap_state->result = NULL;
return NT_STATUS_UNSUCCESSFUL;
@@ -2992,7 +3027,9 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
ldap_state->result)));
- ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
+ ldap_state->entry =
+ ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->result);
ldap_state->index = 0;
return NT_STATUS_OK;
@@ -3013,7 +3050,8 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
GROUP_MAP *map)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
BOOL bret = False;
while (!bret) {
@@ -3021,10 +3059,12 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
return ret;
ldap_state->index++;
- bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
+ bret = init_group_from_ldap(ldap_state, map,
+ ldap_state->entry);
- ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->entry);
+ ldap_state->entry =
+ ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->entry);
}
return NT_STATUS_OK;
@@ -3034,43 +3074,44 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
*********************************************************************/
static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
- enum SID_NAME_USE sid_name_use,
- GROUP_MAP **pp_rmap, size_t *p_num_entries,
+ const DOM_SID *domsid, enum SID_NAME_USE sid_name_use,
+ GROUP_MAP **pp_rmap,
+ size_t *p_num_entries,
BOOL unix_only)
{
GROUP_MAP map;
- GROUP_MAP *mapt;
size_t entries = 0;
*p_num_entries = 0;
*pp_rmap = NULL;
if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
- DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n"));
+ DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
+ "passdb\n"));
return NT_STATUS_ACCESS_DENIED;
}
while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
if (sid_name_use != SID_NAME_UNKNOWN &&
sid_name_use != map.sid_name_use) {
- DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
+ DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+ "not of the requested type\n", map.nt_name));
continue;
}
if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
- DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name));
+ DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+ "non mapped\n", map.nt_name));
continue;
}
- mapt=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
- if (!mapt) {
- DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n"));
- SAFE_FREE(*pp_rmap);
+ (*pp_rmap)=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
+ if (!(*pp_rmap)) {
+ DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
+ "enlarge group map!\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- else
- (*pp_rmap) = mapt;
- mapt[entries] = map;
+ (*pp_rmap)[entries] = map;
entries += 1;
@@ -3095,14 +3136,28 @@ 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;
pstring filter;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list,
- LDAP_ATTR_GROUP_SID),
- sid_string_static(alias));
+ if (sid_check_is_in_builtin(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (sid_check_is_in_our_domain(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+ sid_string_static(alias)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ pstr_sprintf(filter,
+ "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+ type);
if (ldapsam_search_one_group(ldap_state, filter,
&result) != LDAP_SUCCESS)
@@ -3118,8 +3173,8 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
}
if (count > 1) {
- DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for filter %s: "
- "count=%d\n", filter, count));
+ DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
+ "filter %s: count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_ALIAS;
}
@@ -3147,22 +3202,20 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
ldap_mods_free(mods, True);
ldap_msgfree(result);
+ SAFE_FREE(dn);
+
+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
+ return NT_STATUS_MEMBER_IN_ALIAS;
+ }
+
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
+ return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+ }
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, ("ldapsam_modify_aliasmem: Could not modify alias "
- "for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
- SAFE_FREE(dn);
return NT_STATUS_UNSUCCESSFUL;
}
- SAFE_FREE(dn);
-
return NT_STATUS_OK;
}
@@ -3182,7 +3235,8 @@ static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
}
static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
- const DOM_SID *alias, DOM_SID **pp_members,
+ const DOM_SID *alias,
+ DOM_SID **pp_members,
size_t *p_num_members)
{
struct ldapsam_privates *ldap_state =
@@ -3194,15 +3248,29 @@ 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;
*pp_members = NULL;
*p_num_members = 0;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list,
- LDAP_ATTR_GROUP_SID),
- sid_string_static(alias));
+ if (sid_check_is_in_builtin(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (sid_check_is_in_our_domain(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+ sid_string_static(alias)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ pstr_sprintf(filter,
+ "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+ type);
if (ldapsam_search_one_group(ldap_state, filter,
&result) != LDAP_SUCCESS)
@@ -3218,8 +3286,8 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
}
if (count > 1) {
- DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for filter %s: "
- "count=%d\n", filter, count));
+ DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
+ "filter %s: count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_ALIAS;
}
@@ -3279,14 +3347,25 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
int i;
int rc;
char *filter;
+ enum SID_NAME_USE type = SID_NAME_USE_NONE;
+
+ if (sid_check_is_builtin(domain_sid)) {
+ type = SID_NAME_ALIAS;
+ }
- /* This query could be further optimized by adding a
- (&(sambaSID=<domain-sid>*)) so that only those aliases that are
- asked for in the getuseraliases are returned. */
+ if (sid_check_is_domain(domain_sid)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither builtin nor domain!\n",
+ sid_string_static(domain_sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
filter = talloc_asprintf(mem_ctx,
- "(&(|(objectclass=%s)(objectclass=%s))(|",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY);
+ "(&(|(objectclass=%s)(sambaGroupType=%d))(|",
+ LDAP_OBJ_GROUPMAP, type);
for (i=0; i<num_members; i++)
filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
@@ -3331,7 +3410,9 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
return NT_STATUS_OK;
}
-static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, int policy_index, uint32 value)
+static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
+ int policy_index,
+ uint32 value)
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
int rc;
@@ -3352,7 +3433,8 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
policy_attr = get_account_policy_attr(policy_index);
if (policy_attr == NULL) {
- DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid policy\n"));
+ DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
+ "policy\n"));
return ntstatus;
}
@@ -3363,40 +3445,39 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
- rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods);
+ rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
+ mods);
ldap_mods_free(mods, True);
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING,&ld_error);
-
- DEBUG(0, ("ldapsam_set_account_policy_in_ldap: Could not set account policy "
- "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
return ntstatus;
}
if (!cache_account_policy_set(policy_index, value)) {
- DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to update local tdb cache\n"));
+ DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
+ "update local tdb cache\n"));
return ntstatus;
}
return NT_STATUS_OK;
}
-static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
+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 (account_policy_set(policy_index, value)) ?
+ NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
- return ldapsam_set_account_policy_in_ldap(methods, policy_index, value);
+ return ldapsam_set_account_policy_in_ldap(methods, policy_index,
+ value);
}
-static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value)
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
+ int policy_index,
+ uint32 *value)
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
LDAPMessage *result = NULL;
@@ -3419,7 +3500,8 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
policy_attr = get_account_policy_attr(policy_index);
if (!policy_attr) {
- DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid policy index: %d\n", policy_index));
+ DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
+ "policy index: %d\n", policy_index));
return ntstatus;
}
@@ -3427,31 +3509,24 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
attrs[1] = NULL;
rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
- LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result);
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
+ &result);
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING,&ld_error);
-
- DEBUG(3, ("ldapsam_get_account_policy_from_ldap: Could not get account policy "
- "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
return ntstatus;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ count = ldap_count_entries(priv2ld(ldap_state), result);
if (count < 1) {
goto out;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
if (entry == NULL) {
goto out;
}
- vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, policy_attr);
+ vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
if (vals == NULL) {
goto out;
}
@@ -3470,7 +3545,8 @@ out:
/* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache
- - if user hasn't decided to use account policies inside LDAP just reuse the old tdb values
+ - if user hasn't decided to use account policies inside LDAP just reuse the
+ old tdb values
- if there is a valid cache entry, return that
- if there is an LDAP entry, update cache and return
@@ -3478,32 +3554,38 @@ out:
Guenther
*/
-static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
+ int policy_index, uint32 *value)
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
if (!account_policy_migrated(False)) {
- return (account_policy_get(policy_index, value)) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ 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"));
+ DEBUG(11,("ldapsam_get_account_policy: got valid value from "
+ "cache\n"));
return NT_STATUS_OK;
}
- ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, value);
+ ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index,
+ value);
if (NT_STATUS_IS_OK(ntstatus)) {
goto update_cache;
}
- DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from ldap\n"));
+ DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
+ "ldap\n"));
#if 0
/* should we automagically migrate old tdb value here ? */
if (account_policy_get(policy_index, value))
goto update_ldap;
- DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying default\n", policy_index));
+ DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
+ "default\n", policy_index));
#endif
if (!account_policy_get_default(policy_index, value)) {
@@ -3520,7 +3602,8 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int poli
update_cache:
if (!cache_account_policy_set(policy_index, *value)) {
- DEBUG(0,("ldapsam_get_account_policy: failed to update local tdb as a cache\n"));
+ DEBUG(0,("ldapsam_get_account_policy: failed to update local "
+ "tdb as a cache\n"));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -3536,39 +3619,43 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct;
LDAPMessage *msg = NULL;
LDAPMessage *entry;
char *allsids = NULL;
- char *tmp;
int i, rc, num_mapped;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
+ TALLOC_CTX *mem_ctx;
+ LDAP *ld;
+ BOOL is_builtin;
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_lookup_rids(methods, domain_sid,
- num_rids, rids, names, attrs);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ goto done;
+ }
- if (!sid_equal(domain_sid, get_global_sam_sid())) {
- /* TODO: Sooner or later we need to look up BUILTIN rids as
- * well. -- vl */
+ if (!sid_check_is_builtin(domain_sid) &&
+ !sid_check_is_domain(domain_sid)) {
+ result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
for (i=0; i<num_rids; i++)
attrs[i] = SID_NAME_UNKNOWN;
- allsids = SMB_STRDUP("");
- if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+ allsids = talloc_strdup(mem_ctx, "");
+ if (allsids == NULL) {
+ goto done;
+ }
for (i=0; i<num_rids; i++) {
DOM_SID sid;
- sid_copy(&sid, domain_sid);
- sid_append_rid(&sid, rids[i]);
- tmp = allsids;
- asprintf(&allsids, "%s(sambaSid=%s)", allsids,
- sid_string_static(&sid));
- if (allsids == NULL) return NT_STATUS_NO_MEMORY;
- free(tmp);
+ sid_compose(&sid, domain_sid, rids[i]);
+ allsids = talloc_asprintf_append(allsids, "(sambaSid=%s)",
+ sid_string_static(&sid));
+ if (allsids == NULL) {
+ goto done;
+ }
}
/* First look for users */
@@ -3577,40 +3664,43 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
char *filter;
const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
- asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
- allsids);
- if (filter == NULL) return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(
+ mem_ctx, ("(&(objectClass=%s)(|%s))"),
+ LDAP_OBJ_SAMBASAMACCOUNT, allsids);
+
+ if (filter == NULL) {
+ goto done;
+ }
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_user_suffix(),
LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
&msg);
-
- SAFE_FREE(filter);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
}
if (rc != LDAP_SUCCESS)
goto done;
+ ld = ldap_state->smbldap_state->ldap_struct;
num_mapped = 0;
- for (entry = ldap_first_entry(ldap_struct, msg);
+ for (entry = ldap_first_entry(ld, msg);
entry != NULL;
- entry = ldap_next_entry(ldap_struct, entry))
- {
+ entry = ldap_next_entry(ld, entry)) {
uint32 rid;
int rid_index;
- fstring str;
+ const char *name;
- if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
- get_global_sam_sid(),
+ if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
&rid)) {
DEBUG(2, ("Could not find sid from ldap entry\n"));
continue;
}
- if (!smbldap_get_single_attribute(ldap_struct, entry,
- "uid", str, sizeof(str)-1)) {
+ name = smbldap_talloc_single_attribute(ld, entry, "uid",
+ names);
+ if (name == NULL) {
DEBUG(2, ("Could not retrieve uid attribute\n"));
continue;
}
@@ -3626,9 +3716,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
}
attrs[rid_index] = SID_NAME_USER;
- names[rid_index] = talloc_strdup(names, str);
- if (names[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
-
+ names[rid_index] = name;
num_mapped += 1;
}
@@ -3638,49 +3726,82 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
goto done;
}
- if (msg != NULL) {
- ldap_msgfree(msg);
- }
-
/* Same game for groups */
{
char *filter;
- const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
+ const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
+ "sambaGroupType", NULL };
- asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
- allsids);
- if (filter == NULL) return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(
+ mem_ctx, "(&(objectClass=%s)(|%s))",
+ LDAP_OBJ_GROUPMAP, allsids);
+ if (filter == NULL) {
+ goto done;
+ }
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
&msg);
-
- SAFE_FREE(filter);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
}
if (rc != LDAP_SUCCESS)
goto done;
- for (entry = ldap_first_entry(ldap_struct, msg);
+ /* ldap_struct might have changed due to a reconnect */
+
+ ld = ldap_state->smbldap_state->ldap_struct;
+
+ /* For consistency checks, we already checked we're only domain or builtin */
+
+ is_builtin = sid_check_is_builtin(domain_sid);
+
+ for (entry = ldap_first_entry(ld, msg);
entry != NULL;
- entry = ldap_next_entry(ldap_struct, entry))
+ entry = ldap_next_entry(ld, entry))
{
uint32 rid;
int rid_index;
- fstring str;
+ const char *attr;
+ enum SID_NAME_USE type;
+ const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
+
+ attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
+ mem_ctx);
+ if (attr == NULL) {
+ DEBUG(2, ("Could not extract type from ldap entry %s\n",
+ dn));
+ continue;
+ }
- if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
- get_global_sam_sid(),
+ type = atol(attr);
+
+ /* Consistency checks */
+ if ((is_builtin && (type != SID_NAME_ALIAS)) ||
+ (!is_builtin && ((type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_DOM_GRP)))) {
+ DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
+ }
+
+ if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
&rid)) {
- DEBUG(2, ("Could not find sid from ldap entry\n"));
+ DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
continue;
}
- if (!smbldap_get_single_attribute(ldap_struct, entry,
- "cn", str, sizeof(str)-1)) {
- DEBUG(2, ("Could not retrieve cn attribute\n"));
+ attr = smbldap_talloc_single_attribute(ld, entry, "displayName", names);
+
+ if (attr == NULL) {
+ DEBUG(10, ("Could not retrieve 'displayName' attribute from %s\n",
+ dn));
+ attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
+ }
+
+ if (attr == NULL) {
+ DEBUG(2, ("Could not retrieve naming attribute from %s\n",
+ dn));
continue;
}
@@ -3694,9 +3815,8 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
continue;
}
- attrs[rid_index] = SID_NAME_DOM_GRP;
- names[rid_index] = talloc_strdup(names, str);
- if (names[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+ attrs[rid_index] = type;
+ names[rid_index] = attr;
num_mapped += 1;
}
@@ -3706,15 +3826,11 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
result = (num_mapped == num_rids) ?
NT_STATUS_OK : STATUS_SOME_UNMAPPED;
done:
- SAFE_FREE(allsids);
-
- if (msg != NULL)
- ldap_msgfree(msg);
-
+ TALLOC_FREE(mem_ctx);
return result;
}
-char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
+static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
{
char *filter = NULL;
char *escaped = NULL;
@@ -3727,8 +3843,7 @@ char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
escaped = escape_ldap_string_alloc(username);
if (escaped == NULL) goto done;
- filter = realloc_string_sub(filter, "%u", username);
- result = talloc_strdup(mem_ctx, filter);
+ result = talloc_string_sub(mem_ctx, filter, "%u", username);
done:
SAFE_FREE(filter);
@@ -3762,7 +3877,7 @@ const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
struct ldap_search_state {
struct smbldap_state *connection;
- uint16 acct_flags;
+ uint32 acct_flags;
uint16 group_type;
const char *base;
@@ -3834,7 +3949,6 @@ 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;
- LDAP *ld = state->connection->ldap_struct;
int rc;
if (!state->connection->paged_results) {
@@ -3851,7 +3965,7 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search)
if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
return False;
- state->current_entry = ldap_first_entry(ld, state->entries);
+ state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
if (state->current_entry == NULL) {
ldap_msgfree(state->entries);
@@ -3865,7 +3979,6 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
struct samr_displayentry *entry)
{
struct ldap_search_state *state = search->private_data;
- LDAP *ld = state->connection->ldap_struct;
BOOL result;
retry:
@@ -3876,17 +3989,17 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
!ldapsam_search_nextpage(search))
return False;
- result = state->ldap2displayentry(state, search->mem_ctx, ld,
+ result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct,
state->current_entry, entry);
if (!result) {
char *dn;
- dn = ldap_get_dn(ld, state->current_entry);
+ dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
if (dn != NULL) ldap_memfree(dn);
}
- state->current_entry = ldap_next_entry(ld, state->current_entry);
+ state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
if (state->current_entry == NULL) {
ldap_msgfree(state->entries);
@@ -3935,7 +4048,7 @@ static BOOL ldapuser2displayentry(struct ldap_search_state *state,
{
char **vals;
DOM_SID sid;
- uint16 acct_flags;
+ uint32 acct_flags;
vals = ldap_get_values(ld, entry, "sambaAcctFlags");
if ((vals == NULL) || (vals[0] == NULL)) {
@@ -4003,7 +4116,8 @@ static BOOL ldapuser2displayentry(struct ldap_search_state *state,
ldap_value_free(vals);
if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
- DEBUG(0, ("sid %s does not belong to our domain\n", sid_string_static(&sid)));
+ DEBUG(0, ("sid %s does not belong to our domain\n",
+ sid_string_static(&sid)));
return False;
}
@@ -4013,7 +4127,7 @@ static BOOL ldapuser2displayentry(struct ldap_search_state *state,
static BOOL ldapsam_search_users(struct pdb_methods *methods,
struct pdb_search *search,
- uint16 acct_flags)
+ uint32 acct_flags)
{
struct ldapsam_privates *ldap_state = methods->private_data;
struct ldap_search_state *state;
@@ -4103,10 +4217,14 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
DEBUG(5, ("\"cn\" not found\n"));
return False;
}
- pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
}
else {
- pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
}
ldap_value_free(vals);
@@ -4147,21 +4265,15 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
case SID_NAME_DOM_GRP:
case SID_NAME_ALIAS:
- if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
- DEBUG(0, ("%s is not in our domain\n", sid_string_static(&sid)));
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)
+ && !sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid))
+ {
+ DEBUG(0, ("%s is not in our domain\n",
+ sid_string_static(&sid)));
return False;
}
break;
- case SID_NAME_WKN_GRP:
-
- if (!sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid)) {
-
- DEBUG(0, ("%s is not in builtin sid\n", sid_string_static(&sid)));
- return False;
- }
- break;
-
default:
DEBUG(0,("unkown group type: %d\n", group_type));
return False;
@@ -4172,6 +4284,7 @@ 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)
{
struct ldapsam_privates *ldap_state = methods->private_data;
@@ -4190,9 +4303,11 @@ static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
state->scope = LDAP_SCOPE_SUBTREE;
state->filter = talloc_asprintf(search->mem_ctx,
"(&(objectclass=sambaGroupMapping)"
- "(sambaGroupType=%d))", type);
+ "(sambaGroupType=%d)(sambaSID=%s))",
+ type, sid_string_static(sid));
state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
- "displayName", "description", "sambaGroupType", NULL);
+ "displayName", "description",
+ "sambaGroupType", NULL);
state->attrsonly = 0;
state->pagedresults_cookie = NULL;
state->entries = NULL;
@@ -4214,25 +4329,1005 @@ static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
static BOOL ldapsam_search_groups(struct pdb_methods *methods,
struct pdb_search *search)
{
- return ldapsam_search_grouptype(methods, search, SID_NAME_DOM_GRP);
+ return ldapsam_search_grouptype(methods, search, get_global_sam_sid(), SID_NAME_DOM_GRP);
}
static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
struct pdb_search *search,
const DOM_SID *sid)
{
- if (sid_check_is_domain(sid))
- return ldapsam_search_grouptype(methods, search,
- SID_NAME_ALIAS);
+ return ldapsam_search_grouptype(methods, search, sid, SID_NAME_ALIAS);
+}
+
+static BOOL ldapsam_rid_algorithm(struct pdb_methods *methods)
+{
+ return False;
+}
+
+static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
+ uint32 *rid)
+{
+ struct smbldap_state *smbldap_state = priv->smbldap_state;
+
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ NTSTATUS status;
+ char *value;
+ int rc;
+ uint32 nextRid = 0;
- if (sid_check_is_builtin(sid))
- return ldapsam_search_grouptype(methods, search,
- SID_NAME_WKN_GRP);
+ TALLOC_CTX *mem_ctx;
- DEBUG(5, ("Don't know SID %s\n", sid_string_static(sid)));
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = smbldap_search_domain_info(smbldap_state, &result,
+ get_global_sam_name(), False);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("Could not get domain info: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ entry = ldap_first_entry(priv2ld(priv), result);
+ if (entry == NULL) {
+ DEBUG(0, ("Could not get domain info entry\n"));
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ /* Find the largest of the three attributes "sambaNextRid",
+ "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
+ concept of differentiating between user and group rids, and will
+ use only "sambaNextRid" in the future. But for compatibility
+ reasons I look if others have chosen different strategies -- VL */
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextUserRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextGroupRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
+
+ if (nextRid == 0) {
+ nextRid = BASE_RID-1;
+ }
+
+ nextRid += 1;
+
+ smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
+ talloc_asprintf(mem_ctx, "%d", nextRid));
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
+ rc = smbldap_modify(smbldap_state,
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry),
+ mods);
+
+ /* ACCESS_DENIED is used as a placeholder for "the modify failed,
+ * please retry" */
+
+ status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+ if (NT_STATUS_IS_OK(status)) {
+ *rid = nextRid;
+ }
+
+ TALLOC_FREE(mem_ctx);
+ return status;
+}
+
+static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
+{
+ int i;
+
+ for (i=0; i<10; i++) {
+ NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
+ rid);
+ if (NT_STATUS_IS_OK(result)) {
+ return True;
+ }
+
+ if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+ return False;
+ }
+
+ /* The ldap update failed (maybe a race condition), retry */
+ }
+
+ /* Tried 10 times, fail. */
return False;
}
+static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
+ const DOM_SID *sid,
+ union unid_t *id, enum SID_NAME_USE *type)
+{
+ struct ldapsam_privates *priv = methods->private_data;
+ char *filter;
+ const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
+ NULL };
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ BOOL ret = False;
+ char *value;
+ int rc;
+
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(sambaSid=%s)"
+ "(|(objectClass=%s)(objectClass=%s)))",
+ sid_string_static(sid),
+ LDAP_OBJ_GROUPMAP, LDAP_OBJ_SAMBASAMACCOUNT);
+ if (filter == NULL) {
+ DEBUG(5, ("talloc_asprintf failed\n"));
+ goto done;
+ }
+
+ rc = smbldap_search_suffix(priv->smbldap_state, filter,
+ attrs, &result);
+ if (rc != LDAP_SUCCESS) {
+ goto done;
+ }
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ if (ldap_count_entries(priv2ld(priv), result) != 1) {
+ DEBUG(10, ("Got %d entries, expected one\n",
+ ldap_count_entries(priv2ld(priv), result)));
+ goto done;
+ }
+
+ entry = ldap_first_entry(priv2ld(priv), result);
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaGroupType", mem_ctx);
+
+ if (value != NULL) {
+ const char *gid_str;
+ /* It's a group */
+
+ gid_str = smbldap_talloc_single_attribute(
+ priv2ld(priv), entry, "gidNumber", mem_ctx);
+ if (gid_str == NULL) {
+ DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv),
+ entry)));
+ goto done;
+ }
+
+ id->gid = strtoul(gid_str, NULL, 10);
+ *type = strtoul(value, NULL, 10);
+ ret = True;
+ goto done;
+ }
+
+ /* It must be a user */
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "uidNumber", mem_ctx);
+ if (value == NULL) {
+ DEBUG(1, ("Could not find uidNumber in %s\n",
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
+ goto done;
+ }
+
+ id->uid = strtoul(value, NULL, 10);
+ *type = SID_NAME_USER;
+
+ ret = True;
+ done:
+ TALLOC_FREE(mem_ctx);
+ return ret;
+}
+
+/*
+ * The following functions is called only if
+ * ldapsam:trusted and ldapsam:editposix are
+ * set to true
+ */
+
+/*
+ * ldapsam_create_user creates a new
+ * posixAccount and sambaSamAccount object
+ * in the ldap users subtree
+ *
+ * The uid is allocated by winbindd.
+ */
+
+static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx, const char *name,
+ uint32 acb_info, uint32 *rid)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ BOOL is_machine = False;
+ BOOL add_posix = False;
+ LDAPMod **mods = NULL;
+ struct samu *user;
+ char *filter;
+ char *username;
+ char *homedir;
+ char *gidstr;
+ char *uidstr;
+ char *shell;
+ const char *dn = NULL;
+ DOM_SID group_sid;
+ DOM_SID user_sid;
+ gid_t gid = -1;
+ uid_t uid = -1;
+ NTSTATUS ret;
+ int rc;
+
+ if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
+ acb_info & ACB_WSTRUST ||
+ acb_info & ACB_SVRTRUST ||
+ acb_info & ACB_DOMTRUST) {
+ is_machine = True;
+ }
+
+ username = escape_ldap_string_alloc(name);
+ filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))",
+ username, LDAP_OBJ_POSIXACCOUNT);
+ SAFE_FREE(username);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_user: ldap search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_create_user: More than one user with name [%s] ?!\n", name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (num_result == 1) {
+ char *tmp;
+ /* check if it is just a posix account.
+ * or if there is a sid attached to this entry
+ */
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
+ if (tmp) {
+ DEBUG (1, ("ldapsam_create_user: The user [%s] already exist!\n", name));
+ return NT_STATUS_USER_EXISTS;
+ }
+
+ /* it is just a posix account, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_create_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (num_result == 0) {
+ add_posix = True;
+ }
+
+ /* Create the basic samu structure and generate the mods for the ldap commit */
+ if (!NT_STATUS_IS_OK((ret = ldapsam_get_new_rid(ldap_state, rid)))) {
+ DEBUG(1, ("ldapsam_create_user: Could not allocate a new RID\n"));
+ return ret;
+ }
+
+ sid_compose(&user_sid, get_global_sam_sid(), *rid);
+
+ user = samu_new(tmp_ctx);
+ if (!user) {
+ DEBUG(1,("ldapsam_create_user: Unable to allocate user struct\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_username(user, name, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (!pdb_set_domain(user, get_global_sam_name(), PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (is_machine) {
+ if (acb_info & ACB_NORMAL) {
+ if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ } else {
+ if (!pdb_set_acct_ctrl(user, acb_info, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ } else {
+ if (!pdb_set_acct_ctrl(user, ACB_NORMAL | ACB_DISABLED, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (!pdb_set_user_sid(user, &user_sid, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!init_ldap_from_sam(ldap_state, NULL, &mods, user, element_is_set_or_changed)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT) {
+ DEBUG(1,("ldapsam_create_user: Unsupported schema version\n"));
+ }
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
+
+ if (add_posix) {
+ DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
+
+ /* retrieve the Domain Users group gid */
+ if (!sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS) ||
+ !sid_to_gid(&group_sid, &gid)) {
+ DEBUG (0, ("ldapsam_create_user: Unable to get the Domain Users gid: bailing out!\n"));
+ return NT_STATUS_INVALID_PRIMARY_GROUP;
+ }
+
+ /* lets allocate a new userid for this user */
+ if (!winbind_allocate_uid(&uid)) {
+ DEBUG (0, ("ldapsam_create_user: Unable to allocate a new user id: bailing out!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+
+ if (is_machine) {
+ /* TODO: choose a more appropriate default for machines */
+ homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), "SMB_workstations_home", ldap_state->domain_name, uid, gid);
+ shell = talloc_strdup(tmp_ctx, "/bin/false");
+ } else {
+ homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), name, ldap_state->domain_name, uid, gid);
+ shell = talloc_sub_specified(tmp_ctx, lp_template_shell(), name, ldap_state->domain_name, uid, gid);
+ }
+ uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
+ gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+ if (is_machine) {
+ dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_machine_suffix ());
+ } else {
+ dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_user_suffix ());
+ }
+
+ if (!homedir || !shell || !uidstr || !gidstr || !dn) {
+ DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", homedir);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
+ }
+
+ talloc_autofree_ldapmod(tmp_ctx, mods);
+
+ if (add_posix) {
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+ } else {
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_user: failed to create a new user [%s] (dn = %s)\n", name ,dn));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(2,("ldapsam_create_user: added account [%s] in the LDAP database\n", name));
+
+ flush_pwnam_cache();
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, struct samu *sam_acct)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int num_result;
+ const char *dn;
+ char *filter;
+ int rc;
+
+ DEBUG(0,("ldapsam_delete_user: Attempt to delete user [%s]\n", pdb_get_username(sam_acct)));
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(uid=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ pdb_get_username(sam_acct),
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_delete_user: user search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(0,("ldapsam_delete_user: user not found!\n"));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_delete_user: More than one user with name [%s] ?!\n", pdb_get_username(sam_acct)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* it is just a posix account, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_delete_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = smbldap_delete(ldap_state->smbldap_state, dn);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ flush_pwnam_cache();
+
+ return NT_STATUS_OK;
+}
+
+/*
+ * ldapsam_create_group creates a new
+ * posixGroup and sambaGroupMapping object
+ * in the ldap groups subtree
+ *
+ * The gid is allocated by winbindd.
+ */
+
+static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ const char *name,
+ uint32 *rid)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ NTSTATUS ret;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ BOOL is_new_entry = False;
+ LDAPMod **mods = NULL;
+ char *filter;
+ char *groupsidstr;
+ char *groupname;
+ char *grouptype;
+ char *gidstr;
+ const char *dn = NULL;
+ DOM_SID group_sid;
+ gid_t gid = -1;
+ int rc;
+
+ groupname = escape_ldap_string_alloc(name);
+ filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
+ groupname, LDAP_OBJ_POSIXGROUP);
+ SAFE_FREE(groupname);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_group: ldap search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_create_group: There exists more than one group with name [%s]: bailing out!\n", name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (num_result == 1) {
+ char *tmp;
+ /* check if it is just a posix group.
+ * or if there is a sid attached to this entry
+ */
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
+ if (tmp) {
+ DEBUG (1, ("ldapsam_create_group: The group [%s] already exist!\n", name));
+ return NT_STATUS_GROUP_EXISTS;
+ }
+
+ /* it is just a posix group, retrieve the gid and the dn for later use */
+ tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
+ if (!tmp) {
+ DEBUG (1, ("ldapsam_create_group: Couldn't retrieve the gidNumber for [%s]?!?!\n", name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ gid = strtoul(tmp, NULL, 10);
+
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (num_result == 0) {
+ DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
+
+ is_new_entry = True;
+
+ /* lets allocate a new groupid for this group */
+ if (!winbind_allocate_gid(&gid)) {
+ DEBUG (0, ("ldapsam_create_group: Unable to allocate a new group id: bailing out!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+ dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, lp_ldap_group_suffix());
+
+ if (!gidstr || !dn) {
+ DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ }
+
+ if (!NT_STATUS_IS_OK((ret = ldapsam_get_new_rid(ldap_state, rid)))) {
+ DEBUG(1, ("ldapsam_create_group: Could not allocate a new RID\n"));
+ return ret;
+ }
+
+ sid_compose(&group_sid, get_global_sam_sid(), *rid);
+
+ groupsidstr = talloc_strdup(tmp_ctx, sid_string_static(&group_sid));
+ grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
+
+ if (!groupsidstr || !grouptype) {
+ DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
+ talloc_autofree_ldapmod(tmp_ctx, mods);
+
+ if (is_new_entry) {
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+#if 0
+ if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
+ /* This call may fail with rfc2307bis schema */
+ /* Retry adding a structural class */
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", "????");
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+ }
+#endif
+ } else {
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_group: failed to create a new group [%s] (dn = %s)\n", name ,dn));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(2,("ldapsam_create_group: added group [%s] in the LDAP database\n", name));
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, uint32 rid)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int num_result;
+ const char *dn;
+ char *gidstr;
+ char *filter;
+ DOM_SID group_sid;
+ int rc;
+
+ /* get the group sid */
+ sid_compose(&group_sid, get_global_sam_sid(), rid);
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(sambaSID=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ sid_string_static(&group_sid),
+ LDAP_OBJ_POSIXGROUP,
+ LDAP_OBJ_GROUPMAP);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_delete_dom_group: group search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(1,("ldapsam_delete_dom_group: group not found!\n"));
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_delete_dom_group: More than one group with the same SID ?!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* here it is, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_delete_dom_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
+ if (!gidstr) {
+ DEBUG (0, ("ldapsam_delete_dom_group: Unable to find the group's gid!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* check no user have this group marked as primary group */
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(gidNumber=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ gidstr,
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_delete_dom_group: accounts search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result != 0) {
+ DEBUG(3,("ldapsam_delete_dom_group: Can't delete group, it is a primary group for %d users\n", num_result));
+ return NT_STATUS_MEMBERS_PRIMARY_GROUP;
+ }
+
+ rc = smbldap_delete(ldap_state->smbldap_state, dn);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ uint32 group_rid,
+ uint32 member_rid,
+ int modop)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ LDAPMod **mods = NULL;
+ char *filter;
+ char *uidstr;
+ const char *dn = NULL;
+ DOM_SID group_sid;
+ DOM_SID member_sid;
+ int rc;
+
+ switch (modop) {
+ case LDAP_MOD_ADD:
+ DEBUG(1,("ldapsam_change_groupmem: add new member(rid=%d) to a domain group(rid=%d)", member_rid, group_rid));
+ break;
+ case LDAP_MOD_DELETE:
+ DEBUG(1,("ldapsam_change_groupmem: delete member(rid=%d) from a domain group(rid=%d)", member_rid, group_rid));
+ break;
+ default:
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* get member sid */
+ sid_compose(&member_sid, get_global_sam_sid(), member_rid);
+
+ /* get the group sid */
+ sid_compose(&group_sid, get_global_sam_sid(), group_rid);
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(sambaSID=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ sid_string_static(&member_sid),
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+
+ /* get the member uid */
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_change_groupmem: member search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(1,("ldapsam_change_groupmem: member not found!\n"));
+ return NT_STATUS_NO_SUCH_MEMBER;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_change_groupmem: More than one account with the same SID ?!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (modop == LDAP_MOD_DELETE) {
+ /* check if we are trying to remove the member from his primary group */
+ char *gidstr;
+ gid_t user_gid, group_gid;
+
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
+ if (!gidstr) {
+ DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's gid!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ user_gid = strtoul(gidstr, NULL, 10);
+
+ if (!sid_to_gid(&group_sid, &group_gid)) {
+ DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (user_gid == group_gid) {
+ DEBUG (3, ("ldapsam_change_groupmem: can't remove user from it's own primary group!\n"));
+ return NT_STATUS_MEMBERS_PRIMARY_GROUP;
+ }
+ }
+
+ /* here it is, retrieve the uid for later use */
+ uidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "uid", tmp_ctx);
+ if (!uidstr) {
+ DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's name!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(sambaSID=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ sid_string_static(&group_sid),
+ LDAP_OBJ_POSIXGROUP,
+ LDAP_OBJ_GROUPMAP);
+
+ /* get the group */
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_change_groupmem: group search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(1,("ldapsam_change_groupmem: group not found!\n"));
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_change_groupmem: More than one group with the same SID ?!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* here it is, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_change_groupmem: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, modop, "memberUid", uidstr);
+
+ talloc_autofree_ldapmod(tmp_ctx, mods);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ if (rc != LDAP_SUCCESS) {
+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS && modop == LDAP_MOD_ADD) {
+ DEBUG(1,("ldapsam_change_groupmem: member is already in group, add failed!\n"));
+ return NT_STATUS_MEMBER_IN_GROUP;
+ }
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE && modop == LDAP_MOD_DELETE) {
+ DEBUG(1,("ldapsam_change_groupmem: member is not in group, delete failed!\n"));
+ return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ }
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_add_groupmem(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ uint32 group_rid,
+ uint32 member_rid)
+{
+ return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_ADD);
+}
+static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ uint32 group_rid,
+ uint32 member_rid)
+{
+ return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_DELETE);
+}
+
+static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
+ TALLOC_CTX *mem_ctx,
+ struct samu *sampass)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ LDAPMod **mods = NULL;
+ char *filter;
+ char *gidstr;
+ const char *dn = NULL;
+ gid_t gid;
+ int rc;
+
+ DEBUG(0,("ldapsam_set_primary_group: Attempt to set primary group for user [%s]\n", pdb_get_username(sampass)));
+
+ if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
+ DEBUG(0,("ldapsam_set_primary_group: failed to retieve gid from user's group SID!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ gidstr = talloc_asprintf(mem_ctx, "%d", gid);
+ if (!gidstr) {
+ DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(uid=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ pdb_get_username(sampass),
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_set_primary_group: user search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(0,("ldapsam_set_primary_group: user not found!\n"));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_set_primary_group: More than one user with name [%s] ?!\n", pdb_get_username(sampass)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* retrieve the dn for later use */
+ dn = smbldap_talloc_dn(mem_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_set_primary_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* remove the old one, and add the new one, this way we do not risk races */
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "gidNumber", gidstr);
+
+ if (mods == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_set_primary_group: failed to modify [%s] primary group to [%s]\n",
+ pdb_get_username(sampass), gidstr));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ flush_pwnam_cache();
+
+ return NT_STATUS_OK;
+}
+
/**********************************************************************
Housekeeping
*********************************************************************/
@@ -4256,17 +5351,17 @@ static void free_private_data(void **vp)
/* No need to free any further, as it is talloc()ed */
}
-/**********************************************************************
- Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
- *********************************************************************/
+/*********************************************************************
+ Intitalise the parts of the pdb_methods structure that are common to
+ all pdb_ldap modes
+*********************************************************************/
-static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
- const char *location)
+static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
return nt_status;
}
@@ -4289,29 +5384,29 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
(*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
(*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
(*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
- (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
- (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
- (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
(*pdb_method)->get_account_policy = ldapsam_get_account_policy;
(*pdb_method)->set_account_policy = ldapsam_set_account_policy;
(*pdb_method)->get_seq_num = ldapsam_get_seq_num;
+ (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
+ (*pdb_method)->new_rid = ldapsam_new_rid;
+
/* TODO: Setup private data and free */
- ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
- if (!ldap_state) {
+ if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
return NT_STATUS_NO_MEMORY;
}
- if (!NT_STATUS_IS_OK(nt_status =
- smbldap_init(pdb_context->mem_ctx, location,
- &ldap_state->smbldap_state)));
+ nt_status = smbldap_init(*pdb_method, location, &ldap_state->smbldap_state);
+
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
+ return nt_status;
+ }
- ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
- if (!ldap_state->domain_name) {
+ if ( !(ldap_state->domain_name = talloc_strdup(*pdb_method, get_global_sam_name()) ) ) {
return NT_STATUS_NO_MEMORY;
}
@@ -4326,13 +5421,14 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
Initialise the 'compat' mode for pdb_ldap
*********************************************************************/
-NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
+ char *uri = talloc_strdup( NULL, location );
#ifdef WITH_LDAP_SAMCONFIG
- if (!location) {
+ if (!uri) {
int ldap_port = lp_ldap_port();
/* remap default port if not using SSL (ie clear or TLS) */
@@ -4340,17 +5436,23 @@ NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
ldap_port = 389;
}
- location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
- if (!location) {
+ uri = talloc_asprintf(NULL, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
+ if (!uri) {
return NT_STATUS_NO_MEMORY;
}
+ location = uri;
}
#endif
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common( pdb_method, uri ))) {
return nt_status;
}
+ /* the module itself stores a copy of the location so throw this one away */
+
+ if ( uri )
+ TALLOC_FREE( uri );
+
(*pdb_method)->name = "ldapsam_compat";
ldap_state = (*pdb_method)->private_data;
@@ -4365,7 +5467,7 @@ NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
Initialise the normal mode for pdb_ldap
*********************************************************************/
-NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
@@ -4378,7 +5480,8 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
pstring domain_sid_string;
char *dn;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
+ nt_status = pdb_init_ldapsam_common(pdb_method, location);
+ if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
@@ -4392,27 +5495,51 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
(*pdb_method)->search_groups = ldapsam_search_groups;
(*pdb_method)->search_aliases = ldapsam_search_aliases;
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
+ (*pdb_method)->enum_group_memberships =
+ ldapsam_enum_group_memberships;
+ (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+ (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
+
+ if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
+ (*pdb_method)->create_user = ldapsam_create_user;
+ (*pdb_method)->delete_user = ldapsam_delete_user;
+ (*pdb_method)->create_dom_group = ldapsam_create_dom_group;
+ (*pdb_method)->delete_dom_group = ldapsam_delete_dom_group;
+ (*pdb_method)->add_groupmem = ldapsam_add_groupmem;
+ (*pdb_method)->del_groupmem = ldapsam_del_groupmem;
+ (*pdb_method)->set_unix_primary_group = ldapsam_set_primary_group;
+ }
+ }
+
ldap_state = (*pdb_method)->private_data;
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
/* Try to setup the Domain Name, Domain SID, algorithmic rid base */
- nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result,
+ nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
+ &result,
ldap_state->domain_name, True);
if ( !NT_STATUS_IS_OK(nt_status) ) {
- DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n"));
- DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \
-and will risk BDCs having inconsistant SIDs\n"));
+ DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
+ "info, nor add one to the domain\n"));
+ DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
+ "will be unable to allocate new users/groups, "
+ "and will risk BDCs having inconsistant SIDs\n"));
sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
return NT_STATUS_OK;
}
- /* Given that the above might fail, everything below this must be optional */
+ /* Given that the above might fail, everything below this must be
+ * optional */
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ result);
if (!entry) {
- DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n"));
+ DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
+ "entry\n"));
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -4425,35 +5552,51 @@ and will risk BDCs having inconsistant SIDs\n"));
ldap_state->domain_dn = smb_xstrdup(dn);
ldap_memfree(dn);
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
- domain_sid_string)) {
+ if (smbldap_get_single_pstring(
+ ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_USER_SID),
+ domain_sid_string)) {
BOOL found_sid;
if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
- DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be read as a valid SID\n", domain_sid_string));
+ DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
+ "read as a valid SID\n", domain_sid_string));
return NT_STATUS_INVALID_PARAMETER;
}
- found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
- if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
+ found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
+ &secrets_domain_sid);
+ if (!found_sid || !sid_equal(&secrets_domain_sid,
+ &ldap_domain_sid)) {
fstring new_sid_str, old_sid_str;
- DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain %s based on pdb_ldap results %s -> %s\n",
- ldap_state->domain_name,
- sid_to_string(old_sid_str, &secrets_domain_sid),
- sid_to_string(new_sid_str, &ldap_domain_sid)));
+ DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
+ "%s based on pdb_ldap results %s -> %s\n",
+ ldap_state->domain_name,
+ sid_to_string(old_sid_str,
+ &secrets_domain_sid),
+ sid_to_string(new_sid_str,
+ &ldap_domain_sid)));
/* reset secrets.tdb sid */
- secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
- DEBUG(1, ("New global sam SID: %s\n", sid_to_string(new_sid_str, get_global_sam_sid())));
+ secrets_store_domain_sid(ldap_state->domain_name,
+ &ldap_domain_sid);
+ DEBUG(1, ("New global sam SID: %s\n",
+ sid_to_string(new_sid_str,
+ get_global_sam_sid())));
}
sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
}
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string( dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE ),
- alg_rid_base_string)) {
+ if (smbldap_get_single_pstring(
+ ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_attr_key2string( dominfo_attr_list,
+ LDAP_ATTR_ALGORITHMIC_RID_BASE ),
+ alg_rid_base_string)) {
alg_rid_base = (uint32)atol(alg_rid_base_string);
if (alg_rid_base != algorithmic_rid_base()) {
- DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
+ DEBUG(0, ("The value of 'algorithmic RID base' has "
+ "changed since the LDAP\n"
"database was initialised. Aborting. \n"));
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
diff --git a/source/passdb/pdb_mysql.c b/source/passdb/pdb_mysql.c
deleted file mode 100644
index 27675a9cd18..00000000000
--- a/source/passdb/pdb_mysql.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * MySQL password backend for samba
- * Copyright (C) Jelmer Vernooij 2002-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 <mysql/mysql.h>
-
-#define CONFIG_HOST_DEFAULT "localhost"
-#define CONFIG_USER_DEFAULT "samba"
-#define CONFIG_PASS_DEFAULT ""
-#define CONFIG_PORT_DEFAULT "3306"
-#define CONFIG_DB_DEFAULT "samba"
-
-static int mysqlsam_debug_level = DBGC_ALL;
-
-#undef DBGC_CLASS
-#define DBGC_CLASS mysqlsam_debug_level
-
-typedef struct pdb_mysql_data {
- MYSQL *handle;
- MYSQL_RES *pwent;
- const char *location;
-} pdb_mysql_data;
-
-#define SET_DATA(data,methods) { \
- if(!methods){ \
- DEBUG(0, ("invalid methods!\n")); \
- return NT_STATUS_INVALID_PARAMETER; \
- } \
- data = (struct pdb_mysql_data *)methods->private_data; \
- if(!data || !(data->handle)){ \
- DEBUG(0, ("invalid handle!\n")); \
- return NT_STATUS_INVALID_HANDLE; \
- } \
-}
-
-#define config_value( data, name, default_value ) \
- lp_parm_const_string( GLOBAL_SECTION_SNUM, (data)->location, name, default_value )
-
-static long xatol(const char *d)
-{
- if(!d) return 0;
- return atol(d);
-}
-
-static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u)
-{
- MYSQL_ROW row;
- pstring temp;
- unsigned int num_fields;
- DOM_SID sid;
-
- num_fields = mysql_num_fields(r);
- row = mysql_fetch_row(r);
- if (!row)
- return NT_STATUS_INVALID_PARAMETER;
-
- pdb_set_logon_time(u, xatol(row[0]), PDB_SET);
- pdb_set_logoff_time(u, xatol(row[1]), PDB_SET);
- pdb_set_kickoff_time(u, xatol(row[2]), PDB_SET);
- pdb_set_pass_last_set_time(u, xatol(row[3]), PDB_SET);
- pdb_set_pass_can_change_time(u, xatol(row[4]), PDB_SET);
- pdb_set_pass_must_change_time(u, xatol(row[5]), PDB_SET);
- pdb_set_username(u, row[6], PDB_SET);
- pdb_set_domain(u, row[7], PDB_SET);
- pdb_set_nt_username(u, row[8], PDB_SET);
- pdb_set_fullname(u, row[9], PDB_SET);
- pdb_set_homedir(u, row[10], PDB_SET);
- pdb_set_dir_drive(u, row[11], PDB_SET);
- pdb_set_logon_script(u, row[12], PDB_SET);
- pdb_set_profile_path(u, row[13], PDB_SET);
- pdb_set_acct_desc(u, row[14], PDB_SET);
- pdb_set_workstations(u, row[15], PDB_SET);
- pdb_set_unknown_str(u, row[16], PDB_SET);
- pdb_set_munged_dial(u, row[17], PDB_SET);
-
- if(!row[18] || !string_to_sid(&sid, row[18])) {
- DEBUG(0,("No user SID retrieved from database!\n"));
- } else {
- pdb_set_user_sid(u, &sid, PDB_SET);
- }
-
- if(row[19]) {
- string_to_sid(&sid, row[19]);
- pdb_set_group_sid(u, &sid, PDB_SET);
- }
-
- if (pdb_gethexpwd(row[20], temp))
- pdb_set_lanman_passwd(u, temp, PDB_SET);
- if (pdb_gethexpwd(row[21], temp))
- pdb_set_nt_passwd(u, temp, PDB_SET);
-
- /* Only use plaintext password storage when lanman and nt are
- * NOT used */
- if (!row[20] || !row[21])
- pdb_set_plaintext_passwd(u, row[22]);
-
- pdb_set_acct_ctrl(u, xatol(row[23]), PDB_SET);
- pdb_set_logon_divs(u, xatol(row[24]), PDB_SET);
- pdb_set_hours_len(u, xatol(row[25]), PDB_SET);
- pdb_set_bad_password_count(u, xatol(row[26]), PDB_SET);
- pdb_set_logon_count(u, xatol(row[27]), PDB_SET);
- pdb_set_unknown_6(u, xatol(row[28]), PDB_SET);
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask)
-{
- struct pdb_mysql_data *data =
- (struct pdb_mysql_data *) methods->private_data;
- char *query;
- int ret;
-
- if (!data || !(data->handle)) {
- DEBUG(0, ("invalid handle!\n"));
- return NT_STATUS_INVALID_HANDLE;
- }
-
- query = sql_account_query_select(NULL, data->location, update, SQL_SEARCH_NONE, NULL);
-
- ret = mysql_query(data->handle, query);
- talloc_free(query);
-
- if (ret) {
- DEBUG(0,
- ("Error executing MySQL query %s\n", mysql_error(data->handle)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- data->pwent = mysql_store_result(data->handle);
-
- if (data->pwent == NULL) {
- DEBUG(0,
- ("Error storing results: %s\n", mysql_error(data->handle)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(5,
- ("mysqlsam_setsampwent succeeded(%llu results)!\n",
- mysql_num_rows(data->pwent)));
-
- return NT_STATUS_OK;
-}
-
-/***************************************************************
- End enumeration of the passwd list.
- ****************************************************************/
-
-static void mysqlsam_endsampwent(struct pdb_methods *methods)
-{
- struct pdb_mysql_data *data =
- (struct pdb_mysql_data *) methods->private_data;
-
- if (data == NULL) {
- DEBUG(0, ("invalid handle!\n"));
- return;
- }
-
- if (data->pwent != NULL)
- mysql_free_result(data->pwent);
-
- data->pwent = NULL;
-
- DEBUG(5, ("mysql_endsampwent called\n"));
-}
-
-/*****************************************************************
- Get one SAM_ACCOUNT from the list (next in line)
- *****************************************************************/
-
-static NTSTATUS mysqlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user)
-{
- struct pdb_mysql_data *data;
-
- SET_DATA(data, methods);
-
- if (data->pwent == NULL) {
- DEBUG(0, ("invalid pwent\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return row_to_sam_account(data->pwent, user);
-}
-
-static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOUNT * user,
- enum sql_search_field field, const char *sname)
-{
- char *esc_sname;
- char *query;
- NTSTATUS ret;
- MYSQL_RES *res;
- int mysql_ret;
- struct pdb_mysql_data *data;
- char *tmp_sname;
- TALLOC_CTX *mem_ctx = talloc_init("mysqlsam_select_by_field");
-
- SET_DATA(data, methods);
-
- esc_sname = talloc_array(mem_ctx, char, strlen(sname) * 2 + 1);
- if (!esc_sname) {
- talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- tmp_sname = talloc_strdup(mem_ctx, sname);
-
- /* Escape sname */
- mysql_real_escape_string(data->handle, esc_sname, tmp_sname,
- strlen(tmp_sname));
-
- talloc_free(tmp_sname);
-
- if (user == NULL) {
- DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
- talloc_free(mem_ctx);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- query = sql_account_query_select(mem_ctx, data->location, True, field, esc_sname);
-
- talloc_free(esc_sname);
-
- DEBUG(5, ("Executing query %s\n", query));
-
- mysql_ret = mysql_query(data->handle, query);
-
- talloc_free(query);
-
- if (mysql_ret) {
- DEBUG(0,
- ("Error while executing MySQL query %s\n",
- mysql_error(data->handle)));
- talloc_free(mem_ctx);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- res = mysql_store_result(data->handle);
- if (res == NULL) {
- DEBUG(0,
- ("Error storing results: %s\n", mysql_error(data->handle)));
- talloc_free(mem_ctx);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- ret = row_to_sam_account(res, user);
- mysql_free_result(res);
- talloc_free(mem_ctx);
-
- return ret;
-}
-
-/******************************************************************
- Lookup a name in the SAM database
- ******************************************************************/
-
-static NTSTATUS mysqlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user,
- const char *sname)
-{
- struct pdb_mysql_data *data;
-
- SET_DATA(data, methods);
-
- if (!sname) {
- DEBUG(0, ("invalid name specified"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- return mysqlsam_select_by_field(methods, user,
- SQL_SEARCH_USER_NAME, sname);
-}
-
-
-/***************************************************************************
- Search by sid
- **************************************************************************/
-
-static NTSTATUS mysqlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user,
- const DOM_SID * sid)
-{
- struct pdb_mysql_data *data;
- fstring sid_str;
-
- SET_DATA(data, methods);
-
- sid_to_string(sid_str, sid);
-
- return mysqlsam_select_by_field(methods, user, SQL_SEARCH_USER_SID, sid_str);
-}
-
-/***************************************************************************
- Delete a SAM_ACCOUNT
- ****************************************************************************/
-
-static NTSTATUS mysqlsam_delete_sam_account(struct pdb_methods *methods,
- SAM_ACCOUNT * sam_pass)
-{
- const char *sname = pdb_get_username(sam_pass);
- char *esc;
- char *query;
- int ret;
- struct pdb_mysql_data *data;
- char *tmp_sname;
- TALLOC_CTX *mem_ctx;
- SET_DATA(data, methods);
-
- if (!methods) {
- DEBUG(0, ("invalid methods!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- data = (struct pdb_mysql_data *) methods->private_data;
- if (!data || !(data->handle)) {
- DEBUG(0, ("invalid handle!\n"));
- return NT_STATUS_INVALID_HANDLE;
- }
-
- if (!sname) {
- DEBUG(0, ("invalid name specified\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- mem_ctx = talloc_init("mysqlsam_delete_sam_account");
-
- /* Escape sname */
- esc = talloc_array(mem_ctx, char, strlen(sname) * 2 + 1);
- if (!esc) {
- DEBUG(0, ("Can't allocate memory to store escaped name\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- tmp_sname = talloc_strdup(mem_ctx, sname);
-
- mysql_real_escape_string(data->handle, esc, tmp_sname,
- strlen(tmp_sname));
-
- talloc_free(tmp_sname);
-
- query = sql_account_query_delete(mem_ctx, data->location, esc);
-
- talloc_free(esc);
-
- ret = mysql_query(data->handle, query);
-
- talloc_free(query);
-
- if (ret) {
- DEBUG(0,
- ("Error while executing query: %s\n",
- mysql_error(data->handle)));
- talloc_free(mem_ctx);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(5, ("User '%s' deleted\n", sname));
- talloc_free(mem_ctx);
- return NT_STATUS_OK;
-}
-
-static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods,
- const SAM_ACCOUNT * newpwd, char isupdate)
-{
- struct pdb_mysql_data *data;
- char *query;
-
- if (!methods) {
- DEBUG(0, ("invalid methods!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- data = (struct pdb_mysql_data *) methods->private_data;
-
- if (data == NULL || data->handle == NULL) {
- DEBUG(0, ("invalid handle!\n"));
- return NT_STATUS_INVALID_HANDLE;
- }
-
- query = sql_account_query_update(NULL, data->location, newpwd, isupdate);
- if ( query == NULL ) /* Nothing to update. */
- return NT_STATUS_OK;
-
- /* Execute the query */
- if (mysql_query(data->handle, query)) {
- DEBUG(0,
- ("Error executing %s, %s\n", query,
- mysql_error(data->handle)));
- talloc_free(query);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- talloc_free(query);
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS mysqlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * newpwd)
-{
- return mysqlsam_replace_sam_account(methods, newpwd, 0);
-}
-
-static NTSTATUS mysqlsam_update_sam_account(struct pdb_methods *methods,
- SAM_ACCOUNT * newpwd)
-{
- return mysqlsam_replace_sam_account(methods, newpwd, 1);
-}
-
-static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method,
- const char *location)
-{
- NTSTATUS nt_status;
- struct pdb_mysql_data *data;
-
- mysqlsam_debug_level = debug_add_class("mysqlsam");
- if (mysqlsam_debug_level == -1) {
- mysqlsam_debug_level = DBGC_ALL;
- DEBUG(0,
- ("mysqlsam: Couldn't register custom debugging class!\n"));
- }
-
-
- if (!pdb_context) {
- DEBUG(0, ("invalid pdb_methods specified\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!NT_STATUS_IS_OK
- (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
- return nt_status;
- }
-
- (*pdb_method)->name = "mysqlsam";
-
- (*pdb_method)->setsampwent = mysqlsam_setsampwent;
- (*pdb_method)->endsampwent = mysqlsam_endsampwent;
- (*pdb_method)->getsampwent = mysqlsam_getsampwent;
- (*pdb_method)->getsampwnam = mysqlsam_getsampwnam;
- (*pdb_method)->getsampwsid = mysqlsam_getsampwsid;
- (*pdb_method)->add_sam_account = mysqlsam_add_sam_account;
- (*pdb_method)->update_sam_account = mysqlsam_update_sam_account;
- (*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account;
-
- data = talloc(pdb_context->mem_ctx, struct pdb_mysql_data);
- (*pdb_method)->private_data = data;
- data->handle = NULL;
- data->pwent = NULL;
-
- if (!location) {
- DEBUG(0, ("No identifier specified. Check the Samba HOWTO Collection for details\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- data->location = smb_xstrdup(location);
-
- DEBUG(1,
- ("Connecting to database server, host: %s, user: %s, database: %s, port: %ld\n",
- config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
- config_value(data, "mysql user", CONFIG_USER_DEFAULT),
- config_value(data, "mysql database", CONFIG_DB_DEFAULT),
- xatol(config_value(data, "mysql port", CONFIG_PORT_DEFAULT))));
-
- /* Do the mysql initialization */
- data->handle = mysql_init(NULL);
- if (!data->handle) {
- DEBUG(0, ("Failed to connect to server\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if(!sql_account_config_valid(data->location)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* Process correct entry in $HOME/.my.conf */
- if (!mysql_real_connect(data->handle,
- config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
- config_value(data, "mysql user", CONFIG_USER_DEFAULT),
- config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
- config_value(data, "mysql database", CONFIG_DB_DEFAULT),
- xatol(config_value (data, "mysql port", CONFIG_PORT_DEFAULT)),
- NULL, 0)) {
- DEBUG(0,
- ("Failed to connect to mysql database: error: %s\n",
- mysql_error(data->handle)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(5, ("Connected to mysql db\n"));
-
- return NT_STATUS_OK;
-}
-
-NTSTATUS pdb_mysql_init(void)
-{
- return smb_register_passdb(PASSDB_INTERFACE_VERSION, "mysql", mysqlsam_init);
-}
diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c
index cf2d1d7c8a8..a82f4e48d4e 100644
--- a/source/passdb/pdb_nds.c
+++ b/source/passdb/pdb_nds.c
@@ -741,7 +741,7 @@ int pdb_nds_set_password(
*********************************************************************/
static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
- SAM_ACCOUNT *sam_acct, BOOL success)
+ struct samu *sam_acct, BOOL success)
{
struct ldapsam_privates *ldap_state;
@@ -771,13 +771,16 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
result = pdb_get_backend_private_data(sam_acct, methods);
if (!result) {
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL,
+ ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name(ldap_state, username, &result, attr_list );
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- pdb_set_backend_private_data(sam_acct, result, private_data_free_fn, methods, PDB_CHANGED);
+ pdb_set_backend_private_data(sam_acct, result, NULL,
+ methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(sam_acct, result);
}
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
@@ -816,7 +819,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
rc = ldap_simple_bind_s(ld, dn, clear_text_pw);
if (rc == LDAP_SUCCESS) {
DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Successful for %s\n", username));
- ldap_unbind_ext(ld, NULL, NULL);
+ ldap_unbind(ld);
} else {
NTSTATUS nt_status = NT_STATUS_ACCOUNT_RESTRICTION;
DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Failed for %s\n", username));
@@ -845,10 +848,11 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
}
/**********************************************************************
- Intitalise the parts of the pdb_context that are common to NDS_ldapsam modes
+ Intitalise the parts of the pdb_methods structuire that are common
+ to NDS_ldapsam modes
*********************************************************************/
-static NTSTATUS pdb_init_NDS_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
{
struct ldapsam_privates *ldap_state = (*pdb_method)->private_data;
@@ -869,13 +873,13 @@ static NTSTATUS pdb_init_NDS_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHOD
Initialise the 'nds compat' mode for pdb_ldap
*********************************************************************/
-static NTSTATUS pdb_init_NDS_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS pdb_init_NDS_ldapsam_compat(struct pdb_methods **pdb_method, const char *location)
{
- NTSTATUS nt_status = pdb_init_ldapsam_compat(pdb_context, pdb_method, location);
+ NTSTATUS nt_status = pdb_init_ldapsam_compat(pdb_method, location);
(*pdb_method)->name = "NDS_ldapsam_compat";
- pdb_init_NDS_ldapsam_common(pdb_context, pdb_method, location);
+ pdb_init_NDS_ldapsam_common(pdb_method, location);
return nt_status;
}
@@ -885,13 +889,13 @@ static NTSTATUS pdb_init_NDS_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHOD
Initialise the 'nds' normal mode for pdb_ldap
*********************************************************************/
-static NTSTATUS pdb_init_NDS_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS pdb_init_NDS_ldapsam(struct pdb_methods **pdb_method, const char *location)
{
- NTSTATUS nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location);
+ NTSTATUS nt_status = pdb_init_ldapsam(pdb_method, location);
(*pdb_method)->name = "NDS_ldapsam";
- pdb_init_NDS_ldapsam_common(pdb_context, pdb_method, location);
+ pdb_init_NDS_ldapsam_common(pdb_method, location);
return nt_status;
}
diff --git a/source/passdb/pdb_pgsql.c b/source/passdb/pdb_pgsql.c
deleted file mode 100644
index 196fe8f855d..00000000000
--- a/source/passdb/pdb_pgsql.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * PostgresSQL password backend for samba
- * Copyright (C) Hamish Friedlander 2003
- * Copyright (C) Jelmer Vernooij 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 <libpq-fe.h>
-
-#define CONFIG_HOST_DEFAULT "localhost"
-#define CONFIG_USER_DEFAULT "samba"
-#define CONFIG_PASS_DEFAULT ""
-#define CONFIG_PORT_DEFAULT "5432"
-#define CONFIG_DB_DEFAULT "samba"
-
-/* handles for doing db transactions */
-typedef struct pdb_pgsql_data {
- PGconn *master_handle ;
- PGconn *handle ;
-
- PGresult *pwent ;
- long currow ;
- const char *db ;
- const char *host ;
- const char *port ;
- const char *user ;
- const char *pass ;
-
- const char *location ;
-} pdb_pgsql_data ;
-
-struct pdb_context *the_pdb_context;
-
-#define SET_DATA(data,methods) { \
- if(!methods){ \
- DEBUG(0, ("invalid methods!\n")); \
- return NT_STATUS_INVALID_PARAMETER; \
- } \
- data = (struct pdb_pgsql_data *)methods->private_data; \
-}
-
-
-#define SET_DATA_QUIET(data,methods) { \
- if(!methods){ \
- DEBUG(0, ("invalid methods!\n")); \
- return ; \
- } \
- data = (struct pdb_pgsql_data *)methods->private_data; \
-}
-
-
-#define config_value( data, name, default_value ) \
- lp_parm_const_string( GLOBAL_SECTION_SNUM, (data)->location, name, default_value )
-
-static PGconn *pgsqlsam_connect( struct pdb_pgsql_data *data )
-{
- PGconn *handle;
-
- DEBUG
- (
- 1,
- (
- "Connecting to database server, host: %s, user: %s, password: XXXXXX, database: %s, port: %s\n",
- data->host, data->user, data->db, data->port
- )
- ) ;
-
- /* Do the pgsql initialization */
- handle = PQsetdbLogin(
- data->host,
- data->port,
- NULL,
- NULL,
- data->db,
- data->user,
- data->pass
- ) ;
-
- if ( handle != NULL && PQstatus( handle ) != CONNECTION_OK )
- {
- DEBUG( 0, ("Failed to connect to pgsql database: error: %s\n",
- (handle != NULL ? PQerrorMessage( handle ) : "")) ) ;
- return NULL;
- }
-
- DEBUG( 5, ("Connected to pgsql database\n") ) ;
- return handle;
-}
-
-/* The assumption here is that the master process will get connection 0,
- * and all the renaining ones just one connection for their etire life span.
- */
-static PGconn *choose_connection( struct pdb_pgsql_data *data )
-{
- if ( data->master_handle == NULL )
- {
- data->master_handle = pgsqlsam_connect( data );
- return data->master_handle ;
- }
-
- /* Master connection != NULL, so we are just another process. */
-
- /* If we didn't connect yet, do it now. */
- if ( data->handle == NULL )
- {
- data->handle = pgsqlsam_connect( data );
- }
-
- return data->handle ;
-}
-
-static long PQgetlong( PGresult *r, long row, long col )
-{
- if ( PQgetisnull( r, row, col ) ) return 0 ;
-
- return atol( PQgetvalue( r, row, col ) ) ;
-}
-
-static NTSTATUS row_to_sam_account ( PGresult *r, long row, SAM_ACCOUNT *u )
-{
- pstring temp ;
- DOM_SID sid ;
- unsigned char *hours ;
- size_t hours_len = 0 ;
-
- if ( row >= PQntuples( r ) ) return NT_STATUS_INVALID_PARAMETER ;
-
- pdb_set_logon_time ( u, PQgetlong ( r, row, 0 ), PDB_SET ) ;
- pdb_set_logoff_time ( u, PQgetlong ( r, row, 1 ), PDB_SET ) ;
- pdb_set_kickoff_time ( u, PQgetlong ( r, row, 2 ), PDB_SET ) ;
- pdb_set_pass_last_set_time ( u, PQgetlong ( r, row, 3 ), PDB_SET ) ;
- pdb_set_pass_can_change_time ( u, PQgetlong ( r, row, 4 ), PDB_SET ) ;
- pdb_set_pass_must_change_time( u, PQgetlong ( r, row, 5 ), PDB_SET ) ;
- pdb_set_username ( u, PQgetvalue( r, row, 6 ), PDB_SET ) ;
- pdb_set_domain ( u, PQgetvalue( r, row, 7 ), PDB_SET ) ;
- pdb_set_nt_username ( u, PQgetvalue( r, row, 8 ), PDB_SET ) ;
- pdb_set_fullname ( u, PQgetvalue( r, row, 9 ), PDB_SET ) ;
- pdb_set_homedir ( u, PQgetvalue( r, row, 10 ), PDB_SET ) ;
- pdb_set_dir_drive ( u, PQgetvalue( r, row, 11 ), PDB_SET ) ;
- pdb_set_logon_script ( u, PQgetvalue( r, row, 12 ), PDB_SET ) ;
- pdb_set_profile_path ( u, PQgetvalue( r, row, 13 ), PDB_SET ) ;
- pdb_set_acct_desc ( u, PQgetvalue( r, row, 14 ), PDB_SET ) ;
- pdb_set_workstations ( u, PQgetvalue( r, row, 15 ), PDB_SET ) ;
- pdb_set_unknown_str ( u, PQgetvalue( r, row, 16 ), PDB_SET ) ;
- pdb_set_munged_dial ( u, PQgetvalue( r, row, 17 ), PDB_SET ) ;
-
- pdb_set_acct_ctrl ( u, PQgetlong ( r, row, 23 ), PDB_SET ) ;
- pdb_set_logon_divs ( u, PQgetlong ( r, row, 24 ), PDB_SET ) ;
- pdb_set_hours_len ( u, PQgetlong ( r, row, 25 ), PDB_SET ) ;
- pdb_set_bad_password_count ( u, PQgetlong ( r, row, 26 ), PDB_SET ) ;
- pdb_set_logon_count ( u, PQgetlong ( r, row, 27 ), PDB_SET ) ;
- pdb_set_unknown_6 ( u, PQgetlong ( r, row, 28 ), PDB_SET ) ;
- hours = PQgetvalue ( r, row, 29 );
- if ( hours != NULL ) {
- hours = PQunescapeBytea ( hours, &hours_len ) ;
- if ( hours_len > 0 )
- pdb_set_hours ( u, hours, PDB_SET ) ;
- free ( hours );
- }
-
- if ( !PQgetisnull( r, row, 18 ) ) {
- string_to_sid( &sid, PQgetvalue( r, row, 18 ) ) ;
- pdb_set_user_sid ( u, &sid, PDB_SET ) ;
- }
-
- if ( !PQgetisnull( r, row, 19 ) ) {
- string_to_sid( &sid, PQgetvalue( r, row, 19 ) ) ;
- pdb_set_group_sid( u, &sid, PDB_SET ) ;
- }
-
- if ( pdb_gethexpwd( PQgetvalue( r, row, 20 ), temp ), PDB_SET ) pdb_set_lanman_passwd( u, temp, PDB_SET ) ;
- if ( pdb_gethexpwd( PQgetvalue( r, row, 21 ), temp ), PDB_SET ) pdb_set_nt_passwd ( u, temp, PDB_SET ) ;
-
- /* Only use plaintext password storage when lanman and nt are NOT used */
- if ( PQgetisnull( r, row, 20 ) || PQgetisnull( r, row, 21 ) ) pdb_set_plaintext_passwd( u, PQgetvalue( r, row, 22 ) ) ;
-
- return NT_STATUS_OK ;
-}
-
-static NTSTATUS pgsqlsam_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask)
-{
- struct pdb_pgsql_data *data ;
- PGconn *handle ;
- char *query ;
- NTSTATUS retval ;
-
- SET_DATA( data, methods ) ;
-
- /* Connect to the DB. */
- handle = choose_connection( data );
- if ( handle == NULL )
- return NT_STATUS_UNSUCCESSFUL ;
- DEBUG( 5, ("CONNECTING pgsqlsam_setsampwent\n") ) ;
-
- query = sql_account_query_select(NULL, data->location, update, SQL_SEARCH_NONE, NULL);
-
- /* Do it */
- DEBUG( 5, ("Executing query %s\n", query) ) ;
- data->pwent = PQexec( handle, query ) ;
- data->currow = 0 ;
-
- /* Result? */
- if ( data->pwent == NULL )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ;
- retval = NT_STATUS_UNSUCCESSFUL ;
- }
- else if ( PQresultStatus( data->pwent ) != PGRES_TUPLES_OK )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQresultErrorMessage( data->pwent ) ) ) ;
- retval = NT_STATUS_UNSUCCESSFUL ;
- }
- else
- {
- DEBUG( 5, ("pgsqlsam_setsampwent succeeded(%d results)!\n", PQntuples(data->pwent)) ) ;
- retval = NT_STATUS_OK ;
- }
-
- talloc_free(query);
- return retval ;
-}
-
-/***************************************************************
- End enumeration of the passwd list.
- ****************************************************************/
-
-static void pgsqlsam_endsampwent(struct pdb_methods *methods)
-{
- struct pdb_pgsql_data *data ;
-
- SET_DATA_QUIET( data, methods ) ;
-
- if (data->pwent != NULL)
- {
- PQclear( data->pwent ) ;
- }
-
- data->pwent = NULL ;
- data->currow = 0 ;
-
- DEBUG( 5, ("pgsql_endsampwent called\n") ) ;
-}
-
-/*****************************************************************
- Get one SAM_ACCOUNT from the list (next in line)
- *****************************************************************/
-
-static NTSTATUS pgsqlsam_getsampwent( struct pdb_methods *methods, SAM_ACCOUNT *user )
-{
- struct pdb_pgsql_data *data;
- NTSTATUS retval ;
-
- SET_DATA( data, methods ) ;
-
- if ( data->pwent == NULL )
- {
- DEBUG( 0, ("invalid pwent\n") ) ;
- return NT_STATUS_INVALID_PARAMETER ;
- }
-
- retval = row_to_sam_account( data->pwent, data->currow, user ) ;
- data->currow++ ;
-
- return retval ;
-}
-
-static NTSTATUS pgsqlsam_select_by_field ( struct pdb_methods *methods, SAM_ACCOUNT *user, enum sql_search_field field, const char *sname )
-{
- struct pdb_pgsql_data *data ;
- PGconn *handle ;
-
- char *esc ;
- char *query ;
-
- PGresult *result ;
- NTSTATUS retval ;
-
- SET_DATA(data, methods);
-
- if ( user == NULL )
- {
- DEBUG( 0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n") ) ;
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- DEBUG( 5, ("pgsqlsam_select_by_field: getting data where %d = %s(nonescaped)\n", field, sname) ) ;
-
- /* Escape sname */
- esc = talloc_array(NULL, char, strlen(sname) * 2 + 1);
- if ( !esc )
- {
- DEBUG(0, ("Can't allocate memory to store escaped name\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- //tmp_sname = smb_xstrdup(sname);
- PQescapeString( esc, sname, strlen(sname) ) ;
-
- /* Connect to the DB. */
- handle = choose_connection( data );
- if ( handle == NULL )
- return NT_STATUS_UNSUCCESSFUL ;
-
- query = sql_account_query_select(NULL, data->location, True, field, esc);
-
- /* Do it */
- DEBUG( 5, ("Executing query %s\n", query) ) ;
- result = PQexec( handle, query ) ;
-
- /* Result? */
- if ( result == NULL )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ;
- retval = NT_STATUS_UNSUCCESSFUL ;
- }
- else if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQresultErrorMessage( result ) ) ) ;
- retval = NT_STATUS_UNSUCCESSFUL ;
- }
- else
- {
- retval = row_to_sam_account( result, 0, user ) ;
- }
-
- talloc_free( esc ) ;
- talloc_free( query ) ;
-
- if ( result != NULL )
- PQclear( result ) ;
-
- return retval ;
-}
-
-/******************************************************************
- Lookup a name in the SAM database
- ******************************************************************/
-
-static NTSTATUS pgsqlsam_getsampwnam ( struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname )
-{
- struct pdb_pgsql_data *data;
- size_t i, l;
- char *lowercasename;
- NTSTATUS result;
-
- SET_DATA(data, methods);
-
- if ( !sname )
- {
- DEBUG( 0, ("invalid name specified") ) ;
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- lowercasename = smb_xstrdup(sname);
- l = strlen(lowercasename);
- for(i = 0; i < l; i++) {
- lowercasename[i] = tolower_ascii(lowercasename[i]);
- }
-
- result = pgsqlsam_select_by_field( methods, user, SQL_SEARCH_USER_NAME, lowercasename ) ;
-
- SAFE_FREE( lowercasename ) ;
-
- return result;
-}
-
-
-/***************************************************************************
- Search by sid
- **************************************************************************/
-
-static NTSTATUS pgsqlsam_getsampwsid ( struct pdb_methods *methods, SAM_ACCOUNT *user, const DOM_SID *sid )
-{
- struct pdb_pgsql_data *data;
- fstring sid_str;
-
- SET_DATA( data, methods ) ;
-
- sid_to_string( sid_str, sid ) ;
-
- return pgsqlsam_select_by_field( methods, user, SQL_SEARCH_USER_SID, sid_str ) ;
-}
-
-/***************************************************************************
- Delete a SAM_ACCOUNT
- ****************************************************************************/
-
-static NTSTATUS pgsqlsam_delete_sam_account( struct pdb_methods *methods, SAM_ACCOUNT *sam_pass )
-{
- struct pdb_pgsql_data *data ;
- PGconn *handle ;
-
- const char *sname = pdb_get_username( sam_pass ) ;
- char *esc ;
- char *query ;
-
- PGresult *result ;
- NTSTATUS retval ;
-
- SET_DATA(data, methods);
-
- if ( !sname )
- {
- DEBUG( 0, ("invalid name specified\n") ) ;
- return NT_STATUS_INVALID_PARAMETER ;
- }
-
- /* Escape sname */
- esc = talloc_array(NULL, char, strlen(sname) * 2 + 1);
- if ( !esc )
- {
- DEBUG(0, ("Can't allocate memory to store escaped name\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- PQescapeString( esc, sname, strlen(sname) ) ;
-
- /* Connect to the DB. */
- handle = choose_connection( data );
- if ( handle == NULL )
- return NT_STATUS_UNSUCCESSFUL ;
-
- query = sql_account_query_delete(NULL, data->location, esc);
-
- /* Do it */
- result = PQexec( handle, query ) ;
-
- if ( result == NULL )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ;
- retval = NT_STATUS_UNSUCCESSFUL ;
- }
- else if ( PQresultStatus( result ) != PGRES_COMMAND_OK )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQresultErrorMessage( result ) ) ) ;
- retval = NT_STATUS_UNSUCCESSFUL ;
- }
- else
- {
- DEBUG( 5, ("User '%s' deleted\n", sname) ) ;
- retval = NT_STATUS_OK ;
- }
-
- if ( result != NULL )
- PQclear( result ) ;
- talloc_free( esc ) ;
- talloc_free( query ) ;
-
- return retval ;
-}
-
-static NTSTATUS pgsqlsam_replace_sam_account( struct pdb_methods *methods, const SAM_ACCOUNT *newpwd, char isupdate )
-{
- struct pdb_pgsql_data *data ;
- PGconn *handle ;
- char *query;
- PGresult *result ;
- NTSTATUS retval ;
-
- if ( !methods )
- {
- DEBUG( 0, ("invalid methods!\n") ) ;
- return NT_STATUS_INVALID_PARAMETER ;
- }
-
- data = (struct pdb_pgsql_data *) methods->private_data ;
-
- if ( data == NULL || handle == NULL )
- {
- DEBUG( 0, ("invalid handle!\n") ) ;
- return NT_STATUS_INVALID_HANDLE ;
- }
-
- query = sql_account_query_update(NULL, data->location, newpwd, isupdate);
- if ( query == NULL ) /* Nothing to update. */
- return NT_STATUS_OK;
-
- /* Connect to the DB. */
- handle = choose_connection( data );
- if ( handle == NULL )
- return NT_STATUS_UNSUCCESSFUL ;
-
- result = PQexec( handle, query ) ;
-
- /* Execute the query */
- if ( result == NULL )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ;
- retval = NT_STATUS_INVALID_PARAMETER;
- }
- else if ( PQresultStatus( result ) != PGRES_COMMAND_OK )
- {
- DEBUG( 0, ("Error executing %s, %s\n", query, PQresultErrorMessage( result ) ) ) ;
- retval = NT_STATUS_INVALID_PARAMETER;
- }
- else
- {
- retval = NT_STATUS_OK;
- }
- if ( result != NULL )
- PQclear( result ) ;
- talloc_free(query);
-
- return retval;
-}
-
-static NTSTATUS pgsqlsam_add_sam_account ( struct pdb_methods *methods, SAM_ACCOUNT *newpwd )
-{
- return pgsqlsam_replace_sam_account( methods, newpwd, 0 ) ;
-}
-
-static NTSTATUS pgsqlsam_update_sam_account ( struct pdb_methods *methods, SAM_ACCOUNT *newpwd )
-{
- return pgsqlsam_replace_sam_account( methods, newpwd, 1 ) ;
-}
-
-static NTSTATUS pgsqlsam_init ( struct pdb_context *pdb_context, struct pdb_methods **pdb_method, const char *location )
-{
- NTSTATUS nt_status ;
- struct pdb_pgsql_data *data ;
-
- if ( !pdb_context )
- {
- DEBUG( 0, ("invalid pdb_methods specified\n") ) ;
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- the_pdb_context = pdb_context;
-
- if (!NT_STATUS_IS_OK
- (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
- return nt_status;
- }
-
- (*pdb_method)->name = "pgsqlsam" ;
-
- (*pdb_method)->setsampwent = pgsqlsam_setsampwent ;
- (*pdb_method)->endsampwent = pgsqlsam_endsampwent ;
- (*pdb_method)->getsampwent = pgsqlsam_getsampwent ;
- (*pdb_method)->getsampwnam = pgsqlsam_getsampwnam ;
- (*pdb_method)->getsampwsid = pgsqlsam_getsampwsid ;
- (*pdb_method)->add_sam_account = pgsqlsam_add_sam_account ;
- (*pdb_method)->update_sam_account = pgsqlsam_update_sam_account ;
- (*pdb_method)->delete_sam_account = pgsqlsam_delete_sam_account ;
-
- data = talloc( pdb_context->mem_ctx, struct pdb_pgsql_data ) ;
- (*pdb_method)->private_data = data ;
-
- data->master_handle = NULL;
- data->handle = NULL;
- data->pwent = NULL ;
-
- if ( !location )
- {
- DEBUG( 0, ("No identifier specified. Check the Samba HOWTO Collection for details\n") ) ;
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- data->location = smb_xstrdup( location ) ;
-
- if(!sql_account_config_valid(data->location)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- DEBUG
- (
- 1,
- (
- "Database server parameters: host: %s, user: %s, password: XXXX, database: %s, port: %s\n",
- config_value( data, "pgsql host" , CONFIG_HOST_DEFAULT ),
- config_value( data, "pgsql user" , CONFIG_USER_DEFAULT ),
- config_value( data, "pgsql database", CONFIG_DB_DEFAULT ),
- config_value( data, "pgsql port" , CONFIG_PORT_DEFAULT )
- )
- ) ;
-
- /* Save the parameters. */
- data->db = config_value( data, "pgsql database", CONFIG_DB_DEFAULT );
- data->host = config_value( data, "pgsql host" , CONFIG_HOST_DEFAULT );
- data->port = config_value( data, "pgsql port" , CONFIG_PORT_DEFAULT );
- data->user = config_value( data, "pgsql user" , CONFIG_USER_DEFAULT );
- data->pass = config_value( data, "pgsql password", CONFIG_PASS_DEFAULT );
-
- DEBUG( 5, ("Pgsql module intialized\n") ) ;
- return NT_STATUS_OK;
-}
-
-NTSTATUS pdb_pgsql_init(void)
-{
- return smb_register_passdb( PASSDB_INTERFACE_VERSION, "pgsql", pgsqlsam_init ) ;
-}
diff --git a/source/passdb/pdb_plugin.c b/source/passdb/pdb_plugin.c
index 027cd0b5d33..9d835a48ad3 100644
--- a/source/passdb/pdb_plugin.c
+++ b/source/passdb/pdb_plugin.c
@@ -24,7 +24,7 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
-NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_plugin(struct pdb_methods **pdb_method, const char *location)
{
void * dl_handle;
char *plugin_location, *plugin_name, *p;
@@ -76,5 +76,5 @@ NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con
}
DEBUG(5, ("Starting sam plugin %s with location %s\n", plugin_name, plugin_location));
- return plugin_init(pdb_context, pdb_method, plugin_location);
+ return plugin_init(pdb_method, plugin_location);
}
diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c
index 487df96e953..b976595008a 100644
--- a/source/passdb/pdb_smbpasswd.c
+++ b/source/passdb/pdb_smbpasswd.c
@@ -594,7 +594,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
size_t new_entry_length;
char *new_entry;
SMB_OFF_T offpos;
- uint32 max_found_uid = 0;
/* Open the smbpassword file - for update. */
fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth);
@@ -619,11 +618,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
return False;
}
-
- /* Look for a free uid for use in non-unix accounts */
- if (pwd->smb_userid > max_found_uid) {
- max_found_uid = pwd->smb_userid;
- }
}
/* Ok - entry doesn't exist. We can add it */
@@ -1143,12 +1137,12 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
}
/*********************************************************************
- Create a smb_passwd struct from a SAM_ACCOUNT.
+ Create a smb_passwd struct from a struct samu.
We will not allocate any new memory. The smb_passwd struct
- should only stay around as long as the SAM_ACCOUNT does.
+ should only stay around as long as the struct samu does.
********************************************************************/
-static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass)
+static BOOL build_smb_pass (struct smb_passwd *smb_pw, const struct samu *sampass)
{
uint32 rid;
@@ -1161,14 +1155,13 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
/* If the user specified a RID, make sure its able to be both stored and retreived */
if (rid == DOMAIN_USER_RID_GUEST) {
- struct passwd *passwd = getpwnam_alloc(lp_guestaccount());
+ struct passwd *passwd = getpwnam_alloc(NULL, lp_guestaccount());
if (!passwd) {
DEBUG(0, ("Could not find gest account via getpwnam()! (%s)\n", lp_guestaccount()));
return False;
}
smb_pw->smb_userid=passwd->pw_uid;
- passwd_free(&passwd);
-
+ TALLOC_FREE(passwd);
} else if (algorithmic_pdb_rid_is_user(rid)) {
smb_pw->smb_userid=algorithmic_pdb_user_rid_to_uid(rid);
} else {
@@ -1189,31 +1182,31 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
}
/*********************************************************************
- Create a SAM_ACCOUNT from a smb_passwd struct
+ Create a struct samu from a smb_passwd struct
********************************************************************/
static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
- SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf)
+ struct samu *sam_pass, const struct smb_passwd *pw_buf)
{
struct passwd *pwfile;
- if (sam_pass==NULL) {
- DEBUG(5,("build_sam_account: SAM_ACCOUNT is NULL\n"));
+ if ( !sam_pass ) {
+ DEBUG(5,("build_sam_account: struct samu is NULL\n"));
return False;
}
/* verify the user account exists */
- if ( !(pwfile = getpwnam_alloc(pw_buf->smb_name)) ) {
+ if ( !(pwfile = getpwnam_alloc(NULL, pw_buf->smb_name)) ) {
DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid "
"%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
return False;
}
- if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile)))
+ if ( !NT_STATUS_IS_OK( samu_set_unix(sam_pass, pwfile )) )
return False;
- passwd_free(&pwfile);
+ TALLOC_FREE(pwfile);
/* set remaining fields */
@@ -1230,7 +1223,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
Functions to be implemented by the new passdb API
****************************************************************/
-static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
+static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
{
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
@@ -1270,19 +1263,17 @@ static void smbpasswd_endsampwent (struct pdb_methods *my_methods)
/*****************************************************************
****************************************************************/
-static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
+static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, struct samu *user)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
struct smb_passwd *pw_buf=NULL;
BOOL done = False;
+
DEBUG(5,("pdb_getsampwent\n"));
- if (user==NULL) {
+ if ( !user ) {
DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));
-#if 0
- smb_panic("NULL pointer passed to getsampwent (smbpasswd)\n");
-#endif
return nt_status;
}
@@ -1292,7 +1283,7 @@ static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUN
if (pw_buf == NULL)
return nt_status;
- /* build the SAM_ACCOUNT entry from the smb_passwd struct.
+ /* build the struct samu entry from the smb_passwd struct.
We loop in case the user in the pdb does not exist in
the local system password file */
if (build_sam_account(smbpasswd_state, user, pw_buf))
@@ -1312,7 +1303,7 @@ static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUN
***************************************************************/
static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
- SAM_ACCOUNT *sam_acct, const char *username)
+ struct samu *sam_acct, const char *username)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
@@ -1344,14 +1335,11 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name));
if (!sam_acct) {
- DEBUG(10,("getsampwnam (smbpasswd): SAM_ACCOUNT is NULL\n"));
-#if 0
- smb_panic("NULL pointer passed to pdb_getsampwnam\n");
-#endif
+ DEBUG(10,("getsampwnam (smbpasswd): struct samu is NULL\n"));
return nt_status;
}
- /* now build the SAM_ACCOUNT */
+ /* now build the struct samu */
if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw))
return nt_status;
@@ -1359,7 +1347,7 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
return NT_STATUS_OK;
}
-static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
+static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, struct samu *sam_acct, const DOM_SID *sid)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
@@ -1404,14 +1392,11 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUN
DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name));
if (!sam_acct) {
- DEBUG(10,("getsampwrid: (smbpasswd) SAM_ACCOUNT is NULL\n"));
-#if 0
- smb_panic("NULL pointer passed to pdb_getsampwrid\n");
-#endif
+ DEBUG(10,("getsampwrid: (smbpasswd) struct samu is NULL\n"));
return nt_status;
}
- /* now build the SAM_ACCOUNT */
+ /* now build the struct samu */
if (!build_sam_account (smbpasswd_state, sam_acct, smb_pw))
return nt_status;
@@ -1427,12 +1412,12 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUN
return NT_STATUS_OK;
}
-static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sampass)
+static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, struct samu *sampass)
{
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
struct smb_passwd smb_pw;
- /* convert the SAM_ACCOUNT */
+ /* convert the struct samu */
if (!build_smb_pass(&smb_pw, sampass)) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -1445,12 +1430,12 @@ static NTSTATUS smbpasswd_add_sam_account(struct pdb_methods *my_methods, SAM_AC
return NT_STATUS_OK;
}
-static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sampass)
+static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, struct samu *sampass)
{
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
struct smb_passwd smb_pw;
- /* convert the SAM_ACCOUNT */
+ /* convert the struct samu */
if (!build_smb_pass(&smb_pw, sampass)) {
DEBUG(0, ("smbpasswd_update_sam_account: build_smb_pass failed!\n"));
return NT_STATUS_UNSUCCESSFUL;
@@ -1465,7 +1450,7 @@ static NTSTATUS smbpasswd_update_sam_account(struct pdb_methods *my_methods, SAM
return NT_STATUS_OK;
}
-static NTSTATUS smbpasswd_delete_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *sampass)
+static NTSTATUS smbpasswd_delete_sam_account (struct pdb_methods *my_methods, struct samu *sampass)
{
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
@@ -1478,21 +1463,27 @@ static NTSTATUS smbpasswd_delete_sam_account (struct pdb_methods *my_methods, SA
}
static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods,
- SAM_ACCOUNT *old_acct,
+ struct samu *old_acct,
const char *newname)
{
pstring rename_script;
- SAM_ACCOUNT *new_acct = NULL;
+ struct samu *new_acct = NULL;
BOOL interim_account = False;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
if (!*(lp_renameuser_script()))
goto done;
- if (!pdb_copy_sam_account(old_acct, &new_acct) ||
- !pdb_set_username(new_acct, newname, PDB_CHANGED))
+ if ( !(new_acct = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( !pdb_copy_sam_account( new_acct, old_acct )
+ || !pdb_set_username(new_acct, newname, PDB_CHANGED))
+ {
goto done;
-
+ }
+
ret = smbpasswd_add_sam_account(my_methods, new_acct);
if (!NT_STATUS_IS_OK(ret))
goto done;
@@ -1505,9 +1496,11 @@ static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods,
if (*rename_script) {
int rename_ret;
- pstring_sub(rename_script, "%unew", newname);
- pstring_sub(rename_script, "%uold",
- pdb_get_username(old_acct));
+ string_sub2(rename_script, "%unew", newname, sizeof(pstring),
+ True, False, True);
+ string_sub2(rename_script, "%uold", pdb_get_username(old_acct),
+ sizeof(pstring), True, False, True);
+
rename_ret = smbrun(rename_script, NULL);
DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
@@ -1527,11 +1520,16 @@ done:
smbpasswd_delete_sam_account(my_methods, new_acct);
if (new_acct)
- pdb_free_sam(&new_acct);
+ TALLOC_FREE(new_acct);
return (ret);
}
+static BOOL smbpasswd_rid_algorithm(struct pdb_methods *methods)
+{
+ return True;
+}
+
static void free_private_data(void **vp)
{
struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
@@ -1542,12 +1540,12 @@ static void free_private_data(void **vp)
/* No need to free any further, as it is talloc()ed */
}
-static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char *location )
{
NTSTATUS nt_status;
struct smbpasswd_privates *privates;
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ if ( !NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method )) ) {
return nt_status;
}
@@ -1563,11 +1561,11 @@ static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_m
(*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
(*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
- /* Setup private data and free function */
+ (*pdb_method)->rid_algorithm = smbpasswd_rid_algorithm;
- privates = TALLOC_ZERO_P(pdb_context->mem_ctx, struct smbpasswd_privates);
+ /* Setup private data and free function */
- if (!privates) {
+ if ( !(privates = TALLOC_ZERO_P( *pdb_method, struct smbpasswd_privates )) ) {
DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -1575,9 +1573,9 @@ static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_m
/* Store some config details */
if (location) {
- privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, location);
+ privates->smbpasswd_file = talloc_strdup(*pdb_method, location);
} else {
- privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, lp_smb_passwd_file());
+ privates->smbpasswd_file = talloc_strdup(*pdb_method, lp_smb_passwd_file());
}
if (!privates->smbpasswd_file) {
diff --git a/source/passdb/pdb_sql.c b/source/passdb/pdb_sql.c
deleted file mode 100644
index f4f6e0112ae..00000000000
--- a/source/passdb/pdb_sql.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * Common PDB SQL backend functions
- * Copyright (C) Jelmer Vernooij 2003-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"
-
-#define CONFIG_TABLE_DEFAULT "user"
-#define CONFIG_LOGON_TIME_DEFAULT "logon_time"
-#define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time"
-#define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time"
-#define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time"
-#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time"
-#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time"
-#define CONFIG_USERNAME_DEFAULT "username"
-#define CONFIG_DOMAIN_DEFAULT "domain"
-#define CONFIG_NT_USERNAME_DEFAULT "nt_username"
-#define CONFIG_FULLNAME_DEFAULT "nt_fullname"
-#define CONFIG_HOME_DIR_DEFAULT "home_dir"
-#define CONFIG_DIR_DRIVE_DEFAULT "dir_drive"
-#define CONFIG_LOGON_SCRIPT_DEFAULT "logon_script"
-#define CONFIG_PROFILE_PATH_DEFAULT "profile_path"
-#define CONFIG_ACCT_DESC_DEFAULT "acct_desc"
-#define CONFIG_WORKSTATIONS_DEFAULT "workstations"
-#define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str"
-#define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial"
-#define CONFIG_USER_SID_DEFAULT "user_sid"
-#define CONFIG_GROUP_SID_DEFAULT "group_sid"
-#define CONFIG_LM_PW_DEFAULT "lm_pw"
-#define CONFIG_NT_PW_DEFAULT "nt_pw"
-#define CONFIG_PLAIN_PW_DEFAULT "NULL"
-#define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl"
-#define CONFIG_LOGON_DIVS_DEFAULT "logon_divs"
-#define CONFIG_HOURS_LEN_DEFAULT "hours_len"
-#define CONFIG_BAD_PASSWORD_COUNT_DEFAULT "bad_password_count"
-#define CONFIG_LOGON_COUNT_DEFAULT "logon_count"
-#define CONFIG_UNKNOWN_6_DEFAULT "unknown_6"
-#define CONFIG_LOGON_HOURS "logon_hours"
-
-/* Used to construct insert and update queries */
-
-typedef struct pdb_sql_query {
- char update;
- char *part1;
- char *part2;
-} pdb_sql_query;
-
-static void pdb_sql_int_field(struct pdb_sql_query *q, const char *name, int value)
-{
- if (!name || strchr(name, '\''))
- return; /* This field shouldn't be set by us */
-
- if (q->update) {
- q->part1 =
- talloc_asprintf_append(q->part1,
- "%s = %d,", name, value);
- } else {
- q->part1 =
- talloc_asprintf_append(q->part1, "%s,", name);
- q->part2 =
- talloc_asprintf_append(q->part2, "%d,", value);
- }
-}
-
-char *sql_escape_string(TALLOC_CTX *mem_ctx, const char *unesc)
-{
- char *esc = talloc_array(mem_ctx, char, strlen(unesc) * 2 + 3);
- size_t pos_unesc = 0, pos_esc = 0;
-
- for(pos_unesc = 0; unesc[pos_unesc]; pos_unesc++) {
- switch(unesc[pos_unesc]) {
- case '\\':
- case '\'':
- case '"':
- esc[pos_esc] = '\\'; pos_esc++;
- default:
- esc[pos_esc] = unesc[pos_unesc]; pos_esc++;
- break;
- }
- }
-
- esc[pos_esc] = '\0';
-
- return esc;
-}
-
-static NTSTATUS pdb_sql_string_field(struct pdb_sql_query *q,
- const char *name, const char *value)
-{
- char *esc_value;
-
- if (!name || !value || !strcmp(value, "") || strchr(name, '\''))
- return NT_STATUS_INVALID_PARAMETER; /* This field shouldn't be set by module */
-
- esc_value = sql_escape_string(q, value);
-
- if (q->update) {
- q->part1 =
- talloc_asprintf_append(q->part1,
- "%s = '%s',", name, esc_value);
- } else {
- q->part1 =
- talloc_asprintf_append(q->part1, "%s,", name);
- q->part2 =
- talloc_asprintf_append(q->part2, "'%s',",
- esc_value);
- }
-
- talloc_free(esc_value);
-
- return NT_STATUS_OK;
-}
-
-#define config_value(data,name,default_value) \
- lp_parm_const_string(GLOBAL_SECTION_SNUM, data, name, default_value)
-
-static const char * config_value_write(const char *location, const char *name, const char *default_value)
-{
- char const *v = NULL;
- char const *swrite = NULL;
-
- v = lp_parm_const_string(GLOBAL_SECTION_SNUM, location, name, default_value);
-
- if (!v)
- return NULL;
-
- swrite = strrchr(v, ':');
-
- /* Default to the same field as read field */
- if (!swrite) {
-
- /* Updating NULL does not make much sense */
- if (!strcmp(v, "NULL"))
- return NULL;
-
- return v;
- }
-
- swrite++;
-
- /* If the field is 0 chars long, we shouldn't write to it */
- if (!strlen(swrite) || !strcmp(swrite, "NULL"))
- return NULL;
-
- /* Otherwise, use the additionally specified */
- return swrite;
-}
-
-static const char * config_value_read(const char *location, const char *name, const char *default_value)
-{
- char *v = NULL;
- char *swrite;
-
- v = lp_parm_talloc_string(GLOBAL_SECTION_SNUM, location, name, default_value);
-
- if (!v)
- return "NULL";
-
- swrite = strrchr(v, ':');
-
- /* If no write is specified, there are no problems */
- if (!swrite) {
- if (strlen(v) == 0)
- return "NULL";
- return (const char *)v;
- }
-
- /* Otherwise, we have to cut the ':write_part' */
- *swrite = '\0';
- if (strlen(v) == 0)
- return "NULL";
-
- return (const char *)v;
-}
-
-char *sql_account_query_select(TALLOC_CTX *mem_ctx, const char *data, BOOL update, enum sql_search_field field, const char *value)
-{
- const char *field_string;
- char *query;
-
- switch(field) {
- case SQL_SEARCH_NONE:
- field_string = "'1'";
- value = "1";
- break;
-
- case SQL_SEARCH_USER_SID:
- field_string = config_value_read(data, "user sid column",
- CONFIG_USER_SID_DEFAULT);
- break;
-
- case SQL_SEARCH_USER_NAME:
- field_string = config_value_read(data, "username column",
- CONFIG_USERNAME_DEFAULT);
- break;
- default:
- field_string = "unknown";
- break;
- }
-
- query = talloc_asprintf(mem_ctx,
- "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'",
- config_value_read(data, "logon time column",
- CONFIG_LOGON_TIME_DEFAULT),
- config_value_read(data, "logoff time column",
- CONFIG_LOGOFF_TIME_DEFAULT),
- config_value_read(data, "kickoff time column",
- CONFIG_KICKOFF_TIME_DEFAULT),
- config_value_read(data, "pass last set time column",
- CONFIG_PASS_LAST_SET_TIME_DEFAULT),
- config_value_read(data, "pass can change time column",
- CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
- config_value_read(data, "pass must change time column",
- CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
- config_value_read(data, "username column",
- CONFIG_USERNAME_DEFAULT),
- config_value_read(data, "domain column",
- CONFIG_DOMAIN_DEFAULT),
- config_value_read(data, "nt username column",
- CONFIG_NT_USERNAME_DEFAULT),
- config_value_read(data, "fullname column",
- CONFIG_FULLNAME_DEFAULT),
- config_value_read(data, "home dir column",
- CONFIG_HOME_DIR_DEFAULT),
- config_value_read(data, "dir drive column",
- CONFIG_DIR_DRIVE_DEFAULT),
- config_value_read(data, "logon script column",
- CONFIG_LOGON_SCRIPT_DEFAULT),
- config_value_read(data, "profile path column",
- CONFIG_PROFILE_PATH_DEFAULT),
- config_value_read(data, "acct desc column",
- CONFIG_ACCT_DESC_DEFAULT),
- config_value_read(data, "workstations column",
- CONFIG_WORKSTATIONS_DEFAULT),
- config_value_read(data, "unknown string column",
- CONFIG_UNKNOWN_STR_DEFAULT),
- config_value_read(data, "munged dial column",
- CONFIG_MUNGED_DIAL_DEFAULT),
- config_value_read(data, "user sid column",
- CONFIG_USER_SID_DEFAULT),
- config_value_read(data, "group sid column",
- CONFIG_GROUP_SID_DEFAULT),
- config_value_read(data, "lanman pass column",
- CONFIG_LM_PW_DEFAULT),
- config_value_read(data, "nt pass column",
- CONFIG_NT_PW_DEFAULT),
- config_value_read(data, "plain pass column",
- CONFIG_PLAIN_PW_DEFAULT),
- config_value_read(data, "acct ctrl column",
- CONFIG_ACCT_CTRL_DEFAULT),
- config_value_read(data, "logon divs column",
- CONFIG_LOGON_DIVS_DEFAULT),
- config_value_read(data, "hours len column",
- CONFIG_HOURS_LEN_DEFAULT),
- config_value_read(data, "bad password count column",
- CONFIG_BAD_PASSWORD_COUNT_DEFAULT),
- config_value_read(data, "logon count column",
- CONFIG_LOGON_COUNT_DEFAULT),
- config_value_read(data, "unknown 6 column",
- CONFIG_UNKNOWN_6_DEFAULT),
- config_value_read(data, "logon hours column",
- CONFIG_LOGON_HOURS),
- config_value(data, "table", CONFIG_TABLE_DEFAULT),
- field_string, value
- );
- return query;
-}
-
-char *sql_account_query_delete(TALLOC_CTX *mem_ctx, const char *data, const char *esc)
-{
- char *query;
-
- query = talloc_asprintf(mem_ctx, "DELETE FROM %s WHERE %s = '%s'",
- config_value(data, "table", CONFIG_TABLE_DEFAULT),
- config_value_read(data, "username column",
- CONFIG_USERNAME_DEFAULT), esc);
- return query;
-}
-
-char *sql_account_query_update(TALLOC_CTX *mem_ctx, const char *location, const SAM_ACCOUNT *newpwd, char isupdate)
-{
- char *ret;
- pstring temp;
- fstring sid_str;
- pdb_sql_query *query;
- int some_field_affected = 0;
-
- query = talloc(mem_ctx, pdb_sql_query);
- query->update = isupdate;
-
- /* I know this is somewhat overkill but only the talloc
- * functions have asprint_append and the 'normal' asprintf
- * is a GNU extension */
- query->part2 = talloc_asprintf(query, "%s", "");
- if (query->update) {
- query->part1 =
- talloc_asprintf(query, "UPDATE %s SET ",
- config_value(location, "table",
- CONFIG_TABLE_DEFAULT));
- } else {
- query->part1 =
- talloc_asprintf(query, "INSERT INTO %s (",
- config_value(location, "table",
- CONFIG_TABLE_DEFAULT));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_ACCTCTRL)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location, "acct ctrl column",
- CONFIG_ACCT_CTRL_DEFAULT),
- pdb_get_acct_ctrl(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_LOGONTIME)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "logon time column",
- CONFIG_LOGON_TIME_DEFAULT),
- pdb_get_logon_time(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_LOGOFFTIME)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "logoff time column",
- CONFIG_LOGOFF_TIME_DEFAULT),
- pdb_get_logoff_time(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_KICKOFFTIME)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "kickoff time column",
- CONFIG_KICKOFF_TIME_DEFAULT),
- pdb_get_kickoff_time(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_CANCHANGETIME)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "pass can change time column",
- CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
- pdb_get_pass_can_change_time(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_MUSTCHANGETIME)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "pass must change time column",
- CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
- pdb_get_pass_must_change_time(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_PASSLASTSET)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "pass last set time column",
- CONFIG_PASS_LAST_SET_TIME_DEFAULT),
- pdb_get_pass_last_set_time(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_HOURSLEN)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "hours len column",
- CONFIG_HOURS_LEN_DEFAULT),
- pdb_get_hours_len(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_LOGONDIVS)) {
- some_field_affected = 1;
- pdb_sql_int_field(query,
- config_value_write(location,
- "logon divs column",
- CONFIG_LOGON_DIVS_DEFAULT),
- pdb_get_logon_divs(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_USERSID)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "user sid column",
- CONFIG_USER_SID_DEFAULT),
- sid_to_string(sid_str,
- pdb_get_user_sid(newpwd)));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_GROUPSID)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "group sid column",
- CONFIG_GROUP_SID_DEFAULT),
- sid_to_string(sid_str,
- pdb_get_group_sid(newpwd)));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_USERNAME)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "username column",
- CONFIG_USERNAME_DEFAULT),
- pdb_get_username(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_DOMAIN)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "domain column",
- CONFIG_DOMAIN_DEFAULT),
- pdb_get_domain(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_USERNAME)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location,
- "nt username column",
- CONFIG_NT_USERNAME_DEFAULT),
- pdb_get_nt_username(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_FULLNAME)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "fullname column",
- CONFIG_FULLNAME_DEFAULT),
- pdb_get_fullname(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_LOGONSCRIPT)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location,
- "logon script column",
- CONFIG_LOGON_SCRIPT_DEFAULT),
- pdb_get_logon_script(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_PROFILE)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location,
- "profile path column",
- CONFIG_PROFILE_PATH_DEFAULT),
- pdb_get_profile_path(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_DRIVE)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "dir drive column",
- CONFIG_DIR_DRIVE_DEFAULT),
- pdb_get_dir_drive(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_SMBHOME)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location, "home dir column",
- CONFIG_HOME_DIR_DEFAULT),
- pdb_get_homedir(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_WORKSTATIONS)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location,
- "workstations column",
- CONFIG_WORKSTATIONS_DEFAULT),
- pdb_get_workstations(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_UNKNOWNSTR)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location,
- "unknown string column",
- CONFIG_UNKNOWN_STR_DEFAULT),
- pdb_get_workstations(newpwd));
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_LMPASSWD)) {
- some_field_affected = 1;
- pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd),
- pdb_get_acct_ctrl(newpwd));
- pdb_sql_string_field(query,
- config_value_write(location,
- "lanman pass column",
- CONFIG_LM_PW_DEFAULT), temp);
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_NTPASSWD)) {
- some_field_affected = 1;
- pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd),
- pdb_get_acct_ctrl(newpwd));
- pdb_sql_string_field(query,
- config_value_write(location, "nt pass column",
- CONFIG_NT_PW_DEFAULT), temp);
- }
-
- if (!isupdate || IS_SAM_CHANGED(newpwd, PDB_HOURS)) {
- some_field_affected = 1;
- pdb_sql_string_field(query,
- config_value_write(location,
- "logon hours column",
- CONFIG_LOGON_HOURS),
- (const char *)pdb_get_hours(newpwd));
- }
-
- if (!some_field_affected) {
- talloc_free(query);
- return NULL;
- }
-
- if (query->update) {
- query->part1[strlen(query->part1) - 1] = '\0';
- query->part1 = talloc_asprintf(
- mem_ctx, "%s WHERE %s = '%s'", query->part1,
- config_value_read(location,
- "user sid column",
- CONFIG_USER_SID_DEFAULT),
- sid_to_string(sid_str, pdb_get_user_sid (newpwd)));
- } else {
- query->part2[strlen(query->part2) - 1] = ')';
- query->part1[strlen(query->part1) - 1] = ')';
- query->part1 =
- talloc_asprintf_append(query->part1,
- " VALUES (%s", query->part2);
- }
-
- ret = talloc_strdup(mem_ctx, query->part1);
- talloc_free(query);
- return ret;
-}
-
-BOOL sql_account_config_valid(const char *data)
-{
- const char *sid_column, *username_column;
-
- sid_column = config_value_read(data, "user sid column", CONFIG_USER_SID_DEFAULT);
- username_column = config_value_read(data, "username column", CONFIG_USERNAME_DEFAULT);
-
- if(!strcmp(sid_column,"NULL") || !strcmp(username_column, "NULL")) {
- DEBUG(0,("Please specify both a valid 'user sid column' and a valid 'username column' in smb.conf\n"));
- return False;
- }
-
- return True;
-}
diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c
index de79b4096a6..ba8124d3923 100644
--- a/source/passdb/pdb_tdb.c
+++ b/source/passdb/pdb_tdb.c
@@ -3,7 +3,7 @@
* SMB parameters and setup
* Copyright (C) Andrew Tridgell 1992-1998
* Copyright (C) Simo Sorce 2000-2003
- * Copyright (C) Gerald Carter 2000
+ * Copyright (C) Gerald Carter 2000-2006
* Copyright (C) Jeremy Allison 2001
* Copyright (C) Andrew Bartlett 2002
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
@@ -38,60 +38,666 @@ static int tdbsam_debug_level = DBGC_ALL;
#endif
-#define TDBSAM_VERSION 2 /* Most recent TDBSAM version */
+#define TDBSAM_VERSION 3 /* Most recent TDBSAM version */
#define TDBSAM_VERSION_STRING "INFO/version"
#define PASSDB_FILE_NAME "passdb.tdb"
#define USERPREFIX "USER_"
#define RIDPREFIX "RID_"
#define PRIVPREFIX "PRIV_"
-#define tdbsamver_t int32
-
-struct tdbsam_privates {
- TDB_CONTEXT *passwd_tdb;
-
- /* retrive-once info */
- const char *tdbsam_location;
-};
struct pwent_list {
struct pwent_list *prev, *next;
TDB_DATA key;
};
static struct pwent_list *tdbsam_pwent_list;
+static BOOL pwent_initialized;
+
+/* GLOBAL TDB SAM CONTEXT */
+
+static TDB_CONTEXT *tdbsam;
+static int ref_count = 0;
+static pstring tdbsam_filename;
+
+/**********************************************************************
+ Marshall/unmarshall struct samu structs.
+ *********************************************************************/
+#define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
-/**
- * Convert old TDBSAM to the latest version.
- * @param pdb_tdb A pointer to the opened TDBSAM file which must be converted.
- * This file must be opened with read/write access.
- * @param from Current version of the TDBSAM file.
- * @return True if the conversion has been successful, false otherwise.
- **/
+/*********************************************************************
+*********************************************************************/
-static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
+static BOOL init_sam_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
{
- const char * vstring = TDBSAM_VERSION_STRING;
- SAM_ACCOUNT *user = NULL;
- const char *prefix = USERPREFIX;
- TDB_DATA data, key, old_key;
- uint8 *buf = NULL;
- BOOL ret;
- if (pdb_tdb == NULL) {
- DEBUG(0,("tdbsam_convert: Bad TDB Context pointer.\n"));
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+ char *username = NULL;
+ char *domain = NULL;
+ char *nt_username = NULL;
+ char *dir_drive = NULL;
+ char *unknown_str = NULL;
+ char *munged_dial = NULL;
+ char *fullname = NULL;
+ char *homedir = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *acct_desc = NULL;
+ char *workstations = NULL;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
+ uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
+ uint8 *hours = NULL;
+ uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
+ uint32 len = 0;
+ uint32 lm_pw_len, nt_pw_len, hourslen;
+ BOOL ret = True;
+
+ if(sampass == NULL || buf == NULL) {
+ DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
return False;
}
- /* handle a Samba upgrade */
- tdb_lock_bystring(pdb_tdb, vstring, 0);
+/* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
+
+ /* unpack the buffer into variables */
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
+ &logon_time, /* d */
+ &logoff_time, /* d */
+ &kickoff_time, /* d */
+ &pass_last_set_time, /* d */
+ &pass_can_change_time, /* d */
+ &pass_must_change_time, /* d */
+ &username_len, &username, /* B */
+ &domain_len, &domain, /* B */
+ &nt_username_len, &nt_username, /* B */
+ &fullname_len, &fullname, /* B */
+ &homedir_len, &homedir, /* B */
+ &dir_drive_len, &dir_drive, /* B */
+ &logon_script_len, &logon_script, /* B */
+ &profile_path_len, &profile_path, /* B */
+ &acct_desc_len, &acct_desc, /* B */
+ &workstations_len, &workstations, /* B */
+ &unknown_str_len, &unknown_str, /* B */
+ &munged_dial_len, &munged_dial, /* B */
+ &user_rid, /* d */
+ &group_rid, /* d */
+ &lm_pw_len, &lm_pw_ptr, /* B */
+ &nt_pw_len, &nt_pw_ptr, /* B */
+ &acct_ctrl, /* w */
+ &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
+ &logon_divs, /* w */
+ &hours_len, /* d */
+ &hourslen, &hours, /* B */
+ &bad_password_count, /* w */
+ &logon_count, /* w */
+ &unknown_6); /* d */
+
+ if (len == (uint32) -1) {
+ ret = False;
+ goto done;
+ }
+
+ pdb_set_logon_time(sampass, logon_time, PDB_SET);
+ pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+ pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+ pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+ pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+ pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+ pdb_set_username(sampass, username, PDB_SET);
+ pdb_set_domain(sampass, domain, PDB_SET);
+ pdb_set_nt_username(sampass, nt_username, PDB_SET);
+ pdb_set_fullname(sampass, fullname, PDB_SET);
+
+ if (homedir) {
+ pdb_set_homedir(sampass, homedir, PDB_SET);
+ }
+ else {
+ pdb_set_homedir(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_home()),
+ PDB_DEFAULT);
+ }
+
+ if (dir_drive)
+ pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+ else {
+ pdb_set_dir_drive(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_drive()),
+ PDB_DEFAULT);
+ }
+
+ if (logon_script)
+ pdb_set_logon_script(sampass, logon_script, PDB_SET);
+ else {
+ pdb_set_logon_script(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_script()),
+ PDB_DEFAULT);
+ }
+
+ if (profile_path) {
+ pdb_set_profile_path(sampass, profile_path, PDB_SET);
+ } else {
+ pdb_set_profile_path(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_path()),
+ PDB_DEFAULT);
+ }
+
+ pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+ pdb_set_workstations(sampass, workstations, PDB_SET);
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+ if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+ if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+ if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+ pdb_set_user_sid_from_rid(sampass, user_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);
+ pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+ pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+ pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(nt_username);
+ SAFE_FREE(fullname);
+ SAFE_FREE(homedir);
+ SAFE_FREE(dir_drive);
+ SAFE_FREE(logon_script);
+ SAFE_FREE(profile_path);
+ SAFE_FREE(acct_desc);
+ SAFE_FREE(workstations);
+ SAFE_FREE(munged_dial);
+ SAFE_FREE(unknown_str);
+ SAFE_FREE(lm_pw_ptr);
+ SAFE_FREE(nt_pw_ptr);
+ SAFE_FREE(hours);
+
+ return ret;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static BOOL init_sam_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
+{
+
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ bad_password_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+ char *username = NULL;
+ char *domain = NULL;
+ char *nt_username = NULL;
+ char *dir_drive = NULL;
+ char *unknown_str = NULL;
+ char *munged_dial = NULL;
+ char *fullname = NULL;
+ char *homedir = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *acct_desc = NULL;
+ char *workstations = NULL;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
+ uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
+ uint8 *hours = NULL;
+ uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
+ uint32 len = 0;
+ uint32 lm_pw_len, nt_pw_len, hourslen;
+ BOOL ret = True;
- if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
- DEBUG(0,("tdbsam_convert: cannot initialized a SAM_ACCOUNT.\n"));
+ if(sampass == NULL || buf == NULL) {
+ DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
return False;
}
+/* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
+
+ /* unpack the buffer into variables */
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
+ &logon_time, /* d */
+ &logoff_time, /* d */
+ &kickoff_time, /* d */
+ /* Change from V0 is addition of bad_password_time field. */
+ &bad_password_time, /* d */
+ &pass_last_set_time, /* d */
+ &pass_can_change_time, /* d */
+ &pass_must_change_time, /* d */
+ &username_len, &username, /* B */
+ &domain_len, &domain, /* B */
+ &nt_username_len, &nt_username, /* B */
+ &fullname_len, &fullname, /* B */
+ &homedir_len, &homedir, /* B */
+ &dir_drive_len, &dir_drive, /* B */
+ &logon_script_len, &logon_script, /* B */
+ &profile_path_len, &profile_path, /* B */
+ &acct_desc_len, &acct_desc, /* B */
+ &workstations_len, &workstations, /* B */
+ &unknown_str_len, &unknown_str, /* B */
+ &munged_dial_len, &munged_dial, /* B */
+ &user_rid, /* d */
+ &group_rid, /* d */
+ &lm_pw_len, &lm_pw_ptr, /* B */
+ &nt_pw_len, &nt_pw_ptr, /* B */
+ &acct_ctrl, /* w */
+ &remove_me, /* d */
+ &logon_divs, /* w */
+ &hours_len, /* d */
+ &hourslen, &hours, /* B */
+ &bad_password_count, /* w */
+ &logon_count, /* w */
+ &unknown_6); /* d */
+
+ if (len == (uint32) -1) {
+ ret = False;
+ goto done;
+ }
+
+ pdb_set_logon_time(sampass, logon_time, PDB_SET);
+ pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+ pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+
+ /* Change from V0 is addition of bad_password_time field. */
+ pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
+ pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+ pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+ pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+ pdb_set_username(sampass, username, PDB_SET);
+ pdb_set_domain(sampass, domain, PDB_SET);
+ pdb_set_nt_username(sampass, nt_username, PDB_SET);
+ pdb_set_fullname(sampass, fullname, PDB_SET);
+
+ if (homedir) {
+ pdb_set_homedir(sampass, homedir, PDB_SET);
+ }
+ else {
+ pdb_set_homedir(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_home()),
+ PDB_DEFAULT);
+ }
+
+ if (dir_drive)
+ pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+ else {
+ pdb_set_dir_drive(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_drive()),
+ PDB_DEFAULT);
+ }
+
+ if (logon_script)
+ pdb_set_logon_script(sampass, logon_script, PDB_SET);
+ else {
+ pdb_set_logon_script(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_script()),
+ PDB_DEFAULT);
+ }
+
+ if (profile_path) {
+ pdb_set_profile_path(sampass, profile_path, PDB_SET);
+ } else {
+ pdb_set_profile_path(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_path()),
+ PDB_DEFAULT);
+ }
+
+ pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+ pdb_set_workstations(sampass, workstations, PDB_SET);
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+ if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+ if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+ if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+
+ pdb_set_user_sid_from_rid(sampass, user_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);
+ pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+ pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+ pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(nt_username);
+ SAFE_FREE(fullname);
+ SAFE_FREE(homedir);
+ SAFE_FREE(dir_drive);
+ SAFE_FREE(logon_script);
+ SAFE_FREE(profile_path);
+ SAFE_FREE(acct_desc);
+ SAFE_FREE(workstations);
+ SAFE_FREE(munged_dial);
+ SAFE_FREE(unknown_str);
+ SAFE_FREE(lm_pw_ptr);
+ SAFE_FREE(nt_pw_ptr);
+ SAFE_FREE(hours);
+
+ return ret;
+}
+
+BOOL init_sam_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
+{
+
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ bad_password_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+ char *username = NULL;
+ char *domain = NULL;
+ char *nt_username = NULL;
+ char *dir_drive = NULL;
+ char *unknown_str = NULL;
+ char *munged_dial = NULL;
+ char *fullname = NULL;
+ char *homedir = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *acct_desc = NULL;
+ char *workstations = NULL;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ uint32 user_rid, group_rid, hours_len, unknown_6;
+ uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
+ uint8 *hours = NULL;
+ uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
+ uint32 len = 0;
+ uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
+ uint32 pwHistLen = 0;
+ BOOL ret = True;
+ fstring tmpstring;
+ BOOL expand_explicit = lp_passdb_expand_explicit();
+
+ if(sampass == NULL || buf == NULL) {
+ DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
+ return False;
+ }
+
+/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
+
+ /* unpack the buffer into variables */
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2,
+ &logon_time, /* d */
+ &logoff_time, /* d */
+ &kickoff_time, /* d */
+ &bad_password_time, /* d */
+ &pass_last_set_time, /* d */
+ &pass_can_change_time, /* d */
+ &pass_must_change_time, /* d */
+ &username_len, &username, /* B */
+ &domain_len, &domain, /* B */
+ &nt_username_len, &nt_username, /* B */
+ &fullname_len, &fullname, /* B */
+ &homedir_len, &homedir, /* B */
+ &dir_drive_len, &dir_drive, /* B */
+ &logon_script_len, &logon_script, /* B */
+ &profile_path_len, &profile_path, /* B */
+ &acct_desc_len, &acct_desc, /* B */
+ &workstations_len, &workstations, /* B */
+ &unknown_str_len, &unknown_str, /* B */
+ &munged_dial_len, &munged_dial, /* B */
+ &user_rid, /* d */
+ &group_rid, /* d */
+ &lm_pw_len, &lm_pw_ptr, /* B */
+ &nt_pw_len, &nt_pw_ptr, /* B */
+ /* Change from V1 is addition of password history field. */
+ &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */
+ &acct_ctrl, /* w */
+ /* Also "remove_me" field was removed. */
+ &logon_divs, /* w */
+ &hours_len, /* d */
+ &hourslen, &hours, /* B */
+ &bad_password_count, /* w */
+ &logon_count, /* w */
+ &unknown_6); /* d */
+
+ if (len == (uint32) -1) {
+ ret = False;
+ goto done;
+ }
+
+ pdb_set_logon_time(sampass, logon_time, PDB_SET);
+ pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+ pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+ pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
+ pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+ pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+ pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+ pdb_set_username(sampass, username, PDB_SET);
+ pdb_set_domain(sampass, domain, PDB_SET);
+ pdb_set_nt_username(sampass, nt_username, PDB_SET);
+ pdb_set_fullname(sampass, fullname, PDB_SET);
+
+ if (homedir) {
+ fstrcpy( tmpstring, homedir );
+ if (expand_explicit) {
+ standard_sub_basic( username, tmpstring,
+ sizeof(tmpstring) );
+ }
+ pdb_set_homedir(sampass, tmpstring, PDB_SET);
+ }
+ else {
+ pdb_set_homedir(sampass,
+ talloc_sub_basic(sampass, username, lp_logon_home()),
+ PDB_DEFAULT);
+ }
+
+ if (dir_drive)
+ pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+ else
+ pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
+
+ if (logon_script) {
+ fstrcpy( tmpstring, logon_script );
+ if (expand_explicit) {
+ standard_sub_basic( username, 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()),
+ PDB_DEFAULT);
+ }
+
+ if (profile_path) {
+ fstrcpy( tmpstring, profile_path );
+ if (expand_explicit) {
+ standard_sub_basic( username, 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()),
+ PDB_DEFAULT);
+ }
+
+ pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+ pdb_set_workstations(sampass, workstations, PDB_SET);
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+ if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+ if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+ if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ /* 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);
+ if (!pw_hist) {
+ ret = False;
+ goto done;
+ }
+ memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
+ if (nt_pw_hist_ptr && nt_pw_hist_len) {
+ int i;
+ SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
+ nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
+ for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
+ memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
+ &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
+ PW_HISTORY_ENTRY_LEN);
+ }
+ }
+ if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
+ SAFE_FREE(pw_hist);
+ ret = False;
+ goto done;
+ }
+ SAFE_FREE(pw_hist);
+ } else {
+ pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
+ }
+
+ 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);
+ pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+ pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+ pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(nt_username);
+ SAFE_FREE(fullname);
+ SAFE_FREE(homedir);
+ SAFE_FREE(dir_drive);
+ SAFE_FREE(logon_script);
+ SAFE_FREE(profile_path);
+ SAFE_FREE(acct_desc);
+ SAFE_FREE(workstations);
+ SAFE_FREE(munged_dial);
+ SAFE_FREE(unknown_str);
+ SAFE_FREE(lm_pw_ptr);
+ SAFE_FREE(nt_pw_ptr);
+ SAFE_FREE(nt_pw_hist_ptr);
+ SAFE_FREE(hours);
+
+ return ret;
+}
+
+
+/**********************************************************************
+ Intialize a struct samu struct from a BYTE buffer of size len
+ *********************************************************************/
+
+static BOOL init_sam_from_buffer(struct samu *sampass, uint8 *buf, uint32 buflen)
+{
+ return init_sam_from_buffer_v3(sampass, buf, buflen);
+}
+
+/**********************************************************************
+ Intialize a BYTE buffer from a struct samu struct
+ *********************************************************************/
+
+static uint32 init_buffer_from_sam (uint8 **buf, struct samu *sampass, BOOL size_only)
+{
+ return init_buffer_from_sam_v3(buf, sampass, size_only);
+}
+
+/**********************************************************************
+ Intialize a BYTE buffer from a struct samu struct
+ *********************************************************************/
+
+static BOOL tdbsam_convert(int32 from)
+{
+ const char *vstring = TDBSAM_VERSION_STRING;
+ const char *prefix = USERPREFIX;
+ TDB_DATA data, key, old_key;
+ uint8 *buf = NULL;
+ BOOL ret;
+
+ /* handle a Samba upgrade */
+ tdb_lock_bystring(tdbsam, vstring);
+
/* Enumerate all records and convert them */
- key = tdb_firstkey(pdb_tdb);
+ key = tdb_firstkey(tdbsam);
while (key.dptr) {
@@ -99,26 +705,26 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
old_key = key;
/* increment to next in line */
- key = tdb_nextkey(pdb_tdb, key);
+ key = tdb_nextkey(tdbsam, key);
SAFE_FREE(old_key.dptr);
}
if (key.dptr) {
-
+ struct samu *user = NULL;
+
/* read from tdbsam */
- data = tdb_fetch(pdb_tdb, key);
+ data = tdb_fetch(tdbsam, key);
if (!data.dptr) {
DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
return False;
}
- if (!NT_STATUS_IS_OK(pdb_reset_sam(user))) {
- DEBUG(0,("tdbsam_convert: cannot reset SAM_ACCOUNT.\n"));
- SAFE_FREE(data.dptr);
+ /* unpack the buffer from the former format */
+ if ( !(user = samu_new( NULL )) ) {
+ DEBUG(0,("tdbsam_convert: samu_new() failed!\n"));
+ SAFE_FREE( data.dptr );
return False;
}
-
- /* unpack the buffer from the former format */
DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
switch (from) {
case 0:
@@ -130,13 +736,17 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
case 2:
ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize);
break;
+ case 3:
+ ret = init_sam_from_buffer_v3(user, (uint8 *)data.dptr, data.dsize);
+ break;
default:
/* unknown tdbsam version */
ret = False;
}
if (!ret) {
- DEBUG(0,("tdbsam_convert: Bad SAM_ACCOUNT entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
+ DEBUG(0,("tdbsam_convert: Bad struct samu entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
SAFE_FREE(data.dptr);
+ TALLOC_FREE(user );
return False;
}
@@ -144,17 +754,20 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
SAFE_FREE(data.dptr);
/* pack from the buffer into the new format */
+
DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
- if ((data.dsize=init_buffer_from_sam (&buf, user, False)) == -1) {
- DEBUG(0,("tdbsam_convert: cannot pack the SAM_ACCOUNT into the new format\n"));
- SAFE_FREE(data.dptr);
+ data.dsize = init_buffer_from_sam (&buf, user, False);
+ TALLOC_FREE(user );
+
+ if ( data.dsize == -1 ) {
+ DEBUG(0,("tdbsam_convert: cannot pack the struct samu into the new format\n"));
return False;
}
data.dptr = (char *)buf;
/* Store the buffer inside the TDBSAM */
- if (tdb_store(pdb_tdb, key, data, TDB_MODIFY) != TDB_SUCCESS) {
- DEBUG(0,("tdbsam_convert: cannot store the SAM_ACCOUNT (key:%s) in new format\n",key.dptr));
+ if (tdb_store(tdbsam, key, data, TDB_MODIFY) != TDB_SUCCESS) {
+ DEBUG(0,("tdbsam_convert: cannot store the struct samu (key:%s) in new format\n",key.dptr));
SAFE_FREE(data.dptr);
return False;
}
@@ -163,99 +776,106 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
/* increment to next in line */
old_key = key;
- key = tdb_nextkey(pdb_tdb, key);
+ key = tdb_nextkey(tdbsam, key);
SAFE_FREE(old_key.dptr);
}
}
- pdb_free_sam(&user);
/* upgrade finished */
- tdb_store_int32(pdb_tdb, vstring, TDBSAM_VERSION);
- tdb_unlock_bystring(pdb_tdb, vstring);
+ tdb_store_int32(tdbsam, vstring, TDBSAM_VERSION);
+ tdb_unlock_bystring(tdbsam, vstring);
return(True);
}
-/**
- * Open the TDB passwd database, check version and convert it if needed.
- * @param name filename of the tdbsam file.
- * @param open_flags file access mode.
- * @return a TDB_CONTEXT handle on the tdbsam file.
- **/
+/*********************************************************************
+ Open the tdbsam file based on the absolute path specified.
+ Uses a reference count to allow multiple open calls.
+*********************************************************************/
-static TDB_CONTEXT * tdbsam_tdbopen (const char *name, int open_flags)
+static BOOL tdbsam_open( const char *name )
{
- TDB_CONTEXT *pdb_tdb;
- tdbsamver_t version;
+ int32 version;
- /* Try to open tdb passwd */
- if (!(pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT,
- open_flags, 0600))) {
- DEBUG(0, ("Unable to open/create TDB passwd\n"));
- return NULL;
+ /* check if we are already open */
+
+ if ( tdbsam ) {
+ ref_count++;
+ DEBUG(8,("tdbsam_open: Incrementing open reference count. Ref count is now %d\n",
+ ref_count));
+ return True;
+ }
+
+ SMB_ASSERT( ref_count == 0 );
+
+ /* Try to open tdb passwd. Create a new one if necessary */
+
+ if (!(tdbsam = tdb_open_log(name, 0, TDB_DEFAULT, O_CREAT|O_RDWR, 0600))) {
+ DEBUG(0, ("tdbsam_open: Failed to open/create TDB passwd [%s]\n", name));
+ return False;
}
+ /* set the initial reference count - must be done before tdbsam_convert
+ as that calls tdbsam_open()/tdbsam_close(). */
+
+ ref_count = 1;
+
/* Check the version */
- version = (tdbsamver_t) tdb_fetch_int32(pdb_tdb,
- TDBSAM_VERSION_STRING);
- if (version == -1)
+ version = tdb_fetch_int32( tdbsam, TDBSAM_VERSION_STRING );
+
+ if (version == -1) {
version = 0; /* Version not found, assume version 0 */
+ }
/* Compare the version */
if (version > TDBSAM_VERSION) {
/* Version more recent than the latest known */
- DEBUG(0, ("TDBSAM version unknown: %d\n", version));
- tdb_close(pdb_tdb);
- pdb_tdb = NULL;
+ DEBUG(0, ("tdbsam_open: unknown version => %d\n", version));
+ tdb_close( tdbsam );
+ ref_count = 0;
+ return False;
}
- else if (version < TDBSAM_VERSION) {
- /* Older version, must be converted */
- DEBUG(1, ("TDBSAM version too old (%d), trying to convert it.\n", version));
-
- /* Reopen the pdb file with read-write access if needed */
- if (!(open_flags & O_RDWR)) {
- DEBUG(10, ("tdbsam_tdbopen: TDB file opened with read only access, reopen it with read-write access.\n"));
- tdb_close(pdb_tdb);
- pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, (open_flags & 07777770) | O_RDWR, 0600);
- }
+
+
+ if ( version < TDBSAM_VERSION ) {
+ DEBUG(1, ("tdbsam_open: Converting version %d database to version %d.\n",
+ version, TDBSAM_VERSION));
- /* Convert */
- if (!tdbsam_convert(pdb_tdb, version)){
- DEBUG(0, ("tdbsam_tdbopen: Error when trying to convert tdbsam: %s\n",name));
- tdb_close(pdb_tdb);
- pdb_tdb = NULL;
- } else {
- DEBUG(1, ("TDBSAM converted successfully.\n"));
- }
-
- /* Reopen the pdb file as it must be */
- if (!(open_flags & O_RDWR)) {
- tdb_close(pdb_tdb);
- pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, open_flags, 0600);
+ if ( !tdbsam_convert(version) ) {
+ DEBUG(0, ("tdbsam_open: Error when trying to convert tdbsam [%s]\n",name));
+ tdb_close(tdbsam);
+ ref_count = 0;
+ return False;
}
+
+ DEBUG(3, ("TDBSAM converted successfully.\n"));
}
- return pdb_tdb;
+ DEBUG(4,("tdbsam_open: successfully opened %s\n", name ));
+
+ return True;
}
-/*****************************************************************************
- Utility functions to close the tdb sam database
- ****************************************************************************/
+/****************************************************************************
+ wrapper atound tdb_close() to handle the reference count
+****************************************************************************/
-static void tdbsam_tdbclose ( struct tdbsam_privates *state )
+void tdbsam_close( void )
{
- if ( !state )
- return;
-
- if ( state->passwd_tdb ) {
- tdb_close( state->passwd_tdb );
- state->passwd_tdb = NULL;
+ ref_count--;
+
+ DEBUG(8,("tdbsam_close: Reference count is now %d.\n", ref_count));
+
+ SMB_ASSERT(ref_count >= 0 );
+
+ if ( ref_count == 0 ) {
+ tdb_close( tdbsam );
+ tdbsam = NULL;
}
return;
-
}
/****************************************************************************
@@ -295,17 +915,16 @@ static int tdbsam_traverse_setpwent(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data,
Save a list of user keys for iteration.
****************************************************************/
-static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
+static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
{
- uint32 flags = update ? (O_RDWR|O_CREAT) : O_RDONLY;
-
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
-
- if ( !(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, flags )) )
- return NT_STATUS_UNSUCCESSFUL;
+ if ( !tdbsam_open( tdbsam_filename ) ) {
+ DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ tdb_traverse( tdbsam, tdbsam_traverse_setpwent, NULL );
+ pwent_initialized = True;
- tdb_traverse( tdb_state->passwd_tdb, tdbsam_traverse_setpwent, NULL );
-
return NT_STATUS_OK;
}
@@ -316,10 +935,14 @@ static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update,
static void tdbsam_endsampwent(struct pdb_methods *my_methods)
{
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
struct pwent_list *ptr, *ptr_next;
- tdbsam_tdbclose( tdb_state );
+ /* close the tdb only if we have a valid pwent state */
+
+ if ( pwent_initialized ) {
+ DEBUG(7, ("endtdbpwent: closed sam database.\n"));
+ tdbsam_close();
+ }
/* clear out any remaining entries in the list */
@@ -328,59 +951,51 @@ static void tdbsam_endsampwent(struct pdb_methods *my_methods)
DLIST_REMOVE( tdbsam_pwent_list, ptr );
SAFE_FREE( ptr->key.dptr);
SAFE_FREE( ptr );
- }
+ }
- DEBUG(7, ("endtdbpwent: closed sam database.\n"));
+ pwent_initialized = False;
}
/*****************************************************************
- Get one SAM_ACCOUNT from the TDB (next in line)
+ Get one struct samu from the TDB (next in line)
*****************************************************************/
-static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
+static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, struct samu *user)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
TDB_DATA data;
struct pwent_list *pkey;
if ( !user ) {
- DEBUG(0,("tdbsam_getsampwent: SAM_ACCOUNT is NULL.\n"));
+ DEBUG(0,("tdbsam_getsampwent: struct samu is NULL.\n"));
return nt_status;
}
if ( !tdbsam_pwent_list ) {
DEBUG(4,("tdbsam_getsampwent: end of list\n"));
- tdbsam_tdbclose( tdb_state );
return nt_status;
}
- if ( !tdb_state->passwd_tdb ) {
- if ( !(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY)) )
- return nt_status;
- }
-
/* pull the next entry */
pkey = tdbsam_pwent_list;
DLIST_REMOVE( tdbsam_pwent_list, pkey );
- data = tdb_fetch(tdb_state->passwd_tdb, pkey->key);
+ data = tdb_fetch(tdbsam, pkey->key);
SAFE_FREE( pkey->key.dptr);
SAFE_FREE( pkey);
- if (!data.dptr) {
+ if ( !data.dptr ) {
DEBUG(5,("pdb_getsampwent: database entry not found. Was the user deleted?\n"));
return nt_status;
}
- if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
- DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
+ if ( !init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize) ) {
+ DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
}
SAFE_FREE( data.dptr );
-
return NT_STATUS_OK;
}
@@ -389,18 +1004,15 @@ static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *
Lookup a name in the SAM TDB
******************************************************************/
-static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
+static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, struct samu *user, const char *sname)
{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- TDB_CONTEXT *pwd_tdb;
TDB_DATA data, key;
fstring keystr;
fstring name;
if ( !user ) {
- DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
- return nt_status;
+ DEBUG(0,("pdb_getsampwnam: struct samu is NULL.\n"));
+ return NT_STATUS_NO_MEMORY;
}
/* Data is stored in all lower-case */
@@ -412,52 +1024,37 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
- /* open the accounts TDB */
- if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
-
- if (errno == ENOENT) {
- /*
- * TDB file doesn't exist, so try to create new one. This is useful to avoid
- * confusing error msg when adding user account first time
- */
- if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_CREAT ))) {
- DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) did not exist. File successfully created.\n",
- tdb_state->tdbsam_location));
- tdb_close(pwd_tdb);
- } else {
- DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) does not exist. Couldn't create new one. Error was: %s\n",
- tdb_state->tdbsam_location, strerror(errno)));
- }
-
- /* requested user isn't there anyway */
- nt_status = NT_STATUS_NO_SUCH_USER;
- return nt_status;
- }
- DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
- return nt_status;
+ /* open the database */
+
+ if ( !tdbsam_open( tdbsam_filename ) ) {
+ DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
+ return NT_STATUS_ACCESS_DENIED;
}
-
+
/* get the record */
- data = tdb_fetch(pwd_tdb, key);
+
+ data = tdb_fetch(tdbsam, key);
if (!data.dptr) {
DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
- DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
DEBUGADD(5, (" Key: %s\n", keystr));
- tdb_close(pwd_tdb);
- return nt_status;
+ tdbsam_close();
+ return NT_STATUS_NO_SUCH_USER;
}
/* unpack the buffer */
+
if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
- DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
+ DEBUG(0,("pdb_getsampwent: Bad struct samu entry returned from TDB!\n"));
SAFE_FREE(data.dptr);
- tdb_close(pwd_tdb);
- return nt_status;
+ tdbsam_close();
+ return NT_STATUS_NO_MEMORY;
}
+
+ /* success */
+
SAFE_FREE(data.dptr);
-
- /* no further use for database, close it now */
- tdb_close(pwd_tdb);
+ tdbsam_close();
return NT_STATUS_OK;
}
@@ -466,60 +1063,65 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT
Search by rid
**************************************************************************/
-static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
+static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, struct samu *user, uint32 rid)
{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- TDB_CONTEXT *pwd_tdb;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
TDB_DATA data, key;
fstring keystr;
fstring name;
-
- if (user==NULL) {
- DEBUG(0,("pdb_getsampwrid: SAM_ACCOUNT is NULL.\n"));
+
+ if ( !user ) {
+ DEBUG(0,("pdb_getsampwrid: struct samu is NULL.\n"));
return nt_status;
}
-
+
/* set search key */
+
slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
- /* open the accounts TDB */
- if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
- DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
- return nt_status;
+ /* open the database */
+
+ if ( !tdbsam_open( tdbsam_filename ) ) {
+ DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
+ return NT_STATUS_ACCESS_DENIED;
}
/* get the record */
- data = tdb_fetch (pwd_tdb, key);
+
+ data = tdb_fetch (tdbsam, key);
if (!data.dptr) {
DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
- DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
- tdb_close (pwd_tdb);
- return nt_status;
+ DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
}
-
fstrcpy(name, data.dptr);
SAFE_FREE(data.dptr);
- tdb_close (pwd_tdb);
+ nt_status = tdbsam_getsampwnam (my_methods, user, name);
+
+ done:
+ /* cleanup */
- return tdbsam_getsampwnam (my_methods, user, name);
+ tdbsam_close();
+
+ return nt_status;
}
-static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
+static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
{
uint32 rid;
- if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
+
+ if ( !sid_peek_check_rid(get_global_sam_sid(), sid, &rid) )
return NT_STATUS_UNSUCCESSFUL;
+
return tdbsam_getsampwrid(my_methods, user, rid);
}
-static BOOL tdb_delete_samacct_only(TDB_CONTEXT *pwd_tdb,
- struct pdb_methods *my_methods,
- SAM_ACCOUNT *sam_pass)
+static BOOL tdb_delete_samacct_only( struct samu *sam_pass )
{
TDB_DATA key;
fstring keystr;
@@ -529,44 +1131,47 @@ static BOOL tdb_delete_samacct_only(TDB_CONTEXT *pwd_tdb,
strlower_m(name);
/* set the search key */
+
slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
/* it's outaa here! 8^) */
- if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
+
+ if (tdb_delete(tdbsam, key) != TDB_SUCCESS) {
DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
- DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
- tdb_close(pwd_tdb);
+ DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
return False;
}
+
return True;
}
/***************************************************************************
- Delete a SAM_ACCOUNT
+ Delete a struct samu records for the username and RID key
****************************************************************************/
-static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_pass)
+static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, struct samu *sam_pass)
{
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- TDB_CONTEXT *pwd_tdb;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
TDB_DATA key;
fstring keystr;
uint32 rid;
fstring name;
+ /* open the database */
+
+ if ( !tdbsam_open( tdbsam_filename ) ) {
+ DEBUG(0,("tdbsam_delete_sam_account: failed to open %s!\n",
+ tdbsam_filename));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
fstrcpy(name, pdb_get_username(sam_pass));
strlower_m(name);
- /* open the TDB */
- if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR))) {
- DEBUG(0, ("Unable to open TDB passwd!"));
- return nt_status;
- }
-
/* set the search key */
+
slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
@@ -574,40 +1179,43 @@ static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_AC
rid = pdb_get_user_rid(sam_pass);
/* it's outaa here! 8^) */
- if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
- DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
- DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
- tdb_close(pwd_tdb);
- return nt_status;
- }
- /* delete also the RID key */
+ if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
+ DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
+ DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
/* set the search key */
+
slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
/* it's outaa here! 8^) */
- if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
+
+ if ( tdb_delete(tdbsam, key) != TDB_SUCCESS ) {
DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
- DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
- tdb_close(pwd_tdb);
- return nt_status;
+ DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam)));
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
}
+
+ nt_status = NT_STATUS_OK;
- tdb_close(pwd_tdb);
+ done:
+ tdbsam_close();
- return NT_STATUS_OK;
+ return nt_status;
}
/***************************************************************************
Update the TDB SAM account record only
+ Assumes that the tdbsam is already open
****************************************************************************/
-static BOOL tdb_update_samacct_only(TDB_CONTEXT *pwd_tdb,
- struct pdb_methods *my_methods,
- SAM_ACCOUNT* newpwd, int flag)
+static BOOL tdb_update_samacct_only( struct samu* newpwd, int flag )
{
TDB_DATA key, data;
uint8 *buf = NULL;
@@ -615,9 +1223,10 @@ static BOOL tdb_update_samacct_only(TDB_CONTEXT *pwd_tdb,
fstring name;
BOOL ret = True;
- /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
- if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) {
- DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
+ /* copy the struct samu struct into a BYTE buffer for storage */
+
+ if ( (data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1 ) {
+ DEBUG(0,("tdb_update_sam: ERROR - Unable to copy struct samu info BYTE buffer!\n"));
ret = False;
goto done;
}
@@ -636,9 +1245,10 @@ static BOOL tdb_update_samacct_only(TDB_CONTEXT *pwd_tdb,
key.dsize = strlen(keystr) + 1;
/* add the account */
- if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
+
+ if ( tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS ) {
DEBUG(0, ("Unable to modify passwd TDB!"));
- DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam)));
DEBUGADD(0, (" occured while storing the main record (%s)\n",
keystr));
ret = False;
@@ -649,15 +1259,14 @@ done:
/* cleanup */
SAFE_FREE(buf);
- return (ret);
+ return ret;
}
/***************************************************************************
Update the TDB SAM RID record only
+ Assumes that the tdbsam is already open
****************************************************************************/
-static BOOL tdb_update_ridrec_only(TDB_CONTEXT *pwd_tdb,
- struct pdb_methods *my_methods,
- SAM_ACCOUNT* newpwd, int flag)
+static BOOL tdb_update_ridrec_only( struct samu* newpwd, int flag )
{
TDB_DATA key, data;
fstring keystr;
@@ -671,15 +1280,14 @@ static BOOL tdb_update_ridrec_only(TDB_CONTEXT *pwd_tdb,
data.dptr = name;
/* setup the RID index key */
- slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
- pdb_get_user_rid(newpwd));
+ slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
/* add the reference */
- if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
+ if (tdb_store(tdbsam, key, data, flag) != TDB_SUCCESS) {
DEBUG(0, ("Unable to modify TDB passwd !"));
- DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" Error: %s\n", tdb_errorstr(tdbsam)));
DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
return False;
}
@@ -692,82 +1300,72 @@ static BOOL tdb_update_ridrec_only(TDB_CONTEXT *pwd_tdb,
Update the TDB SAM
****************************************************************************/
-static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
+static BOOL tdb_update_sam(struct pdb_methods *my_methods, struct samu* newpwd, int flag)
{
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- TDB_CONTEXT *pwd_tdb = NULL;
- BOOL ret = True;
uint32 user_rid;
+ BOOL result = True;
/* invalidate the existing TDB iterator if it is open */
- if (tdb_state->passwd_tdb) {
- tdb_close(tdb_state->passwd_tdb);
- tdb_state->passwd_tdb = NULL;
- }
-
- /* open the account TDB passwd*/
-
- pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
+ tdbsam_endsampwent( my_methods );
- if (!pwd_tdb) {
- DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
- tdb_state->tdbsam_location));
+#if 0
+ if ( !pdb_get_group_rid(newpwd) ) {
+ DEBUG (0,("tdb_update_sam: Failing to store a struct samu for [%s] "
+ "without a primary group RID\n", pdb_get_username(newpwd)));
return False;
}
-
- if (!pdb_get_group_rid(newpwd)) {
- DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
- pdb_get_username(newpwd)));
- ret = False;
- goto done;
- }
+#endif
if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
- DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd)));
- ret = False;
- goto done;
+ DEBUG(0,("tdb_update_sam: struct samu (%s) with no RID!\n", pdb_get_username(newpwd)));
+ return False;
}
- if (!tdb_update_samacct_only(pwd_tdb, my_methods, newpwd, flag) ||
- !tdb_update_ridrec_only(pwd_tdb, my_methods, newpwd, flag)) {
- ret = False;
- goto done;
+ /* open the database */
+
+ if ( !tdbsam_open( tdbsam_filename ) ) {
+ DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
+ return False;
+ }
+
+ if ( !tdb_update_samacct_only(newpwd, flag) || !tdb_update_ridrec_only(newpwd, flag)) {
+ result = False;
}
-done:
/* cleanup */
- tdb_close (pwd_tdb);
+
+ tdbsam_close();
- return (ret);
+ return result;
}
/***************************************************************************
- Modifies an existing SAM_ACCOUNT
+ Modifies an existing struct samu
****************************************************************************/
-static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
+static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
{
- if (tdb_update_sam(my_methods, newpwd, TDB_MODIFY))
- return NT_STATUS_OK;
- else
+ if ( !tdb_update_sam(my_methods, newpwd, TDB_MODIFY) )
return NT_STATUS_UNSUCCESSFUL;
+
+ return NT_STATUS_OK;
}
/***************************************************************************
- Adds an existing SAM_ACCOUNT
+ Adds an existing struct samu
****************************************************************************/
-static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
+static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, struct samu *newpwd)
{
- if (tdb_update_sam(my_methods, newpwd, TDB_INSERT))
- return NT_STATUS_OK;
- else
+ if ( !tdb_update_sam(my_methods, newpwd, TDB_INSERT) )
return NT_STATUS_UNSUCCESSFUL;
+
+ return NT_STATUS_OK;
}
/***************************************************************************
- Renames a SAM_ACCOUNT
+ Renames a struct samu
- check for the posix user/rename user script
- Add and lock the new user record
- rename the posix user
@@ -776,123 +1374,202 @@ static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCO
- unlock the new user record
***************************************************************************/
static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
- SAM_ACCOUNT *old_acct,
+ struct samu *old_acct,
const char *newname)
{
- struct tdbsam_privates *tdb_state =
- (struct tdbsam_privates *)my_methods->private_data;
- SAM_ACCOUNT *new_acct = NULL;
- pstring rename_script;
- TDB_CONTEXT *pwd_tdb = NULL;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- BOOL interim_account = False;
-
- if (!*(lp_renameuser_script()))
- goto done;
+ struct samu *new_acct = NULL;
+ pstring rename_script;
+ BOOL interim_account = False;
+ int rename_ret;
- if (!pdb_copy_sam_account(old_acct, &new_acct) ||
- !pdb_set_username(new_acct, newname, PDB_CHANGED))
- goto done;
-
- /* invalidate the existing TDB iterator if it is open */
+ /* can't do anything without an external script */
- if (tdb_state->passwd_tdb) {
- tdb_close(tdb_state->passwd_tdb);
- tdb_state->passwd_tdb = NULL;
+ pstrcpy(rename_script, lp_renameuser_script() );
+ if ( ! *rename_script ) {
+ return NT_STATUS_ACCESS_DENIED;
}
- /* open the account TDB passwd */
+ /* invalidate the existing TDB iterator if it is open */
- pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
+ tdbsam_endsampwent( my_methods );
+
+ if ( !(new_acct = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
- if (!pwd_tdb) {
- DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
- tdb_state->tdbsam_location));
- goto done;
+ if ( !pdb_copy_sam_account(new_acct, old_acct)
+ || !pdb_set_username(new_acct, newname, PDB_CHANGED))
+ {
+ TALLOC_FREE(new_acct );
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* open the database */
+
+ if ( !tdbsam_open( tdbsam_filename ) ) {
+ DEBUG(0,("tdbsam_getsampwnam: failed to open %s!\n", tdbsam_filename));
+ TALLOC_FREE(new_acct );
+ return NT_STATUS_ACCESS_DENIED;
}
/* add the new account and lock it */
- if (!tdb_update_samacct_only(pwd_tdb, my_methods, new_acct,
- TDB_INSERT))
+
+ if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
goto done;
+ }
+
interim_account = True;
- if (tdb_lock_bystring(pwd_tdb, newname, 30) == -1) {
+ if ( tdb_lock_bystring_with_timeout(tdbsam, newname, 30) == -1 ) {
goto done;
}
/* rename the posix user */
- pstrcpy(rename_script, lp_renameuser_script());
-
- if (*rename_script) {
- int rename_ret;
-
- pstring_sub(rename_script, "%unew", newname);
- pstring_sub(rename_script, "%uold",
- pdb_get_username(old_acct));
- rename_ret = smbrun(rename_script, NULL);
+ string_sub2(rename_script, "%unew", newname, sizeof(pstring),
+ True, False, True);
+ string_sub2(rename_script, "%uold", pdb_get_username(old_acct),
+ sizeof(pstring), True, False, True);
+ rename_ret = smbrun(rename_script, NULL);
- DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
+ DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
- if (rename_ret)
- goto done;
- } else {
- goto done;
+ if (rename_ret) {
+ goto done;
}
/* rewrite the rid->username record */
- if (!tdb_update_ridrec_only(pwd_tdb, my_methods, new_acct, TDB_MODIFY))
+
+ if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
goto done;
+ }
interim_account = False;
- tdb_unlock_bystring(pwd_tdb, newname);
-
- tdb_delete_samacct_only(pwd_tdb, my_methods, old_acct);
-
- ret = NT_STATUS_OK;
+ tdb_unlock_bystring( tdbsam, newname );
+ tdb_delete_samacct_only( old_acct );
+
+ tdbsam_close();
+
+ TALLOC_FREE(new_acct );
+ return NT_STATUS_OK;
done:
/* cleanup */
if (interim_account) {
- tdb_unlock_bystring(pwd_tdb, newname);
- tdb_delete_samacct_only(pwd_tdb, my_methods, new_acct);
+ tdb_unlock_bystring(tdbsam, newname);
+ tdb_delete_samacct_only(new_acct);
}
- if (pwd_tdb)
- tdb_close (pwd_tdb);
+
+ tdbsam_close();
+
if (new_acct)
- pdb_free_sam(&new_acct);
+ TALLOC_FREE(new_acct);
- return (ret);
+ return NT_STATUS_ACCESS_DENIED;
}
-
-static void free_private_data(void **vp)
+
+static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
{
- struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
- tdbsam_tdbclose(*tdb_state);
- *tdb_state = NULL;
+ return False;
+}
+
+/*
+ * Historically, winbind was responsible for allocating RIDs, so the next RID
+ * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
+ * but for compatibility reasons we still keep the the next RID counter in
+ * winbindd_idmap.tdb.
+ */
+
+/*****************************************************************************
+ Initialise idmap database. For now (Dec 2005) this is a copy of the code in
+ sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
+ winbind completely and store the RID counter in passdb.tdb.
- /* No need to free any further, as it is talloc()ed */
+ Dont' fully initialize with the HWM values, if it's new, we're only
+ interested in the RID counter.
+*****************************************************************************/
+
+static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
+{
+ int32 version;
+
+ if (tdb_lock_bystring(tdb, "IDMAP_VERSION") != 0) {
+ DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
+ return False;
+ }
+
+ version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
+
+ if (version == -1) {
+ /* No key found, must be a new db */
+ if (tdb_store_int32(tdb, "IDMAP_VERSION",
+ IDMAP_VERSION) != 0) {
+ DEBUG(0, ("Could not store IDMAP_VERSION\n"));
+ tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+ return False;
+ }
+ version = IDMAP_VERSION;
+ }
+
+ if (version != IDMAP_VERSION) {
+ DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
+ "start winbind once\n", IDMAP_VERSION, version));
+ tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+ return False;
+ }
+
+ tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+ return True;
}
+static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
+{
+ TDB_CONTEXT *tdb;
+ uint32 rid;
+ BOOL ret = False;
+
+ tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
+ TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
+ if (tdb == NULL) {
+ DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
+ goto done;
+ }
+ if (!init_idmap_tdb(tdb)) {
+ DEBUG(1, ("Could not init idmap\n"));
+ goto done;
+ }
-/**
- * Init tdbsam backend
- *
- * @param pdb_context initialised passdb context
- * @param pdb_method backend methods structure to be filled with function pointers
- * @param location the backend tdb file location
- *
- * @return nt_status code
- **/
+ rid = BASE_RID; /* Default if not set */
-static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+ if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
+ DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
+ goto done;
+ }
+
+ *prid = rid;
+ ret = True;
+
+ done:
+ if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
+ smb_panic("tdb_close(idmap_tdb) failed\n");
+ }
+
+ return ret;
+}
+
+/*********************************************************************
+ Initialize the tdb sam backend. Setup the dispath table of methods,
+ open the tdb, etc...
+*********************************************************************/
+
+static NTSTATUS pdb_init_tdbsam(struct pdb_methods **pdb_method, const char *location)
{
NTSTATUS nt_status;
- struct tdbsam_privates *tdb_state;
+ pstring tdbfile;
+ const char *pfile = location;
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
return nt_status;
}
@@ -908,26 +1585,21 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
(*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
(*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
- tdb_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct tdbsam_privates);
-
- if (!tdb_state) {
- DEBUG(0, ("talloc() failed for tdbsam private_data!\n"));
- return NT_STATUS_NO_MEMORY;
- }
+ (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
+ (*pdb_method)->new_rid = tdbsam_new_rid;
- if (location) {
- tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location);
- } else {
- pstring tdbfile;
- get_private_directory(tdbfile);
- pstrcat(tdbfile, "/");
- pstrcat(tdbfile, PASSDB_FILE_NAME);
- tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
+ /* save the path for later */
+
+ if ( !location ) {
+ pstr_sprintf( tdbfile, "%s/%s", lp_private_dir(), PASSDB_FILE_NAME );
+ pfile = tdbfile;
}
+ pstrcpy( tdbsam_filename, pfile );
- (*pdb_method)->private_data = tdb_state;
-
- (*pdb_method)->free_private_data = free_private_data;
+ /* no private data */
+
+ (*pdb_method)->private_data = NULL;
+ (*pdb_method)->free_private_data = NULL;
return NT_STATUS_OK;
}
diff --git a/source/passdb/pdb_xml.c b/source/passdb/pdb_xml.c
deleted file mode 100644
index d40a5731a43..00000000000
--- a/source/passdb/pdb_xml.c
+++ /dev/null
@@ -1,580 +0,0 @@
-
-/*
- * XML password backend for samba
- * Copyright (C) Jelmer Vernooij 2002
- * Some parts based on the libxml gjobread example by Daniel Veillard
- *
- * This 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.
- */
-
-/* FIXME:
- * - Support stdin input by using '-'
- * - Be faster. Don't rewrite the whole file when adding a user, but store it in the memory and save it when exiting. Requires changes to samba source.
- * - Gives the ability to read/write to standard input/output
- * - Do locking!
- * - Better names!
- */
-
-
-#define XML_URL "http://samba.org/samba/DTD/passdb"
-
-#include "includes.h"
-
-#include <libxml/xmlmemory.h>
-#include <libxml/parser.h>
-
-static int xmlsam_debug_level = DBGC_ALL;
-
-#undef DBGC_CLASS
-#define DBGC_CLASS xmlsam_debug_level
-
-
-/* Helper utilities for charset conversion */
-static xmlNodePtr smbXmlNewChild(xmlNodePtr prnt, xmlNsPtr ns, const xmlChar *name, const char *content)
-{
- char *string_utf8;
- xmlNodePtr ret;
-
- if(!content) return xmlNewChild(prnt, ns, name, NULL);
-
-
- if(push_utf8_allocate(&string_utf8,content) == (size_t)-1)
- return NULL;
-
- ret = xmlNewTextChild(prnt, ns, name, string_utf8);
-
- SAFE_FREE(string_utf8);
-
- return ret;
-}
-
-
-static char * iota(int a) {
- static char tmp[10];
-
- snprintf(tmp, 9, "%d", a);
- return tmp;
-}
-
-static BOOL parsePass(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, SAM_ACCOUNT * u)
-{
- pstring temp;
-
- cur = cur->xmlChildrenNode;
- while (cur != NULL) {
- if (strcmp(cur->name, "crypt"))
- DEBUG(0, ("Unknown element %s\n", cur->name));
- else {
- if (!strcmp(xmlGetProp(cur, "type"), "nt")
- &&
- pdb_gethexpwd(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1), temp))
- pdb_set_nt_passwd(u, temp, PDB_SET);
- else if (!strcmp(xmlGetProp(cur, "type"), "lanman")
- &&
- pdb_gethexpwd(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1), temp))
- pdb_set_lanman_passwd(u, temp, PDB_SET);
- else
- DEBUG(0,
- ("Unknown crypt type: %s\n",
- xmlGetProp(cur, "type")));
- }
- cur = cur->next;
- }
- return True;
-}
-
-static BOOL parseUser(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, SAM_ACCOUNT * u)
-{
- char *tmp;
- DOM_SID sid;
-
- tmp = xmlGetProp(cur, "sid");
- if (tmp){
- string_to_sid(&sid, tmp);
- pdb_set_user_sid(u, &sid, PDB_SET);
- }
- pdb_set_username(u, xmlGetProp(cur, "name"), PDB_SET);
- /* We don't care what the top level element name is */
- cur = cur->xmlChildrenNode;
- while (cur != NULL) {
- if ((!strcmp(cur->name, "group")) && (cur->ns == ns)) {
- tmp = xmlGetProp(cur, "sid");
- if (tmp){
- string_to_sid(&sid, tmp);
- pdb_set_group_sid(u, &sid, PDB_SET);
- }
- }
-
- else if ((!strcmp(cur->name, "domain")) && (cur->ns == ns))
- pdb_set_domain(u,
- xmlNodeListGetString(doc, cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "fullname") && cur->ns == ns)
- pdb_set_fullname(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "nt_username") && cur->ns == ns)
- pdb_set_nt_username(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "logon_script") && cur->ns == ns)
- pdb_set_logon_script(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "profile_path") && cur->ns == ns)
- pdb_set_profile_path(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "logon_time") && cur->ns == ns)
- pdb_set_logon_time(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "logoff_time") && cur->ns == ns)
- pdb_set_logoff_time(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)),
- PDB_SET);
-
- else if (!strcmp(cur->name, "kickoff_time") && cur->ns == ns)
- pdb_set_kickoff_time(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)),
- PDB_SET);
-
- else if (!strcmp(cur->name, "logon_divs") && cur->ns == ns)
- pdb_set_logon_divs(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "hours_len") && cur->ns == ns)
- pdb_set_hours_len(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "bad_password_count") && cur->ns == ns)
- pdb_set_bad_password_count(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "logon_count") && cur->ns == ns)
- pdb_set_logon_count(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "unknown_6") && cur->ns == ns)
- pdb_set_unknown_6(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "homedir") && cur->ns == ns)
- pdb_set_homedir(u,
- xmlNodeListGetString(doc, cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "unknown_str") && cur->ns == ns)
- pdb_set_unknown_str(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "dir_drive") && cur->ns == ns)
- pdb_set_dir_drive(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "munged_dial") && cur->ns == ns)
- pdb_set_munged_dial(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "acct_desc") && cur->ns == ns)
- pdb_set_acct_desc(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if (!strcmp(cur->name, "acct_ctrl") && cur->ns == ns)
- pdb_set_acct_ctrl(u,
- atol(xmlNodeListGetString
- (doc, cur->xmlChildrenNode, 1)), PDB_SET);
-
- else if (!strcmp(cur->name, "workstations") && cur->ns == ns)
- pdb_set_workstations(u,
- xmlNodeListGetString(doc,
- cur->xmlChildrenNode,
- 1), PDB_SET);
-
- else if ((!strcmp(cur->name, "password")) && (cur->ns == ns)) {
- tmp = xmlGetProp(cur, "last_set");
- if (tmp)
- pdb_set_pass_last_set_time(u, atol(tmp), PDB_SET);
- tmp = xmlGetProp(cur, "must_change");
- if (tmp)
- pdb_set_pass_must_change_time(u, atol(tmp), PDB_SET);
- tmp = xmlGetProp(cur, "can_change");
- if (tmp)
- pdb_set_pass_can_change_time(u, atol(tmp), PDB_SET);
- parsePass(doc, ns, cur, u);
- }
-
- else
- DEBUG(0, ("Unknown element %s\n", cur->name));
- cur = cur->next;
- }
-
- return True;
-}
-
-typedef struct pdb_xml {
- char *location;
- char written;
- xmlDocPtr doc;
- xmlNodePtr users;
- xmlNodePtr pwent;
- xmlNsPtr ns;
-} pdb_xml;
-
-static xmlNodePtr parseSambaXMLFile(struct pdb_xml *data)
-{
- xmlNodePtr cur;
-
- data->doc = xmlParseFile(data->location);
- if (data->doc == NULL)
- return NULL;
-
- cur = xmlDocGetRootElement(data->doc);
- if (!cur) {
- DEBUG(0, ("empty document\n"));
- xmlFreeDoc(data->doc);
- return NULL;
- }
- data->ns = xmlSearchNsByHref(data->doc, cur, XML_URL);
- if (!data->ns) {
- DEBUG(0,
- ("document of the wrong type, samba user namespace not found\n"));
- xmlFreeDoc(data->doc);
- return NULL;
- }
- if (strcmp(cur->name, "samba")) {
- DEBUG(0, ("document of the wrong type, root node != samba"));
- xmlFreeDoc(data->doc);
- return NULL;
- }
-
- cur = cur->xmlChildrenNode;
- while (cur && xmlIsBlankNode(cur)) {
- cur = cur->next;
- }
- if (!cur)
- return NULL;
- if ((strcmp(cur->name, "users")) || (cur->ns != data->ns)) {
- DEBUG(0, ("document of the wrong type, was '%s', users expected",
- cur->name));
- DEBUG(0, ("xmlDocDump follows\n"));
- xmlDocDump(stderr, data->doc);
- DEBUG(0, ("xmlDocDump finished\n"));
- xmlFreeDoc(data->doc);
- return NULL;
- }
- data->users = cur;
- cur = cur->xmlChildrenNode;
- return cur;
-}
-
-static NTSTATUS xmlsam_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask)
-{
- pdb_xml *data;
-
- if (!methods) {
- DEBUG(0, ("Invalid methods\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- data = (pdb_xml *) methods->private_data;
- if (!data) {
- DEBUG(0, ("Invalid pdb_xml_data\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- data->pwent = parseSambaXMLFile(data);
- if (!data->pwent)
- return NT_STATUS_UNSUCCESSFUL;
-
- return NT_STATUS_OK;
-}
-
-/***************************************************************
- End enumeration of the passwd list.
- ****************************************************************/
-
-static void xmlsam_endsampwent(struct pdb_methods *methods)
-{
- pdb_xml *data;
-
- if (!methods) {
- DEBUG(0, ("Invalid methods\n"));
- return;
- }
-
- data = (pdb_xml *) methods->private_data;
-
- if (!data) {
- DEBUG(0, ("Invalid pdb_xml_data\n"));
- return;
- }
-
- xmlFreeDoc(data->doc);
- data->doc = NULL;
- data->pwent = NULL;
-}
-
-/*****************************************************************
- Get one SAM_ACCOUNT from the list (next in line)
- *****************************************************************/
-
-static NTSTATUS xmlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user)
-{
- pdb_xml *data;
-
- if (!methods) {
- DEBUG(0, ("Invalid methods\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- data = (pdb_xml *) methods->private_data;
-
- if (!data) {
- DEBUG(0, ("Invalid pdb_xml_data\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- while (data->pwent) {
- if ((!strcmp(data->pwent->name, "user")) &&
- (data->pwent->ns == data->ns)) {
-
- parseUser(data->doc, data->ns, data->pwent, user);
- data->pwent = data->pwent->next;
- return NT_STATUS_OK;
- }
- data->pwent = data->pwent->next;
- }
- return NT_STATUS_UNSUCCESSFUL;
-}
-
-/***************************************************************************
- Adds an existing SAM_ACCOUNT
- ****************************************************************************/
-
-static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * u)
-{
- pstring temp;
- fstring sid_str;
- xmlNodePtr cur, user, pass, root;
- pdb_xml *data;
-
- DEBUG(10, ("xmlsam_add_sam_account called!\n"));
-
- if (!methods) {
- DEBUG(0, ("Invalid methods\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- data = (pdb_xml *) methods->private_data;
- if (!data) {
- DEBUG(0, ("Invalid pdb_xml_data\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* Create a new document if we can't open the current one */
- if (!parseSambaXMLFile(data)) {
- DEBUG(0, ("Can't load current XML file, creating a new one\n"));
- data->doc = xmlNewDoc(XML_DEFAULT_VERSION);
- root = xmlNewDocNode(data->doc, NULL, "samba", NULL);
- cur = xmlDocSetRootElement(data->doc, root);
- data->ns = xmlNewNs(root, XML_URL, "samba");
- data->users = smbXmlNewChild(root, data->ns, "users", NULL);
- }
-
- user = smbXmlNewChild(data->users, data->ns, "user", NULL);
- xmlNewProp(user, "sid",
- sid_to_string(sid_str, pdb_get_user_sid(u)));
-
- if (pdb_get_username(u) && strcmp(pdb_get_username(u), ""))
- xmlNewProp(user, "name", pdb_get_username(u));
-
- cur = smbXmlNewChild(user, data->ns, "group", NULL);
-
- xmlNewProp(cur, "sid",
- sid_to_string(sid_str, pdb_get_group_sid(u)));
-
- if (pdb_get_init_flags(u, PDB_LOGONTIME) != PDB_DEFAULT)
- smbXmlNewChild(user, data->ns, "logon_time",
- iota(pdb_get_logon_time(u)));
-
- if (pdb_get_init_flags(u, PDB_LOGOFFTIME) != PDB_DEFAULT)
- smbXmlNewChild(user, data->ns, "logoff_time",
- iota(pdb_get_logoff_time(u)));
-
- if (pdb_get_init_flags(u, PDB_KICKOFFTIME) != PDB_DEFAULT)
- smbXmlNewChild(user, data->ns, "kickoff_time",
- iota(pdb_get_kickoff_time(u)));
-
- if (pdb_get_domain(u) && strcmp(pdb_get_domain(u), ""))
- smbXmlNewChild(user, data->ns, "domain", pdb_get_domain(u));
-
- if (pdb_get_nt_username(u) && strcmp(pdb_get_nt_username(u), ""))
- smbXmlNewChild(user, data->ns, "nt_username", pdb_get_nt_username(u));
-
- if (pdb_get_fullname(u) && strcmp(pdb_get_fullname(u), ""))
- smbXmlNewChild(user, data->ns, "fullname", pdb_get_fullname(u));
-
- if (pdb_get_homedir(u) && strcmp(pdb_get_homedir(u), ""))
- smbXmlNewChild(user, data->ns, "homedir", pdb_get_homedir(u));
-
- if (pdb_get_dir_drive(u) && strcmp(pdb_get_dir_drive(u), ""))
- smbXmlNewChild(user, data->ns, "dir_drive", pdb_get_dir_drive(u));
-
- if (pdb_get_logon_script(u) && strcmp(pdb_get_logon_script(u), ""))
- smbXmlNewChild(user, data->ns, "logon_script",
- pdb_get_logon_script(u));
-
- if (pdb_get_profile_path(u) && strcmp(pdb_get_profile_path(u), ""))
- smbXmlNewChild(user, data->ns, "profile_path",
- pdb_get_profile_path(u));
-
- if (pdb_get_acct_desc(u) && strcmp(pdb_get_acct_desc(u), ""))
- smbXmlNewChild(user, data->ns, "acct_desc", pdb_get_acct_desc(u));
-
- if (pdb_get_workstations(u) && strcmp(pdb_get_workstations(u), ""))
- smbXmlNewChild(user, data->ns, "workstations",
- pdb_get_workstations(u));
-
- if (pdb_get_unknown_str(u) && strcmp(pdb_get_unknown_str(u), ""))
- smbXmlNewChild(user, data->ns, "unknown_str", pdb_get_unknown_str(u));
-
- if (pdb_get_munged_dial(u) && strcmp(pdb_get_munged_dial(u), ""))
- smbXmlNewChild(user, data->ns, "munged_dial", pdb_get_munged_dial(u));
-
-
- /* Password stuff */
- pass = smbXmlNewChild(user, data->ns, "password", NULL);
- if (pdb_get_pass_last_set_time(u))
- xmlNewProp(pass, "last_set", iota(pdb_get_pass_last_set_time(u)));
- if (pdb_get_init_flags(u, PDB_CANCHANGETIME) != PDB_DEFAULT)
- xmlNewProp(pass, "can_change",
- iota(pdb_get_pass_can_change_time(u)));
-
- if (pdb_get_init_flags(u, PDB_MUSTCHANGETIME) != PDB_DEFAULT)
- xmlNewProp(pass, "must_change",
- iota(pdb_get_pass_must_change_time(u)));
-
-
- if (pdb_get_lanman_passwd(u)) {
- pdb_sethexpwd(temp, pdb_get_lanman_passwd(u),
- pdb_get_acct_ctrl(u));
- cur = smbXmlNewChild(pass, data->ns, "crypt", temp);
- xmlNewProp(cur, "type", "lanman");
- }
-
- if (pdb_get_nt_passwd(u)) {
- pdb_sethexpwd(temp, pdb_get_nt_passwd(u), pdb_get_acct_ctrl(u));
- cur = smbXmlNewChild(pass, data->ns, "crypt", temp);
- xmlNewProp(cur, "type", "nt");
- }
-
- smbXmlNewChild(user, data->ns, "acct_ctrl", iota(pdb_get_acct_ctrl(u)));
-
- if (pdb_get_logon_divs(u))
- smbXmlNewChild(user, data->ns, "logon_divs",
- iota(pdb_get_logon_divs(u)));
-
- if (pdb_get_hours_len(u))
- smbXmlNewChild(user, data->ns, "hours_len",
- iota(pdb_get_hours_len(u)));
-
- smbXmlNewChild(user, data->ns, "bad_password_count", iota(pdb_get_bad_password_count(u)));
- smbXmlNewChild(user, data->ns, "logon_count", iota(pdb_get_logon_count(u)));
- smbXmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u)));
- xmlSaveFile(data->location, data->doc);
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method,
- const char *location)
-{
- NTSTATUS nt_status;
- pdb_xml *data;
-
- xmlsam_debug_level = debug_add_class("xmlsam");
- if (xmlsam_debug_level == -1) {
- xmlsam_debug_level = DBGC_ALL;
- DEBUG(0, ("xmlsam: Couldn't register custom debugging class!\n"));
- }
-
- if (!pdb_context) {
- DEBUG(0, ("invalid pdb_methods specified\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!NT_STATUS_IS_OK
- (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
- return nt_status;
- }
-
- (*pdb_method)->name = "xmlsam";
-
- (*pdb_method)->setsampwent = xmlsam_setsampwent;
- (*pdb_method)->endsampwent = xmlsam_endsampwent;
- (*pdb_method)->getsampwent = xmlsam_getsampwent;
- (*pdb_method)->add_sam_account = xmlsam_add_sam_account;
- (*pdb_method)->getsampwnam = NULL;
- (*pdb_method)->getsampwsid = NULL;
- (*pdb_method)->update_sam_account = NULL;
- (*pdb_method)->delete_sam_account = NULL;
- (*pdb_method)->getgrsid = NULL;
- (*pdb_method)->getgrgid = NULL;
- (*pdb_method)->getgrnam = NULL;
- (*pdb_method)->add_group_mapping_entry = NULL;
- (*pdb_method)->update_group_mapping_entry = NULL;
- (*pdb_method)->delete_group_mapping_entry = NULL;
- (*pdb_method)->enum_group_mapping = NULL;
-
- data = _talloc(pdb_context->mem_ctx, sizeof(pdb_xml));
- data->location = talloc_strdup(pdb_context->mem_ctx, (location ? location : "passdb.xml"));
- data->pwent = NULL;
- data->written = 0;
- (*pdb_method)->private_data = data;
-
- LIBXML_TEST_VERSION xmlKeepBlanksDefault(0);
-
- return NT_STATUS_OK;
-}
-
-NTSTATUS pdb_xml_init(void)
-{
- return smb_register_passdb(PASSDB_INTERFACE_VERSION, "xml", xmlsam_init);
-}
diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c
index 14896a33400..32793dea586 100644
--- a/source/passdb/secrets.c
+++ b/source/passdb/secrets.c
@@ -177,13 +177,16 @@ BOOL secrets_fetch_domain_guid(const char *domain, struct uuid *guid)
strupper_m(key);
dyn_guid = (struct uuid *)secrets_fetch(key, &size);
- if ((!dyn_guid) && (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);
- if (dyn_guid == NULL)
+ 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);
+ }
+ if (dyn_guid == NULL) {
return False;
+ }
}
if (size != sizeof(struct uuid)) {
@@ -242,7 +245,7 @@ BOOL secrets_lock_trust_account_password(const char *domain, BOOL dolock)
return False;
if (dolock)
- return (tdb_lock_bystring(tdb, trust_keystr(domain),0) == 0);
+ return (tdb_lock_bystring(tdb, trust_keystr(domain)) == 0);
else
tdb_unlock_bystring(tdb, trust_keystr(domain));
return True;
@@ -388,10 +391,11 @@ BOOL secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16])
* @return true if succeeded
**/
-BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_dom_name,
- size_t uni_name_len, const char* pwd,
- DOM_SID sid)
-{
+BOOL secrets_store_trusted_domain_password(const char* domain, const char* pwd,
+ const DOM_SID *sid)
+{
+ smb_ucs2_t *uni_dom_name;
+
/* packing structures */
pstring pass_buf;
int pass_len = 0;
@@ -399,13 +403,16 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
struct trusted_dom_pass pass;
ZERO_STRUCT(pass);
-
- /* unicode domain name and its length */
- if (!uni_dom_name)
+
+ if (push_ucs2_allocate(&uni_dom_name, domain) < 0) {
+ DEBUG(0, ("Could not convert domain name %s to unicode\n",
+ domain));
return False;
-
+ }
+
strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
- pass.uni_name_len = uni_name_len;
+ pass.uni_name_len = strlen_w(uni_dom_name)+1;
+ SAFE_FREE(uni_dom_name);
/* last change time */
pass.mod_time = time(NULL);
@@ -415,7 +422,7 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
fstrcpy(pass.pass, pwd);
/* domain sid */
- sid_copy(&pass.domain_sid, &sid);
+ sid_copy(&pass.domain_sid, sid);
pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_buf_len, &pass);
@@ -658,138 +665,101 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
/**
* Get trusted domains info from secrets.tdb.
- *
- * The linked list is allocated on the supplied talloc context, caller gets to destroy
- * when done.
- *
- * @param ctx Allocation context
- * @param enum_ctx Starting index, eg. we can start fetching at third
- * or sixth trusted domain entry. Zero is the first index.
- * Value it is set to is the enum context for the next enumeration.
- * @param num_domains Number of domain entries to fetch at one call
- * @param domains Pointer to array of trusted domain structs to be filled up
- *
- * @return nt status code of rpc response
**/
-NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
- int *num_domains, TRUSTDOM ***domains)
+NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
+ struct trustdom_info ***domains)
{
TDB_LIST_NODE *keys, *k;
- TRUSTDOM *dom = NULL;
char *pattern;
- unsigned int start_idx;
- uint32 idx = 0;
- size_t size = 0, packed_size = 0;
- fstring dom_name;
- char *packed_pass;
- struct trusted_dom_pass *pass = TALLOC_ZERO_P(ctx, struct trusted_dom_pass);
- NTSTATUS status;
if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
- if (!pass) {
- DEBUG(0, ("talloc_zero failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- *num_domains = 0;
- start_idx = *enum_ctx;
-
/* generate searching pattern */
- if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
- DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
+ pattern = talloc_asprintf(mem_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
+ if (pattern == NULL) {
+ DEBUG(0, ("secrets_trusted_domains: talloc_asprintf() "
+ "failed!\n"));
return NT_STATUS_NO_MEMORY;
}
- DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n",
- max_num_domains, *enum_ctx));
-
- *domains = TALLOC_ZERO_ARRAY(ctx, TRUSTDOM *, max_num_domains);
+ *domains = NULL;
+ *num_domains = 0;
/* fetching trusted domains' data and collecting them in a list */
keys = tdb_search_keys(tdb, pattern);
- /*
- * if there's no keys returned ie. no trusted domain,
- * return "no more entries" code
- */
- status = NT_STATUS_NO_MORE_ENTRIES;
-
/* searching for keys in secrets db -- way to go ... */
for (k = keys; k; k = k->next) {
+ char *packed_pass;
+ size_t size = 0, packed_size = 0;
+ struct trusted_dom_pass pass;
char *secrets_key;
+ struct trustdom_info *dom_info;
/* important: ensure null-termination of the key string */
- secrets_key = SMB_STRNDUP(k->node_key.dptr, k->node_key.dsize);
+ secrets_key = talloc_strndup(mem_ctx,
+ k->node_key.dptr,
+ k->node_key.dsize);
if (!secrets_key) {
DEBUG(0, ("strndup failed!\n"));
+ tdb_search_list_free(keys);
return NT_STATUS_NO_MEMORY;
}
packed_pass = secrets_fetch(secrets_key, &size);
- packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
+ packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size,
+ &pass);
/* packed representation isn't needed anymore */
SAFE_FREE(packed_pass);
if (size != packed_size) {
- DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
+ DEBUG(2, ("Secrets record %s is invalid!\n",
+ secrets_key));
continue;
}
-
- pull_ucs2_fstring(dom_name, pass->uni_name);
- DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
- idx, dom_name, sid_string_static(&pass->domain_sid)));
-
- SAFE_FREE(secrets_key);
-
- if (idx >= start_idx && idx < start_idx + max_num_domains) {
- dom = TALLOC_ZERO_P(ctx, TRUSTDOM);
- if (!dom) {
- /* free returned tdb record */
- return NT_STATUS_NO_MEMORY;
- }
-
- /* copy domain sid */
- SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
- memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
-
- /* copy unicode domain name */
- dom->name = TALLOC_MEMDUP(ctx, pass->uni_name,
- (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t));
-
- (*domains)[idx - start_idx] = dom;
-
- DEBUG(18, ("Secret record is in required range.\n \
- start_idx = %d, max_num_domains = %d. Added to returned array.\n",
- start_idx, max_num_domains));
- *enum_ctx = idx + 1;
- (*num_domains)++;
-
- /* set proper status code to return */
- if (k->next) {
- /* there are yet some entries to enumerate */
- status = STATUS_MORE_ENTRIES;
- } else {
- /* this is the last entry in the whole enumeration */
- status = NT_STATUS_OK;
- }
- } else {
- DEBUG(18, ("Secret is outside the required range.\n \
- start_idx = %d, max_num_domains = %d. Not added to returned array\n",
- start_idx, max_num_domains));
+ if (pass.domain_sid.num_auths != 4) {
+ DEBUG(0, ("SID %s is not a domain sid, has %d "
+ "auths instead of 4\n",
+ sid_string_static(&pass.domain_sid),
+ pass.domain_sid.num_auths));
+ continue;
}
-
- idx++;
+
+ dom_info = TALLOC_P(mem_ctx, struct trustdom_info);
+ if (dom_info == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ tdb_search_list_free(keys);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (pull_ucs2_talloc(mem_ctx, &dom_info->name,
+ pass.uni_name) < 0) {
+ DEBUG(2, ("pull_ucs2_talloc failed\n"));
+ tdb_search_list_free(keys);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ sid_copy(&dom_info->sid, &pass.domain_sid);
+
+ ADD_TO_ARRAY(mem_ctx, struct trustdom_info *, dom_info,
+ domains, num_domains);
+
+ if (*domains == NULL) {
+ tdb_search_list_free(keys);
+ return NT_STATUS_NO_MEMORY;
+ }
+ talloc_steal(*domains, dom_info);
}
- DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains));
+ DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n",
+ *num_domains));
/* free the results of searching the keys */
tdb_search_list_free(keys);
- return status;
+ return NT_STATUS_OK;
}
/*******************************************************************************
@@ -804,7 +774,7 @@ BOOL secrets_named_mutex(const char *name, unsigned int timeout)
if (!secrets_init())
return False;
- ret = tdb_lock_bystring(tdb, name, timeout);
+ ret = tdb_lock_bystring_with_timeout(tdb, name, timeout);
if (ret == 0)
DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name ));
@@ -821,35 +791,6 @@ void secrets_named_mutex_release(const char *name)
DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
}
-/*********************************************************
- Check to see if we must talk to the PDC to avoid sam
- sync delays
- ********************************************************/
-
-BOOL must_use_pdc( const char *domain )
-{
- time_t now = time(NULL);
- time_t last_change_time;
- unsigned char passwd[16];
-
- if ( !secrets_fetch_trust_account_password(domain, passwd, &last_change_time, NULL) )
- return False;
-
- /*
- * If the time the machine password has changed
- * was less than about 15 minutes then we need to contact
- * the PDC only, as we cannot be sure domain replication
- * has yet taken place. Bug found by Gerald (way to go
- * Gerald !). JRA.
- */
-
- if ( now - last_change_time < SAM_SYNC_WINDOW )
- return True;
-
- return False;
-
-}
-
/*******************************************************************************
Store a complete AFS keyfile into secrets.tdb.
*******************************************************************************/
@@ -959,7 +900,7 @@ static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
if (!tdb_sc) {
DEBUG(0,("open_schannel_session_store: Failed to open %s\n", fname));
- talloc_free(fname);
+ TALLOC_FREE(fname);
return NULL;
}
@@ -987,7 +928,7 @@ static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
}
SAFE_FREE(vers.dptr);
- talloc_free(fname);
+ TALLOC_FREE(fname);
return tdb_sc;
}
@@ -997,13 +938,15 @@ static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx)
Note we must be root here.
*******************************************************************************/
-BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinfo *pdc)
+BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx,
+ const char *remote_machine,
+ const struct dcinfo *pdc)
{
TDB_CONTEXT *tdb_sc = NULL;
TDB_DATA value;
BOOL ret;
char *keystr = talloc_asprintf(mem_ctx, "%s/%s", SECRETS_SCHANNEL_STATE,
- pdc->remote_machine);
+ remote_machine);
if (!keystr) {
return False;
}
@@ -1016,7 +959,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinf
8, pdc->seed_chal.data,
8, pdc->clnt_chal.data,
8, pdc->srv_chal.data,
- 8, pdc->sess_key,
+ 16, pdc->sess_key,
16, pdc->mach_pw,
pdc->mach_acct,
pdc->remote_machine,
@@ -1024,7 +967,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinf
value.dptr = TALLOC(mem_ctx, value.dsize);
if (!value.dptr) {
- talloc_free(keystr);
+ TALLOC_FREE(keystr);
return False;
}
@@ -1033,7 +976,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinf
8, pdc->seed_chal.data,
8, pdc->clnt_chal.data,
8, pdc->srv_chal.data,
- 8, pdc->sess_key,
+ 16, pdc->sess_key,
16, pdc->mach_pw,
pdc->mach_acct,
pdc->remote_machine,
@@ -1041,8 +984,8 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinf
tdb_sc = open_schannel_session_store(mem_ctx);
if (!tdb_sc) {
- talloc_free(keystr);
- talloc_free(value.dptr);
+ TALLOC_FREE(keystr);
+ TALLOC_FREE(value.dptr);
return False;
}
@@ -1052,8 +995,8 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinf
keystr ));
tdb_close(tdb_sc);
- talloc_free(keystr);
- talloc_free(value.dptr);
+ TALLOC_FREE(keystr);
+ TALLOC_FREE(value.dptr);
return ret;
}
@@ -1064,7 +1007,7 @@ BOOL secrets_store_schannel_session_info(TALLOC_CTX *mem_ctx, const struct dcinf
BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
const char *remote_machine,
- struct dcinfo *pdc)
+ struct dcinfo **ppdc)
{
TDB_CONTEXT *tdb_sc = NULL;
TDB_DATA value;
@@ -1075,10 +1018,11 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
unsigned char *pmach_pw = NULL;
uint32 l1, l2, l3, l4, l5;
int ret;
+ struct dcinfo *pdc = NULL;
char *keystr = talloc_asprintf(mem_ctx, "%s/%s", SECRETS_SCHANNEL_STATE,
remote_machine);
- ZERO_STRUCTP(pdc);
+ *ppdc = NULL;
if (!keystr) {
return False;
@@ -1088,7 +1032,7 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
tdb_sc = open_schannel_session_store(mem_ctx);
if (!tdb_sc) {
- talloc_free(keystr);
+ TALLOC_FREE(keystr);
return False;
}
@@ -1102,6 +1046,8 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
tdb_close(tdb_sc);
+ pdc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
+
/* Retrieve the record. */
ret = tdb_unpack(value.dptr, value.dsize, "dBBBBBfff",
&pdc->sequence,
@@ -1114,29 +1060,31 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
&pdc->remote_machine,
&pdc->domain);
- if (ret == -1 || l1 != 8 || l2 != 8 || l3 != 8 || l4 != 8 || l5 != 16) {
- talloc_free(keystr);
+ if (ret == -1 || l1 != 8 || l2 != 8 || l3 != 8 || l4 != 16 || l5 != 16) {
+ /* Bad record - delete it. */
+ tdb_delete_bystring(tdb_sc, keystr);
+ TALLOC_FREE(keystr);
+ TALLOC_FREE(pdc);
SAFE_FREE(pseed_chal);
SAFE_FREE(pclnt_chal);
SAFE_FREE(psrv_chal);
SAFE_FREE(psess_key);
SAFE_FREE(pmach_pw);
SAFE_FREE(value.dptr);
- ZERO_STRUCTP(pdc);
return False;
}
memcpy(pdc->seed_chal.data, pseed_chal, 8);
memcpy(pdc->clnt_chal.data, pclnt_chal, 8);
memcpy(pdc->srv_chal.data, psrv_chal, 8);
- memcpy(pdc->sess_key, psess_key, 8);
+ memcpy(pdc->sess_key, psess_key, 16);
memcpy(pdc->mach_pw, pmach_pw, 16);
/* We know these are true so didn't bother to store them. */
pdc->challenge_sent = True;
pdc->authenticated = True;
- DEBUG(3,("secrets_store_schannel_session_info: restored schannel info key %s\n",
+ DEBUG(3,("secrets_restore_schannel_session_info: restored schannel info key %s\n",
keystr ));
SAFE_FREE(pseed_chal);
@@ -1145,7 +1093,10 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx,
SAFE_FREE(psess_key);
SAFE_FREE(pmach_pw);
- talloc_free(keystr);
+ TALLOC_FREE(keystr);
SAFE_FREE(value.dptr);
+
+ *ppdc = pdc;
+
return True;
}
diff --git a/source/passdb/util_builtin.c b/source/passdb/util_builtin.c
index 1f810ac37a1..9c59df1f687 100644
--- a/source/passdb/util_builtin.c
+++ b/source/passdb/util_builtin.c
@@ -20,6 +20,61 @@
#include "includes.h"
+struct rid_name_map {
+ uint32 rid;
+ const char *name;
+};
+
+static const struct rid_name_map builtin_aliases[] = {
+ { BUILTIN_ALIAS_RID_ADMINS, "Administrators" },
+ { BUILTIN_ALIAS_RID_USERS, "Users" },
+ { BUILTIN_ALIAS_RID_GUESTS, "Guests" },
+ { BUILTIN_ALIAS_RID_POWER_USERS, "Power Users" },
+ { BUILTIN_ALIAS_RID_ACCOUNT_OPS, "Account Operators" },
+ { BUILTIN_ALIAS_RID_SYSTEM_OPS, "Server Operators" },
+ { BUILTIN_ALIAS_RID_PRINT_OPS, "Print Operators" },
+ { BUILTIN_ALIAS_RID_BACKUP_OPS, "Backup Operators" },
+ { BUILTIN_ALIAS_RID_REPLICATOR, "Replicator" },
+ { BUILTIN_ALIAS_RID_RAS_SERVERS, "RAS Servers" },
+ { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, "Pre-Windows 2000 Compatible Access" },
+ { 0, NULL}};
+
+/*******************************************************************
+ Look up a rid in the BUILTIN domain
+ ********************************************************************/
+BOOL lookup_builtin_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name)
+{
+ const struct rid_name_map *aliases = builtin_aliases;
+
+ while (aliases->name != NULL) {
+ if (rid == aliases->rid) {
+ *name = talloc_strdup(mem_ctx, aliases->name);
+ return True;
+ }
+ aliases++;
+ }
+
+ return False;
+}
+
+/*******************************************************************
+ Look up a name in the BUILTIN domain
+ ********************************************************************/
+BOOL lookup_builtin_name(const char *name, uint32 *rid)
+{
+ const struct rid_name_map *aliases = builtin_aliases;
+
+ while (aliases->name != NULL) {
+ if (strequal(name, aliases->name)) {
+ *rid = aliases->rid;
+ return True;
+ }
+ aliases++;
+ }
+
+ return False;
+}
+
/*****************************************************************
Return the name of the BUILTIN domain
*****************************************************************/
@@ -29,3 +84,27 @@ const char *builtin_domain_name(void)
return "BUILTIN";
}
+/*****************************************************************
+ Check if the SID is the builtin SID (S-1-5-32).
+*****************************************************************/
+
+BOOL sid_check_is_builtin(const DOM_SID *sid)
+{
+ return sid_equal(sid, &global_sid_Builtin);
+}
+
+/*****************************************************************
+ Check if the SID is one of the builtin SIDs (S-1-5-32-a).
+*****************************************************************/
+
+BOOL sid_check_is_in_builtin(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_check_is_builtin(&dom_sid);
+}
+
diff --git a/source/passdb/util_sam_sid.c b/source/passdb/util_sam_sid.c
deleted file mode 100644
index 822b7f6a349..00000000000
--- a/source/passdb/util_sam_sid.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Samba utility functions
- Copyright (C) Andrew Tridgell 1992-1998
- Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
- Copyright (C) Jeremy Allison 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.
-*/
-
-#include "includes.h"
-
-#define MAX_SID_NAMES 7
-
-typedef struct _known_sid_users {
- uint32 rid;
- enum SID_NAME_USE sid_name_use;
- const char *known_user_name;
-} known_sid_users;
-
-struct sid_name_map_info
-{
- const DOM_SID *sid;
- const char *name;
- const known_sid_users *known_users;
-};
-
-static const known_sid_users everyone_users[] = {
- { 0, SID_NAME_WKN_GRP, "Everyone" },
- {0, (enum SID_NAME_USE)0, NULL}};
-
-static const known_sid_users creator_owner_users[] = {
- { 0, SID_NAME_WKN_GRP, "Creator Owner" },
- { 1, SID_NAME_WKN_GRP, "Creator Group" },
- {0, (enum SID_NAME_USE)0, NULL}};
-
-static const known_sid_users nt_authority_users[] = {
- { 1, SID_NAME_WKN_GRP, "Dialup" },
- { 2, SID_NAME_WKN_GRP, "Network"},
- { 3, SID_NAME_WKN_GRP, "Batch"},
- { 4, SID_NAME_WKN_GRP, "Interactive"},
- { 6, SID_NAME_WKN_GRP, "Service"},
- { 7, SID_NAME_WKN_GRP, "AnonymousLogon"},
- { 8, SID_NAME_WKN_GRP, "Proxy"},
- { 9, SID_NAME_WKN_GRP, "ServerLogon"},
- { 10, SID_NAME_WKN_GRP, "Self"},
- { 11, SID_NAME_WKN_GRP, "Authenticated Users"},
- { 12, SID_NAME_WKN_GRP, "Restricted"},
- { 13, SID_NAME_WKN_GRP, "Terminal Server User"},
- { 14, SID_NAME_WKN_GRP, "Remote Interactive Logon"},
- { 15, SID_NAME_WKN_GRP, "This Organization"},
- { 18, SID_NAME_WKN_GRP, "SYSTEM"},
- { 19, SID_NAME_WKN_GRP, "Local Service"},
- { 20, SID_NAME_WKN_GRP, "Network Service"},
- { 0, (enum SID_NAME_USE)0, NULL}};
-
-static const known_sid_users builtin_groups[] = {
- { BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" },
- { BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" },
- { BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" },
- { BUILTIN_ALIAS_RID_POWER_USERS, SID_NAME_ALIAS, "Power Users" },
- { BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" },
- { BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" },
- { BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" },
- { BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" },
- { BUILTIN_ALIAS_RID_REPLICATOR, SID_NAME_ALIAS, "Replicator" },
- { BUILTIN_ALIAS_RID_RAS_SERVERS, SID_NAME_ALIAS, "RAS Servers" },
- { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, SID_NAME_ALIAS, "Pre-Windows 2000 Compatible Access" },
- { 0, (enum SID_NAME_USE)0, NULL}};
-
-static struct sid_name_map_info special_domains[] = {
- { &global_sid_Builtin, "BUILTIN", builtin_groups },
- { &global_sid_World_Domain, "", everyone_users },
- { &global_sid_Creator_Owner_Domain, "", creator_owner_users },
- { &global_sid_NT_Authority, "NT Authority", nt_authority_users },
- { NULL, NULL, NULL }};
-
-/**************************************************************************
- Turns a domain SID into a name, returned in the nt_domain argument.
-***************************************************************************/
-
-BOOL map_domain_sid_to_name(const DOM_SID *sid, fstring nt_domain)
-{
- fstring sid_str;
- int i = 0;
-
- sid_to_string(sid_str, sid);
-
- DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
-
- while (special_domains[i].sid != NULL) {
- DEBUG(5,("map_domain_sid_to_name: compare: %s\n",
- sid_string_static(special_domains[i].sid)));
- if (sid_equal(special_domains[i].sid, sid)) {
- fstrcpy(nt_domain, special_domains[i].name);
- DEBUG(5,("map_domain_sid_to_name: found '%s'\n",
- nt_domain));
- return True;
- }
- i++;
- }
-
- DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n",
- sid_string_static(sid)));
-
- return False;
-}
-
-/**************************************************************************
- Looks up a known username from one of the known domains.
-***************************************************************************/
-
-BOOL lookup_special_sid(const DOM_SID *sid, const char **domain,
- const char **name, enum SID_NAME_USE *type)
-{
- int i;
- DOM_SID dom_sid;
- uint32 rid;
- const known_sid_users *users = NULL;
-
- sid_copy(&dom_sid, sid);
- if (!sid_split_rid(&dom_sid, &rid)) {
- DEBUG(2, ("Could not split rid from SID\n"));
- return False;
- }
-
- for (i=0; special_domains[i].sid != NULL; i++) {
- if (sid_equal(&dom_sid, special_domains[i].sid)) {
- *domain = special_domains[i].name;
- users = special_domains[i].known_users;
- break;
- }
- }
-
- if (users == NULL) {
- DEBUG(10, ("SID %s is no special sid\n",
- sid_string_static(sid)));
- return False;
- }
-
- for (i=0; users[i].known_user_name != NULL; i++) {
- if (rid == users[i].rid) {
- *name = users[i].known_user_name;
- *type = users[i].sid_name_use;
- return True;
- }
- }
-
- DEBUG(10, ("RID of special SID %s not found\n",
- sid_string_static(sid)));
-
- return False;
-}
-
-/*******************************************************************
- Look up a rid in the BUILTIN domain
- ********************************************************************/
-BOOL lookup_builtin_rid(uint32 rid, fstring name)
-{
- const known_sid_users *aliases = builtin_groups;
- int i;
-
- for (i=0; aliases[i].known_user_name != NULL; i++) {
- if (rid == aliases[i].rid) {
- fstrcpy(name, aliases[i].known_user_name);
- return True;
- }
- }
-
- return False;
-}
-
-/*****************************************************************
- Check if the SID is our domain SID (S-1-5-21-x-y-z).
-*****************************************************************/
-
-BOOL sid_check_is_domain(const DOM_SID *sid)
-{
- return sid_equal(sid, get_global_sam_sid());
-}
-
-/*****************************************************************
- Check if the SID is our domain SID (S-1-5-21-x-y-z).
-*****************************************************************/
-
-BOOL sid_check_is_in_our_domain(const DOM_SID *sid)
-{
- DOM_SID dom_sid;
- uint32 rid;
-
- sid_copy(&dom_sid, sid);
- sid_split_rid(&dom_sid, &rid);
-
- return sid_equal(&dom_sid, get_global_sam_sid());
-}
-
-/**************************************************************************
- Try and map a name to one of the well known SIDs.
-***************************************************************************/
-
-BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char *name)
-{
- int i, j;
-
- DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name));
-
- for (i=0; special_domains[i].sid != NULL; i++) {
- const known_sid_users *users = special_domains[i].known_users;
-
- if (users == NULL)
- continue;
-
- for (j=0; users[j].known_user_name != NULL; j++) {
- if ( strequal(users[j].known_user_name, name) ) {
- sid_copy(sid, special_domains[i].sid);
- sid_append_rid(sid, users[j].rid);
- *use = users[j].sid_name_use;
- return True;
- }
- }
- }
-
- return False;
-}
-
-
diff --git a/source/passdb/util_unixsids.c b/source/passdb/util_unixsids.c
new file mode 100644
index 00000000000..2a4818e3aec
--- /dev/null
+++ b/source/passdb/util_unixsids.c
@@ -0,0 +1,94 @@
+/*
+ Unix SMB/CIFS implementation.
+ Translate unix-defined names to SIDs and vice versa
+ 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"
+
+BOOL sid_check_is_unix_users(const DOM_SID *sid)
+{
+ return sid_equal(sid, &global_sid_Unix_Users);
+}
+
+BOOL sid_check_is_in_unix_users(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_check_is_unix_users(&dom_sid);
+}
+
+const char *unix_users_domain_name(void)
+{
+ return "Unix User";
+}
+
+BOOL lookup_unix_user_name(const char *name, DOM_SID *sid)
+{
+ struct passwd *pwd;
+
+ pwd = getpwnam_alloc(NULL, name);
+ if (pwd == NULL) {
+ return False;
+ }
+
+ sid_copy(sid, &global_sid_Unix_Users);
+ sid_append_rid(sid, pwd->pw_uid); /* For 64-bit uid's we have enough
+ * space ... */
+ TALLOC_FREE(pwd);
+ return True;
+}
+
+BOOL sid_check_is_unix_groups(const DOM_SID *sid)
+{
+ return sid_equal(sid, &global_sid_Unix_Groups);
+}
+
+BOOL sid_check_is_in_unix_groups(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_check_is_unix_groups(&dom_sid);
+}
+
+const char *unix_groups_domain_name(void)
+{
+ return "Unix Group";
+}
+
+BOOL lookup_unix_group_name(const char *name, DOM_SID *sid)
+{
+ struct group *grp;
+
+ grp = getgrnam(name);
+ if (grp == NULL) {
+ return False;
+ }
+
+ sid_copy(sid, &global_sid_Unix_Groups);
+ sid_append_rid(sid, grp->gr_gid); /* For 64-bit uid's we have enough
+ * space ... */
+ return True;
+}
diff --git a/source/passdb/util_wellknown.c b/source/passdb/util_wellknown.c
new file mode 100644
index 00000000000..9a6fa7def52
--- /dev/null
+++ b/source/passdb/util_wellknown.c
@@ -0,0 +1,175 @@
+/*
+ Unix SMB/CIFS implementation.
+ Lookup routines for well-known SIDs
+ Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Luke Kenneth Caseson Leighton 1998-1999
+ Copyright (C) Jeremy Allison 1999
+ 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"
+
+struct rid_name_map {
+ uint32 rid;
+ const char *name;
+};
+
+struct sid_name_map_info
+{
+ const DOM_SID *sid;
+ const char *name;
+ const struct rid_name_map *known_users;
+};
+
+static const struct rid_name_map everyone_users[] = {
+ { 0, "Everyone" },
+ { 0, NULL}};
+
+static const struct rid_name_map creator_owner_users[] = {
+ { 0, "Creator Owner" },
+ { 1, "Creator Group" },
+ { 0, NULL}};
+
+static const struct rid_name_map nt_authority_users[] = {
+ { 1, "Dialup" },
+ { 2, "Network"},
+ { 3, "Batch"},
+ { 4, "Interactive"},
+ { 6, "Service"},
+ { 7, "AnonymousLogon"},
+ { 8, "Proxy"},
+ { 9, "ServerLogon"},
+ { 10, "Self"},
+ { 11, "Authenticated Users"},
+ { 12, "Restricted"},
+ { 13, "Terminal Server User"},
+ { 14, "Remote Interactive Logon"},
+ { 15, "This Organization"},
+ { 18, "SYSTEM"},
+ { 19, "Local Service"},
+ { 20, "Network Service"},
+ { 0, NULL}};
+
+static struct sid_name_map_info special_domains[] = {
+ { &global_sid_World_Domain, "", everyone_users },
+ { &global_sid_Creator_Owner_Domain, "", creator_owner_users },
+ { &global_sid_NT_Authority, "NT Authority", nt_authority_users },
+ { NULL, NULL, NULL }};
+
+BOOL sid_check_is_wellknown_domain(const DOM_SID *sid, const char **name)
+{
+ int i;
+
+ for (i=0; special_domains[i].sid != NULL; i++) {
+ if (sid_equal(sid, special_domains[i].sid)) {
+ if (name != NULL) {
+ *name = special_domains[i].name;
+ }
+ return True;
+ }
+ }
+ return False;
+}
+
+BOOL sid_check_is_in_wellknown_domain(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_check_is_wellknown_domain(&dom_sid, NULL);
+}
+
+/**************************************************************************
+ Looks up a known username from one of the known domains.
+***************************************************************************/
+
+BOOL lookup_wellknown_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ const char **domain, const char **name)
+{
+ int i;
+ DOM_SID dom_sid;
+ uint32 rid;
+ const struct rid_name_map *users = NULL;
+
+ sid_copy(&dom_sid, sid);
+ if (!sid_split_rid(&dom_sid, &rid)) {
+ DEBUG(2, ("Could not split rid from SID\n"));
+ return False;
+ }
+
+ for (i=0; special_domains[i].sid != NULL; i++) {
+ if (sid_equal(&dom_sid, special_domains[i].sid)) {
+ *domain = talloc_strdup(mem_ctx,
+ special_domains[i].name);
+ users = special_domains[i].known_users;
+ break;
+ }
+ }
+
+ if (users == NULL) {
+ DEBUG(10, ("SID %s is no special sid\n",
+ sid_string_static(sid)));
+ return False;
+ }
+
+ for (i=0; users[i].name != NULL; i++) {
+ if (rid == users[i].rid) {
+ *name = talloc_strdup(mem_ctx, users[i].name);
+ return True;
+ }
+ }
+
+ DEBUG(10, ("RID of special SID %s not found\n",
+ sid_string_static(sid)));
+
+ return False;
+}
+
+/**************************************************************************
+ Try and map a name to one of the well known SIDs.
+***************************************************************************/
+
+BOOL lookup_wellknown_name(TALLOC_CTX *mem_ctx, const char *name,
+ DOM_SID *sid, const char **domain)
+{
+ int i, j;
+
+ DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name));
+
+ for (i=0; special_domains[i].sid != NULL; i++) {
+ const struct rid_name_map *users =
+ special_domains[i].known_users;
+
+ if (users == NULL)
+ continue;
+
+ for (j=0; users[j].name != NULL; j++) {
+ if ( strequal(users[j].name, name) ) {
+ sid_copy(sid, special_domains[i].sid);
+ sid_append_rid(sid, users[j].rid);
+ *domain = talloc_strdup(
+ mem_ctx, special_domains[i].name);
+ return True;
+ }
+ }
+ }
+
+ return False;
+}
diff --git a/source/printing/lpq_parse.c b/source/printing/lpq_parse.c
index 68c06ade41f..7e81b5187c9 100644
--- a/source/printing/lpq_parse.c
+++ b/source/printing/lpq_parse.c
@@ -971,7 +971,7 @@ BOOL parse_lpq_entry(enum printing_types printing_type,char *line,
}
/* in the LPRNG case, we skip lines starting by a space.*/
- if (line && !ret && (printing_type==PRINT_LPRNG) )
+ if (!ret && (printing_type==PRINT_LPRNG) )
{
if (line[0]==' ')
return ret;
diff --git a/source/printing/notify.c b/source/printing/notify.c
index e71d9e6f259..f27eb2011ff 100644
--- a/source/printing/notify.c
+++ b/source/printing/notify.c
@@ -520,7 +520,7 @@ BOOL print_notify_pid_list(const char *printername, TALLOC_CTX *mem_ctx, size_t
return False;
tdb = pdb->tdb;
- if (tdb_read_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
+ if (tdb_read_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
DEBUG(0,("print_notify_pid_list: Failed to lock printer %s database\n",
printername));
if (pdb)
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 1df6bb605aa..1a664fbb34e 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -673,7 +673,7 @@ uint32 update_c_setprinter(BOOL initialize)
int32 c_setprinter;
int32 printer_count = 0;
- tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
+ tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
/* Traverse the tdb, counting the printers */
tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
@@ -743,17 +743,19 @@ BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
}
/****************************************************************************
-get a form struct list
+ get a form struct list.
****************************************************************************/
+
int get_ntforms(nt_forms_struct **list)
{
TDB_DATA kbuf, newkey, dbuf;
- nt_forms_struct *tl;
nt_forms_struct form;
int ret;
int i;
int n = 0;
+ *list = NULL;
+
for (kbuf = tdb_firstkey(tdb_forms);
kbuf.dptr;
newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
@@ -773,12 +775,11 @@ int get_ntforms(nt_forms_struct **list)
if (ret != dbuf.dsize)
continue;
- tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
- if (!tl) {
+ *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
+ if (!*list) {
DEBUG(0,("get_ntforms: Realloc fail.\n"));
return 0;
}
- *list = tl;
(*list)[n] = form;
n++;
}
@@ -823,7 +824,6 @@ BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
int n=0;
BOOL update;
fstring form_name;
- nt_forms_struct *tl;
/*
* NT tries to add forms even when
@@ -842,11 +842,10 @@ BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
}
if (update==False) {
- if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
+ if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
return False;
}
- *list = tl;
unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
(*count)++;
}
@@ -940,7 +939,6 @@ int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
{
int total=0;
const char *short_archi;
- fstring *fl;
pstring key;
TDB_DATA kbuf, newkey;
@@ -954,11 +952,10 @@ int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
continue;
- if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
+ if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
return -1;
}
- else *list = fl;
fstrcpy((*list)[total], kbuf.dptr+strlen(key));
total++;
@@ -1296,7 +1293,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
}
}
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
/* Get file version info (if available) for new file */
pstrcpy(filepath, new_file);
@@ -1332,7 +1329,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
}
}
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
if (use_version && (new_major != old_major || new_minor != old_minor)) {
/* Compare versions and choose the larger version number */
@@ -1361,7 +1358,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
error_exit:
if(fsp)
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
return -1;
}
@@ -1486,7 +1483,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
driverpath, cversion));
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
close_cnum(conn, user->vuid);
unbecome_user();
*perr = WERR_OK;
@@ -1496,7 +1493,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
error_exit:
if(fsp)
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
close_cnum(conn, user->vuid);
unbecome_user();
@@ -1973,15 +1970,12 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
}
if (len != buflen) {
- char *tb;
-
- tb = (char *)SMB_REALLOC(buf, len);
- if (!tb) {
+ buf = (char *)SMB_REALLOC(buf, len);
+ if (!buf) {
DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
ret = -1;
goto done;
}
- else buf = tb;
buflen = len;
goto again;
}
@@ -2098,15 +2092,11 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
i=0;
while (len < dbuf.dsize) {
- fstring *tddfs;
-
- tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
- if ( !tddfs ) {
+ driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
+ if ( !driver.dependentfiles ) {
DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
break;
}
- else
- driver.dependentfiles = tddfs;
len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
&driver.dependentfiles[i]);
@@ -2406,15 +2396,12 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
len += pack_values( info->data, buf+len, buflen-len );
if (buflen != len) {
- char *tb;
-
- tb = (char *)SMB_REALLOC(buf, len);
- if (!tb) {
+ buf = (char *)SMB_REALLOC(buf, len);
+ if (!buf) {
DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
ret = WERR_NOMEM;
goto done;
}
- else buf = tb;
buflen = len;
goto again;
}
@@ -2744,7 +2731,7 @@ int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subke
int key_len;
int num_subkeys = 0;
char *p;
- fstring *ptr, *subkeys_ptr = NULL;
+ fstring *subkeys_ptr = NULL;
fstring subkeyname;
if ( !data )
@@ -2760,14 +2747,12 @@ int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subke
/* found a match, so allocate space and copy the name */
- if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
+ if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
num_subkeys+1));
- SAFE_FREE( subkeys );
return -1;
}
- subkeys_ptr = ptr;
fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
num_subkeys++;
}
@@ -2807,14 +2792,12 @@ int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subke
/* found a match, so allocate space and copy the name */
- if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
+ if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
num_subkeys+1));
- SAFE_FREE( subkeys );
return 0;
}
- subkeys_ptr = ptr;
fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
num_subkeys++;
}
@@ -2823,8 +2806,10 @@ int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subke
/* return error if the key was not found */
- if ( i == data->num_keys )
+ if ( i == data->num_keys ) {
+ SAFE_FREE(subkeys_ptr);
return -1;
+ }
done:
/* tag off the end */
@@ -3545,9 +3530,10 @@ static void map_to_os2_driver(fstring drivername)
return;
}
- lines = file_lines_load(mapfile, &numlines);
- if (numlines == 0) {
+ lines = file_lines_load(mapfile, &numlines,0);
+ if (numlines == 0 || lines == NULL) {
DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
+ SAFE_FREE(lines);
return;
}
@@ -4076,16 +4062,12 @@ static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
len += pack_values( info->data, buf+len, buflen-len );
if (buflen < len) {
- char *tb;
-
- tb = (char *)SMB_REALLOC(buf, len);
- if (!tb) {
+ buf = (char *)SMB_REALLOC(buf, len);
+ if (!buf) {
DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
ret = -1;
goto done;
}
- else
- buf = tb;
buflen = len;
goto again;
}
@@ -5280,7 +5262,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
/* Always allow root or SE_PRINT_OPERATROR to do anything */
- if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
+ if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
return True;
}
@@ -5331,9 +5313,11 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
/* see if we need to try the printer admin list */
- if ( access_granted == 0 ) {
- if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
- return True;
+ if ((access_granted == 0) &&
+ (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
+ user->nt_user_token,
+ lp_printer_admin(snum)))) {
+ return True;
}
talloc_destroy(mem_ctx);
diff --git a/source/printing/print_cups.c b/source/printing/print_cups.c
index 8ae896fddf4..afa301bbea1 100644
--- a/source/printing/print_cups.c
+++ b/source/printing/print_cups.c
@@ -816,16 +816,13 @@ static int cups_queue_get(const char *sharename,
if (qcount >= qalloc) {
qalloc += 16;
- temp = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
+ queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
- if (temp == NULL) {
+ if (queue == NULL) {
DEBUG(0,("cups_queue_get: Not enough memory!"));
qcount = 0;
- SAFE_FREE(queue);
goto out;
}
-
- queue = temp;
}
temp = queue + qcount;
diff --git a/source/printing/print_generic.c b/source/printing/print_generic.c
index b2484d5b433..e445bc3ce00 100644
--- a/source/printing/print_generic.c
+++ b/source/printing/print_generic.c
@@ -187,17 +187,21 @@ static int generic_queue_get(const char *printer_name,
}
numlines = 0;
- qlines = fd_lines_load(fd, &numlines);
+ qlines = fd_lines_load(fd, &numlines,0);
close(fd);
/* turn the lpq output into a series of job structures */
qcount = 0;
ZERO_STRUCTP(status);
- if (numlines)
+ if (numlines) {
queue = SMB_MALLOC_ARRAY(print_queue_struct, numlines+1);
-
- if (queue) {
+ if (!queue) {
+ file_lines_free(qlines);
+ *q = NULL;
+ return 0;
+ }
memset(queue, '\0', sizeof(print_queue_struct)*(numlines+1));
+
for (i=0; i<numlines; i++) {
/* parse the line */
if (parse_lpq_entry(printing_type,qlines[i],
@@ -206,8 +210,8 @@ static int generic_queue_get(const char *printer_name,
}
}
}
- file_lines_free(qlines);
+ file_lines_free(qlines);
*q = queue;
return qcount;
}
diff --git a/source/printing/print_iprint.c b/source/printing/print_iprint.c
index fc606676284..04b096a8a5b 100644
--- a/source/printing/print_iprint.c
+++ b/source/printing/print_iprint.c
@@ -1074,16 +1074,13 @@ static int iprint_queue_get(const char *sharename,
if (qcount >= qalloc) {
qalloc += 16;
- temp = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
+ queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
- if (temp == NULL) {
+ if (queue == NULL) {
DEBUG(0,("iprint_queue_get: Not enough memory!"));
qcount = 0;
- SAFE_FREE(queue);
goto out;
}
-
- queue = temp;
}
temp = queue + qcount;
diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c
index eb81dc4536f..c248851822b 100644
--- a/source/printing/printfsp.c
+++ b/source/printing/printfsp.c
@@ -94,7 +94,7 @@ files_struct *print_fsp_open(connection_struct *conn, const char *fname)
Print a file - called on closing the file.
****************************************************************************/
-void print_fsp_end(files_struct *fsp, BOOL normal_close)
+void print_fsp_end(files_struct *fsp, enum file_close_type close_type)
{
uint32 jobid;
fstring sharename;
@@ -117,5 +117,5 @@ void print_fsp_end(files_struct *fsp, BOOL normal_close)
return;
}
- print_job_end(SNUM(fsp->conn),jobid, normal_close);
+ print_job_end(SNUM(fsp->conn),jobid, close_type);
}
diff --git a/source/printing/printing.c b/source/printing/printing.c
index 6e74095f719..b131727f8a4 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -197,7 +197,7 @@ BOOL print_backend_init(void)
pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
continue;
- if (tdb_lock_bystring(pdb->tdb, sversion, 0) == -1) {
+ if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
release_print_db(pdb);
return False;
@@ -541,15 +541,11 @@ static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjo
len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
if (buflen != len) {
- char *tb;
-
- tb = (char *)SMB_REALLOC(buf, len);
- if (!tb) {
+ buf = (char *)SMB_REALLOC(buf, len);
+ if (!buf) {
DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
goto done;
}
- else
- buf = tb;
newlen = len;
}
} while ( buflen != len );
@@ -1295,7 +1291,7 @@ static void print_queue_update_with_lock( const char *sharename,
slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
/* Only wait 10 seconds for this. */
- if (tdb_lock_bystring(pdb->tdb, keystr, 10) == -1) {
+ if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
release_print_db(pdb);
return;
@@ -1404,7 +1400,7 @@ void start_background_queue(void)
/* check for some essential signals first */
if (got_sig_term) {
- exit_server("Caught TERM signal");
+ exit_server_cleanly(NULL);
}
if (reload_after_sighup) {
@@ -1447,11 +1443,13 @@ static void print_queue_update(int snum, BOOL force)
/* don't strip out characters like '$' from the printername */
pstrcpy( lpqcommand, lp_lpqcommand(snum));
- string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), False, False );
+ string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand),
+ False, False, False );
standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
pstrcpy( lprmcommand, lp_lprmcommand(snum));
- string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), False, False );
+ string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand),
+ False, False, False );
standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) );
/*
@@ -1565,7 +1563,7 @@ BOOL print_notify_register_pid(int snum)
tdb = pdb->tdb;
}
- if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
+ if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
printername));
if (pdb)
@@ -1655,7 +1653,7 @@ BOOL print_notify_deregister_pid(int snum)
tdb = pdb->tdb;
}
- if (tdb_lock_bystring(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
+ if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
DEBUG(0,("print_notify_register_pid: Failed to lock \
printer %s database\n", printername));
if (pdb)
@@ -1932,7 +1930,7 @@ static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
return strequal(pjob->user, vuser->user.smb_name);
} else {
- return strequal(pjob->user, uidtoname(user->uid));
+ return strequal(pjob->user, uidtoname(user->ut.uid));
}
}
@@ -1963,7 +1961,7 @@ BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR
sys_adminlog( LOG_ERR,
"Permission denied-- user not allowed to delete, \
pause, or resume print job. User name: %s. Printer name: %s.",
- uidtoname(user->uid), PRINTERNAME(snum) );
+ uidtoname(user->ut.uid), PRINTERNAME(snum) );
/* END_ADMIN_LOG */
return False;
@@ -2030,7 +2028,7 @@ BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *
sys_adminlog( LOG_ERR,
"Permission denied-- user not allowed to delete, \
pause, or resume print job. User name: %s. Printer name: %s.",
- uidtoname(user->uid), PRINTERNAME(snum) );
+ uidtoname(user->ut.uid), PRINTERNAME(snum) );
/* END_ADMIN_LOG */
*errcode = WERR_ACCESS_DENIED;
@@ -2085,7 +2083,7 @@ BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR
sys_adminlog( LOG_ERR,
"Permission denied-- user not allowed to delete, \
pause, or resume print job. User name: %s. Printer name: %s.",
- uidtoname(user->uid), PRINTERNAME(snum) );
+ uidtoname(user->ut.uid), PRINTERNAME(snum) );
/* END_ADMIN_LOG */
return False;
}
@@ -2207,7 +2205,7 @@ static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char
for (i = 0; i < 3; i++) {
/* Lock the database - only wait 20 seconds. */
- if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob", 20) == -1) {
+ if (tdb_lock_bystring_with_timeout(pdb->tdb, "INFO/nextjob", 20) == -1) {
DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", sharename));
return False;
}
@@ -2366,7 +2364,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DE
if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
fstrcpy(pjob.user, vuser->user.smb_name);
} else {
- fstrcpy(pjob.user, uidtoname(user->uid));
+ fstrcpy(pjob.user, uidtoname(user->ut.uid));
}
fstrcpy(pjob.queuename, lp_const_servicename(snum));
@@ -2437,7 +2435,7 @@ void print_job_endpage(int snum, uint32 jobid)
error.
****************************************************************************/
-BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
+BOOL print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
{
const char* sharename = lp_const_servicename(snum);
struct printjob *pjob;
@@ -2453,7 +2451,8 @@ BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
if (pjob->spooled || pjob->pid != sys_getpid())
return False;
- if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
+ if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
+ (sys_fstat(pjob->fd, &sbuf) == 0)) {
pjob->size = sbuf.st_size;
close(pjob->fd);
pjob->fd = -1;
diff --git a/source/python/py_common.c b/source/python/py_common.c
index 66f35759c3d..70d478b9797 100644
--- a/source/python/py_common.c
+++ b/source/python/py_common.c
@@ -47,7 +47,7 @@ void py_samba_init(void)
/* Load configuration file */
- if (!lp_load(dyn_CONFIGFILE, True, False, False))
+ if (!lp_load(dyn_CONFIGFILE, True, False, False, True))
fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
/* Misc other stuff */
diff --git a/source/python/py_lsa.c b/source/python/py_lsa.c
index 4f809520bc3..a4e8254e0d1 100644
--- a/source/python/py_lsa.c
+++ b/source/python/py_lsa.c
@@ -186,8 +186,8 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args)
}
ntstatus = rpccli_lsa_lookup_names(
- hnd->cli, mem_ctx, &hnd->pol, num_names, names, &sids,
- &name_types);
+ hnd->cli, mem_ctx, &hnd->pol, num_names, names,
+ NULL, &sids, &name_types);
if (!NT_STATUS_IS_OK(ntstatus) && NT_STATUS_V(ntstatus) != 0x107) {
PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus));
diff --git a/source/python/py_samr.c b/source/python/py_samr.c
index fc9f2a83ebe..a26cd8d132e 100644
--- a/source/python/py_samr.c
+++ b/source/python/py_samr.c
@@ -467,7 +467,7 @@ static PyObject *samr_create_dom_user(PyObject *self, PyObject *args,
uint32 user_rid;
PyObject *result = NULL;
TALLOC_CTX *mem_ctx;
- uint16 acb_info = ACB_NORMAL;
+ uint32 acb_info = ACB_NORMAL;
POLICY_HND user_pol;
if (!PyArg_ParseTupleAndKeywords(
diff --git a/source/python/py_winbind.c b/source/python/py_winbind.c
index 2f22649bfbf..40181f5579d 100644
--- a/source/python/py_winbind.c
+++ b/source/python/py_winbind.c
@@ -134,8 +134,8 @@ static PyObject *py_enum_domain_users(PyObject *self, PyObject *args)
result = PyList_New(0);
- if (response.extra_data) {
- const char *extra_data = response.extra_data;
+ if (response.extra_data.data) {
+ const char *extra_data = response.extra_data.data;
fstring name;
while (next_token(&extra_data, name, ",", sizeof(fstring)))
@@ -165,8 +165,8 @@ static PyObject *py_enum_domain_groups(PyObject *self, PyObject *args)
result = PyList_New(0);
- if (response.extra_data) {
- const char *extra_data = response.extra_data;
+ if (response.extra_data.data) {
+ const char *extra_data = response.extra_data.data;
fstring name;
while (next_token(&extra_data, name, ",", sizeof(fstring)))
@@ -200,8 +200,8 @@ static PyObject *py_enum_trust_dom(PyObject *self, PyObject *args)
result = PyList_New(0);
- if (response.extra_data) {
- const char *extra_data = response.extra_data;
+ if (response.extra_data.data) {
+ const char *extra_data = response.extra_data.data;
fstring name;
while (next_token(&extra_data, name, ",", sizeof(fstring)))
diff --git a/source/registry/reg_db.c b/source/registry/reg_db.c
index ddc08cf2ce4..5484c238b60 100644
--- a/source/registry/reg_db.c
+++ b/source/registry/reg_db.c
@@ -298,7 +298,7 @@ int regdb_close( void )
static BOOL regdb_store_keys_internal( const char *key, REGSUBKEY_CTR *ctr )
{
TDB_DATA kbuf, dbuf;
- char *buffer, *tmpbuf;
+ char *buffer;
int i = 0;
uint32 len, buflen;
BOOL ret = True;
@@ -327,12 +327,11 @@ 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 ((tmpbuf = SMB_REALLOC( buffer, len*2 )) == NULL) {
+ if ((buffer = 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;
}
- buffer = tmpbuf;
buflen = len*2;
len = tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
@@ -526,11 +525,13 @@ static int regdb_pack_values(REGVAL_CTR *values, char *buf, int buflen)
int len = 0;
int i;
REGISTRY_VALUE *val;
- int num_values = regval_ctr_numvals( values );
+ int num_values;
if ( !values )
return 0;
+ num_values = regval_ctr_numvals( values );
+
/* pack the number of values first */
len += tdb_pack( buf+len, buflen-len, "d", num_values );
diff --git a/source/registry/reg_objects.c b/source/registry/reg_objects.c
index 05567d561c6..33c2660331b 100644
--- a/source/registry/reg_objects.c
+++ b/source/registry/reg_objects.c
@@ -43,8 +43,6 @@
int regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
{
- char **pp;
-
if ( !keyname )
return ctr->num_subkeys;
@@ -55,12 +53,15 @@ int regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, const char *keyname )
/* allocate a space for the char* in the array */
- if ( ctr->subkeys == 0 )
- ctr->subkeys = TALLOC_P( ctr, char *);
- else {
- pp = TALLOC_REALLOC_ARRAY( ctr, ctr->subkeys, char *, ctr->num_subkeys+1);
- if ( pp )
- ctr->subkeys = pp;
+ if (ctr->subkeys == NULL) {
+ ctr->subkeys = TALLOC_P(ctr, char *);
+ } else {
+ ctr->subkeys = TALLOC_REALLOC_ARRAY(ctr, ctr->subkeys, char *, ctr->num_subkeys+1);
+ }
+
+ if (!ctr->subkeys) {
+ ctr->num_subkeys = 0;
+ return 0;
}
/* allocate the string and save it in the array */
@@ -269,8 +270,6 @@ BOOL regval_ctr_key_exists( REGVAL_CTR *ctr, const char *value )
int regval_ctr_addvalue( REGVAL_CTR *ctr, const char *name, uint16 type,
const char *data_p, size_t size )
{
- REGISTRY_VALUE **ppreg;
-
if ( !name )
return ctr->num_values;
@@ -280,17 +279,24 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, const char *name, uint16 type,
/* allocate a slot in the array of pointers */
- if ( ctr->num_values == 0 )
+ if ( ctr->num_values == 0 ) {
ctr->values = TALLOC_P( ctr, REGISTRY_VALUE *);
- else {
- ppreg = TALLOC_REALLOC_ARRAY( ctr, ctr->values, REGISTRY_VALUE *, ctr->num_values+1 );
- if ( ppreg )
- ctr->values = ppreg;
+ } else {
+ ctr->values = TALLOC_REALLOC_ARRAY( ctr, ctr->values, REGISTRY_VALUE *, ctr->num_values+1 );
+ }
+
+ if (!ctr->values) {
+ ctr->num_values = 0;
+ return 0;
}
/* allocate a new value and store the pointer in the arrya */
ctr->values[ctr->num_values] = TALLOC_P( ctr, REGISTRY_VALUE);
+ if (!ctr->values[ctr->num_values]) {
+ ctr->num_values = 0;
+ return 0;
+ }
/* init the value */
@@ -309,23 +315,27 @@ int regval_ctr_addvalue( REGVAL_CTR *ctr, const char *name, uint16 type,
int regval_ctr_copyvalue( REGVAL_CTR *ctr, REGISTRY_VALUE *val )
{
- REGISTRY_VALUE **ppreg;
-
- if ( val )
- {
+ if ( val ) {
/* allocate a slot in the array of pointers */
- if ( ctr->num_values == 0 )
+ if ( ctr->num_values == 0 ) {
ctr->values = TALLOC_P( ctr, REGISTRY_VALUE *);
- else {
- ppreg = TALLOC_REALLOC_ARRAY( ctr, ctr->values, REGISTRY_VALUE *, ctr->num_values+1 );
- if ( ppreg )
- ctr->values = ppreg;
+ } else {
+ ctr->values = TALLOC_REALLOC_ARRAY( ctr, ctr->values, REGISTRY_VALUE *, ctr->num_values+1 );
+ }
+
+ if (!ctr->values) {
+ ctr->num_values = 0;
+ return 0;
}
/* allocate a new value and store the pointer in the arrya */
ctr->values[ctr->num_values] = TALLOC_P( ctr, REGISTRY_VALUE);
+ if (!ctr->values[ctr->num_values]) {
+ ctr->num_values = 0;
+ return 0;
+ }
/* init the value */
@@ -410,4 +420,3 @@ char* regval_sz( REGISTRY_VALUE *val )
return data;
}
-
diff --git a/source/registry/reg_perfcount.c b/source/registry/reg_perfcount.c
index a31154fc33b..385128e7b55 100644
--- a/source/registry/reg_perfcount.c
+++ b/source/registry/reg_perfcount.c
@@ -158,7 +158,7 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
{
TDB_DATA kbuf, dbuf;
char temp[256];
- char *buf1 = *retbuf, *buf2 = NULL;
+ char *buf1 = *retbuf;
uint32 working_size = 0;
UNISTR2 name_index, name;
@@ -172,32 +172,26 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
/* If a key isn't there, just bypass it -- this really shouldn't
happen unless someone's mucking around with the tdb */
DEBUG(3, ("_reg_perfcount_multi_sz_from_tdb: failed to find key [%s] in [%s].\n",
- temp, tdb->name));
+ temp, tdb_name(tdb)));
return buffer_size;
}
/* First encode the name_index */
working_size = (kbuf.dsize + 1)*sizeof(uint16);
- buf2 = SMB_REALLOC(buf1, buffer_size + working_size);
- if(!buf2)
- {
- SAFE_FREE(buf1);
+ buf1 = SMB_REALLOC(buf1, buffer_size + working_size);
+ if(!buf1) {
buffer_size = 0;
return buffer_size;
}
- buf1 = buf2;
init_unistr2(&name_index, kbuf.dptr, UNI_STR_TERMINATE);
memcpy(buf1+buffer_size, (char *)name_index.buffer, working_size);
buffer_size += working_size;
/* Now encode the actual name */
working_size = (dbuf.dsize + 1)*sizeof(uint16);
- buf2 = SMB_REALLOC(buf1, buffer_size + working_size);
- if(!buf2)
- {
- SAFE_FREE(buf1);
+ buf1 = SMB_REALLOC(buf1, buffer_size + working_size);
+ if(!buf1) {
buffer_size = 0;
return buffer_size;
}
- buf1 = buf2;
memset(temp, 0, sizeof(temp));
memcpy(temp, dbuf.dptr, dbuf.dsize);
SAFE_FREE(dbuf.dptr);
@@ -215,7 +209,7 @@ static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb,
uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf)
{
- char *buf1 = NULL, *buf2 = NULL;
+ char *buf1 = NULL;
uint32 buffer_size = 0;
TDB_CONTEXT *names;
const char *fname = counters_directory( NAMES_DB );
@@ -240,15 +234,10 @@ uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf)
/* Now terminate the MULTI_SZ with a double unicode NULL */
buf1 = *retbuf;
- buf2 = SMB_REALLOC(buf1, buffer_size + 2);
- if(!buf2)
- {
- SAFE_FREE(buf1);
+ buf1 = SMB_REALLOC(buf1, buffer_size + 2);
+ if(!buf1) {
buffer_size = 0;
- }
- else
- {
- buf1 = buf2;
+ } else {
buf1[buffer_size++] = '\0';
buf1[buffer_size++] = '\0';
}
@@ -263,7 +252,7 @@ uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf)
uint32 reg_perfcount_get_counter_names(uint32 base_index, char **retbuf)
{
- char *buf1 = NULL, *buf2 = NULL;
+ char *buf1 = NULL;
uint32 buffer_size = 0;
TDB_CONTEXT *names;
const char *fname = counters_directory( NAMES_DB );
@@ -290,15 +279,10 @@ uint32 reg_perfcount_get_counter_names(uint32 base_index, char **retbuf)
/* Now terminate the MULTI_SZ with a double unicode NULL */
buf1 = *retbuf;
- buf2 = SMB_REALLOC(buf1, buffer_size + 2);
- if(!buf2)
- {
- SAFE_FREE(buf1);
+ buf1 = SMB_REALLOC(buf1, buffer_size + 2);
+ if(!buf1) {
buffer_size = 0;
- }
- else
- {
- buf1 = buf2;
+ } else {
buf1[buffer_size++] = '\0';
buf1[buffer_size++] = '\0';
}
@@ -515,7 +499,7 @@ static BOOL _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
obj->counters[obj->NumCounters].CounterType = atoi(buf);
DEBUG(10, ("_reg_perfcount_get_counter_info: Got type [%d] for counter [%d].\n",
obj->counters[obj->NumCounters].CounterType, CounterIndex));
- free(data.dptr);
+ SAFE_FREE(data.dptr);
/* Fetch the actual data */
_reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "");
@@ -560,7 +544,7 @@ static BOOL _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
memset(buf, 0, PERFCOUNT_MAX_LEN);
memcpy(buf, data.dptr, data.dsize);
}
- free(data.dptr);
+ SAFE_FREE(data.dptr);
obj->counter_data.ByteLength += dsize + padding;
obj->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
@@ -710,7 +694,7 @@ BOOL _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
return False;
memset(inst->counter_data.data, 0, data.dsize);
memcpy(inst->counter_data.data, data.dptr, data.dsize);
- free(data.dptr);
+ SAFE_FREE(data.dptr);
/* Fetch instance name */
memset(temp, 0, PERFCOUNT_MAX_LEN);
@@ -735,7 +719,7 @@ BOOL _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
uint8,
inst->NameLength);
memcpy(inst->data, name, inst->NameLength);
- free(data.dptr);
+ SAFE_FREE(data.dptr);
}
inst->ParentObjectTitleIndex = 0;
@@ -823,7 +807,7 @@ static int _reg_perfcount_assemble_global(PERF_DATA_BLOCK *block,
DEBUG(3, ("_reg_perfcount_assemble_global: Failed to add new relationship for counter [%d].\n", j));
retval = -1;
}
- free(data.dptr);
+ SAFE_FREE(data.dptr);
}
else
DEBUG(3, ("NULL relationship for counter [%d] using key [%s].\n", j, keybuf));
@@ -853,7 +837,7 @@ static BOOL _reg_perfcount_get_64(SMB_BIG_UINT *retval,
memset(buf, 0, PERFCOUNT_MAX_LEN);
memcpy(buf, data.dptr, data.dsize);
- free(data.dptr);
+ SAFE_FREE(data.dptr);
*retval = atof(buf);
diff --git a/source/registry/reg_printing.c b/source/registry/reg_printing.c
index 592069052f8..f001fdad244 100644
--- a/source/registry/reg_printing.c
+++ b/source/registry/reg_printing.c
@@ -858,7 +858,6 @@ static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL_CTR *values )
{
char *buffer = NULL;
- char *buffer2 = NULL;
int buffer_size = 0;
int i, length;
char *filename;
@@ -903,10 +902,10 @@ static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL
length = strlen(filename);
- buffer2 = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
- if ( !buffer2 )
+ buffer = SMB_REALLOC( buffer, buffer_size + (length + 1)*sizeof(uint16) );
+ if ( !buffer ) {
break;
- buffer = buffer2;
+ }
init_unistr2( &data, filename, UNI_STR_TERMINATE);
memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
@@ -916,12 +915,10 @@ static void fill_in_driver_values( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3, REGVAL
/* terminated by double NULL. Add the final one here */
- buffer2 = SMB_REALLOC( buffer, buffer_size + 2 );
- if ( !buffer2 ) {
- SAFE_FREE( buffer );
+ buffer = SMB_REALLOC( buffer, buffer_size + 2 );
+ if ( !buffer ) {
buffer_size = 0;
} else {
- buffer = buffer2;
buffer[buffer_size++] = '\0';
buffer[buffer_size++] = '\0';
}
diff --git a/source/rpc_client/cli_dfs.c b/source/rpc_client/cli_dfs.c
index 78df220ac2a..8b94d6ed9d4 100644
--- a/source/rpc_client/cli_dfs.c
+++ b/source/rpc_client/cli_dfs.c
@@ -1,183 +1,632 @@
-/*
- Unix SMB/CIFS implementation.
- RPC pipe client
- Copyright (C) Tim Potter 2000-2001,
- 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.
-*/
+/*
+ * Unix SMB/CIFS implementation.
+ * client auto-generated by pidl. DO NOT MODIFY!
+ */
#include "includes.h"
-/* Query DFS support */
-
-NTSTATUS rpccli_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- BOOL *dfs_exists)
+NTSTATUS rpccli_dfs_GetManagerVersion(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 *exist_flag)
{
prs_struct qbuf, rbuf;
- DFS_Q_DFS_EXIST q;
- DFS_R_DFS_EXIST r;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
+ NETDFS_Q_DFS_GETMANAGERVERSION q;
+ NETDFS_R_DFS_GETMANAGERVERSION r;
+
ZERO_STRUCT(q);
ZERO_STRUCT(r);
-
+
/* Marshall data and send request */
-
- init_dfs_q_dfs_exist(&q);
-
- CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_EXIST,
+
+ if (!init_netdfs_q_dfs_GetManagerVersion(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_GETMANAGERVERSION,
q, r,
- qbuf, rbuf,
- dfs_io_q_dfs_exist,
- dfs_io_r_dfs_exist,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_GetManagerVersion,
+ netdfs_io_r_dfs_GetManagerVersion,
NT_STATUS_UNSUCCESSFUL);
-
+
+ /* Return variables */
+ *exist_flag = r.exist_flag;
+
/* Return result */
-
- *dfs_exists = (r.status != 0);
-
- result = NT_STATUS_OK;
-
- return result;
+ return NT_STATUS_OK;
}
-NTSTATUS rpccli_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- const char *entrypath, const char *servername,
- const char *sharename, const char *comment, uint32 flags)
+NTSTATUS rpccli_dfs_Add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *path, const char *server, const char *share, const char *comment, uint32 flags)
{
prs_struct qbuf, rbuf;
- DFS_Q_DFS_ADD q;
- DFS_R_DFS_ADD r;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
+ NETDFS_Q_DFS_ADD q;
+ NETDFS_R_DFS_ADD r;
+
ZERO_STRUCT(q);
ZERO_STRUCT(r);
-
+
/* Marshall data and send request */
-
- init_dfs_q_dfs_add(&q, entrypath, servername, sharename, comment,
- flags);
-
- CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ADD,
+
+ if (!init_netdfs_q_dfs_Add(&q, path, server, share, comment, flags))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADD,
q, r,
- qbuf, rbuf,
- dfs_io_q_dfs_add,
- dfs_io_r_dfs_add,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Add,
+ netdfs_io_r_dfs_Add,
NT_STATUS_UNSUCCESSFUL);
-
+
+ /* Return variables */
+
/* Return result */
-
- result = werror_to_ntstatus(r.status);
-
- return result;
+ return werror_to_ntstatus(r.status);
}
-NTSTATUS rpccli_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- const char *entrypath, const char *servername,
- const char *sharename)
+NTSTATUS rpccli_dfs_Remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *path, const char *server, const char *share)
{
prs_struct qbuf, rbuf;
- DFS_Q_DFS_REMOVE q;
- DFS_R_DFS_REMOVE r;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
+ NETDFS_Q_DFS_REMOVE q;
+ NETDFS_R_DFS_REMOVE r;
+
ZERO_STRUCT(q);
ZERO_STRUCT(r);
-
+
/* Marshall data and send request */
-
- init_dfs_q_dfs_remove(&q, entrypath, servername, sharename);
-
- CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_REMOVE,
+
+ if (!init_netdfs_q_dfs_Remove(&q, path, server, share))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVE,
q, r,
- qbuf, rbuf,
- dfs_io_q_dfs_remove,
- dfs_io_r_dfs_remove,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Remove,
+ netdfs_io_r_dfs_Remove,
NT_STATUS_UNSUCCESSFUL);
-
+
+ /* Return variables */
+
/* Return result */
+ return werror_to_ntstatus(r.status);
+}
- result = werror_to_ntstatus(r.status);
+NTSTATUS rpccli_dfs_SetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_SETINFO q;
+ NETDFS_R_DFS_SETINFO r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_SetInfo(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_SETINFO,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_SetInfo,
+ netdfs_io_r_dfs_SetInfo,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- return result;
+NTSTATUS rpccli_dfs_GetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *path, const char *server, const char *share, uint32 level, NETDFS_DFS_INFO_CTR *info)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_GETINFO q;
+ NETDFS_R_DFS_GETINFO r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_GetInfo(&q, path, server, share, level))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_GETINFO,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_GetInfo,
+ netdfs_io_r_dfs_GetInfo,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+ *info = r.info;
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
}
-NTSTATUS rpccli_dfs_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- const char *entrypath, const char *servername,
- const char *sharename, uint32 info_level,
- DFS_INFO_CTR *ctr)
+NTSTATUS rpccli_dfs_Enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, uint32 bufsize, NETDFS_DFS_ENUMSTRUCT *info, uint32 *unknown, uint32 *total)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_ENUM q;
+ NETDFS_R_DFS_ENUM r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_Enum(&q, level, bufsize, info, unknown, total))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ENUM,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Enum,
+ netdfs_io_r_dfs_Enum,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+ *info = r.info;
+ *total = r.total;
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_Rename(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
{
prs_struct qbuf, rbuf;
- DFS_Q_DFS_GET_INFO q;
- DFS_R_DFS_GET_INFO r;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ NETDFS_Q_DFS_RENAME q;
+ NETDFS_R_DFS_RENAME r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_Rename(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_RENAME,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Rename,
+ netdfs_io_r_dfs_Rename,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_Move(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_MOVE q;
+ NETDFS_R_DFS_MOVE r;
+
ZERO_STRUCT(q);
ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_Move(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MOVE,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Move,
+ netdfs_io_r_dfs_Move,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_ManagerGetConfigInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_MANAGERGETCONFIGINFO q;
+ NETDFS_R_DFS_MANAGERGETCONFIGINFO r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
/* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_ManagerGetConfigInfo(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MANAGERGETCONFIGINFO,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_ManagerGetConfigInfo,
+ netdfs_io_r_dfs_ManagerGetConfigInfo,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- init_dfs_q_dfs_get_info(&q, entrypath, servername, sharename,
- info_level);
+NTSTATUS rpccli_dfs_ManagerSendSiteInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_MANAGERSENDSITEINFO q;
+ NETDFS_R_DFS_MANAGERSENDSITEINFO r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_ManagerSendSiteInfo(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MANAGERSENDSITEINFO,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_ManagerSendSiteInfo,
+ netdfs_io_r_dfs_ManagerSendSiteInfo,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_GET_INFO,
+NTSTATUS rpccli_dfs_AddFtRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_ADDFTROOT q;
+ NETDFS_R_DFS_ADDFTROOT r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_AddFtRoot(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADDFTROOT,
q, r,
- qbuf, rbuf,
- dfs_io_q_dfs_get_info,
- dfs_io_r_dfs_get_info,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_AddFtRoot,
+ netdfs_io_r_dfs_AddFtRoot,
NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_RemoveFtRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_REMOVEFTROOT q;
+ NETDFS_R_DFS_REMOVEFTROOT r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_RemoveFtRoot(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVEFTROOT,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_RemoveFtRoot,
+ netdfs_io_r_dfs_RemoveFtRoot,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
/* Return result */
+ return werror_to_ntstatus(r.status);
+}
- result = werror_to_ntstatus(r.status);
- *ctr = r.ctr;
+NTSTATUS rpccli_dfs_AddStdRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_ADDSTDROOT q;
+ NETDFS_R_DFS_ADDSTDROOT r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
- return result;
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_AddStdRoot(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADDSTDROOT,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_AddStdRoot,
+ netdfs_io_r_dfs_AddStdRoot,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
}
-/* Enumerate dfs shares */
+NTSTATUS rpccli_dfs_RemoveStdRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_REMOVESTDROOT q;
+ NETDFS_R_DFS_REMOVESTDROOT r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_RemoveStdRoot(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVESTDROOT,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_RemoveStdRoot,
+ netdfs_io_r_dfs_RemoveStdRoot,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
-NTSTATUS rpccli_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- uint32 info_level, DFS_INFO_CTR *ctr)
+NTSTATUS rpccli_dfs_ManagerInitialize(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
{
prs_struct qbuf, rbuf;
- DFS_Q_DFS_ENUM q;
- DFS_R_DFS_ENUM r;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ NETDFS_Q_DFS_MANAGERINITIALIZE q;
+ NETDFS_R_DFS_MANAGERINITIALIZE r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_ManagerInitialize(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MANAGERINITIALIZE,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_ManagerInitialize,
+ netdfs_io_r_dfs_ManagerInitialize,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_AddStdRootForced(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_ADDSTDROOTFORCED q;
+ NETDFS_R_DFS_ADDSTDROOTFORCED r;
+
ZERO_STRUCT(q);
ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_AddStdRootForced(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADDSTDROOTFORCED,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_AddStdRootForced,
+ netdfs_io_r_dfs_AddStdRootForced,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_GetDcAddress(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_GETDCADDRESS q;
+ NETDFS_R_DFS_GETDCADDRESS r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
/* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_GetDcAddress(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_GETDCADDRESS,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_GetDcAddress,
+ netdfs_io_r_dfs_GetDcAddress,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- init_dfs_q_dfs_enum(&q, info_level, ctr);
+NTSTATUS rpccli_dfs_SetDcAddress(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_SETDCADDRESS q;
+ NETDFS_R_DFS_SETDCADDRESS r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_SetDcAddress(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_SETDCADDRESS,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_SetDcAddress,
+ netdfs_io_r_dfs_SetDcAddress,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- r.ctr = ctr;
+NTSTATUS rpccli_dfs_FlushFtTable(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_FLUSHFTTABLE q;
+ NETDFS_R_DFS_FLUSHFTTABLE r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_FlushFtTable(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_FLUSHFTTABLE,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_FlushFtTable,
+ netdfs_io_r_dfs_FlushFtTable,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ENUM,
+NTSTATUS rpccli_dfs_Add2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_ADD2 q;
+ NETDFS_R_DFS_ADD2 r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_Add2(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADD2,
q, r,
- qbuf, rbuf,
- dfs_io_q_dfs_enum,
- dfs_io_r_dfs_enum,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Add2,
+ netdfs_io_r_dfs_Add2,
NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
+NTSTATUS rpccli_dfs_Remove2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_REMOVE2 q;
+ NETDFS_R_DFS_REMOVE2 r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_Remove2(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVE2,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_Remove2,
+ netdfs_io_r_dfs_Remove2,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
/* Return result */
+ return werror_to_ntstatus(r.status);
+}
- result = werror_to_ntstatus(r.status);
+NTSTATUS rpccli_dfs_EnumEx(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_ENUMEX q;
+ NETDFS_R_DFS_ENUMEX r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_EnumEx(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ENUMEX,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_EnumEx,
+ netdfs_io_r_dfs_EnumEx,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
+}
- return result;
+NTSTATUS rpccli_dfs_SetInfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+ prs_struct qbuf, rbuf;
+ NETDFS_Q_DFS_SETINFO2 q;
+ NETDFS_R_DFS_SETINFO2 r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ if (!init_netdfs_q_dfs_SetInfo2(&q))
+ return NT_STATUS_INVALID_PARAMETER;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_SETINFO2,
+ q, r,
+ qbuf, rbuf,
+ netdfs_io_q_dfs_SetInfo2,
+ netdfs_io_r_dfs_SetInfo2,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return variables */
+
+ /* Return result */
+ return werror_to_ntstatus(r.status);
}
+
diff --git a/source/rpc_client/cli_echo.c b/source/rpc_client/cli_echo.c
index 89de6cec941..9818fad79b5 100644
--- a/source/rpc_client/cli_echo.c
+++ b/source/rpc_client/cli_echo.c
@@ -79,6 +79,9 @@ NTSTATUS rpccli_echo_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
if (out_data) {
*out_data = TALLOC(mem_ctx, size);
+ if (!*out_data) {
+ return NT_STATUS_NO_MEMORY;
+ }
memcpy(*out_data, r.data, size);
}
diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c
index aa1cb95fda1..ac797243edc 100644
--- a/source/rpc_client/cli_lsarpc.c
+++ b/source/rpc_client/cli_lsarpc.c
@@ -221,19 +221,19 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
if (!((*domains) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
- result = NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_NO_MEMORY;
goto done;
}
if (!((*names) = TALLOC_ARRAY(mem_ctx, char *, num_sids))) {
DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
- result = NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_NO_MEMORY;
goto done;
}
if (!((*types) = TALLOC_ARRAY(mem_ctx, uint32, num_sids))) {
DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
- result = NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_NO_MEMORY;
goto done;
}
@@ -277,7 +277,9 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
POLICY_HND *pol, int num_names,
- const char **names, DOM_SID **sids,
+ const char **names,
+ const char ***dom_names,
+ DOM_SID **sids,
uint32 **types)
{
prs_struct qbuf, rbuf;
@@ -321,37 +323,54 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
if (!((*sids = TALLOC_ARRAY(mem_ctx, DOM_SID, num_names)))) {
DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
- result = NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_NO_MEMORY;
goto done;
}
if (!((*types = TALLOC_ARRAY(mem_ctx, uint32, num_names)))) {
DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
- result = NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_NO_MEMORY;
goto done;
}
+ if (dom_names != NULL) {
+ *dom_names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
+ if (*dom_names == NULL) {
+ DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+
for (i = 0; i < num_names; i++) {
- DOM_RID2 *t_rids = r.dom_rid;
+ DOM_RID *t_rids = r.dom_rid;
uint32 dom_idx = t_rids[i].rid_idx;
uint32 dom_rid = t_rids[i].rid;
DOM_SID *sid = &(*sids)[i];
/* Translate optimised sid through domain index array */
- if (dom_idx != 0xffffffff) {
+ if (dom_idx == 0xffffffff) {
+ /* Nothing to do, this is unknown */
+ ZERO_STRUCTP(sid);
+ (*types)[i] = SID_NAME_UNKNOWN;
+ continue;
+ }
- sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
+ sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
- if (dom_rid != 0xffffffff) {
- sid_append_rid(sid, dom_rid);
- }
+ if (dom_rid != 0xffffffff) {
+ sid_append_rid(sid, dom_rid);
+ }
- (*types)[i] = t_rids[i].type;
- } else {
- ZERO_STRUCTP(sid);
- (*types)[i] = SID_NAME_UNKNOWN;
+ (*types)[i] = t_rids[i].type;
+
+ if (dom_names == NULL) {
+ continue;
}
+
+ (*dom_names)[i] = rpcstr_pull_unistr2_talloc(
+ *dom_names, &ref.ref_dom[dom_idx].uni_dom_name);
}
done:
@@ -359,6 +378,76 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
return result;
}
+NTSTATUS rpccli_lsa_query_info_policy_new(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol, uint16 info_class,
+ LSA_INFO_CTR *ctr)
+{
+ prs_struct qbuf, rbuf;
+ LSA_Q_QUERY_INFO q;
+ LSA_R_QUERY_INFO r;
+ NTSTATUS result;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ init_q_query(&q, pol, info_class);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFOPOLICY,
+ q, r,
+ qbuf, rbuf,
+ lsa_io_q_query,
+ lsa_io_r_query,
+ NT_STATUS_UNSUCCESSFUL);
+
+ result = r.status;
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+
+ *ctr = r.ctr;
+
+ return result;
+}
+
+NTSTATUS rpccli_lsa_query_info_policy2_new(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol, uint16 info_class,
+ LSA_INFO_CTR2 *ctr)
+{
+ prs_struct qbuf, rbuf;
+ LSA_Q_QUERY_INFO2 q;
+ LSA_R_QUERY_INFO2 r;
+ NTSTATUS result;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ init_q_query2(&q, pol, info_class);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFO2,
+ q, r,
+ qbuf, rbuf,
+ lsa_io_q_query_info2,
+ lsa_io_r_query_info2,
+ NT_STATUS_UNSUCCESSFUL);
+
+ result = r.status;
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+
+ *ctr = r.ctr;
+
+ return result;
+}
+
+
+
/** Query info policy
*
* @param domain_sid - returned remote server's domain sid */
@@ -396,34 +485,42 @@ NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli,
switch (info_class) {
case 3:
- if (domain_name && (r.dom.id3.buffer_dom_name != 0)) {
+ if (domain_name && (r.ctr.info.id3.buffer_dom_name != 0)) {
*domain_name = unistr2_tdup(mem_ctx,
- &r.dom.id3.
+ &r.ctr.info.id3.
uni_domain_name);
+ if (!*domain_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
- if (domain_sid && (r.dom.id3.buffer_dom_sid != 0)) {
+ if (domain_sid && (r.ctr.info.id3.buffer_dom_sid != 0)) {
*domain_sid = TALLOC_P(mem_ctx, DOM_SID);
- if (*domain_sid) {
- sid_copy(*domain_sid, &r.dom.id3.dom_sid.sid);
+ if (!*domain_sid) {
+ return NT_STATUS_NO_MEMORY;
}
+ sid_copy(*domain_sid, &r.ctr.info.id3.dom_sid.sid);
}
break;
case 5:
- if (domain_name && (r.dom.id5.buffer_dom_name != 0)) {
+ if (domain_name && (r.ctr.info.id5.buffer_dom_name != 0)) {
*domain_name = unistr2_tdup(mem_ctx,
- &r.dom.id5.
+ &r.ctr.info.id5.
uni_domain_name);
+ if (!*domain_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
- if (domain_sid && (r.dom.id5.buffer_dom_sid != 0)) {
+ if (domain_sid && (r.ctr.info.id5.buffer_dom_sid != 0)) {
*domain_sid = TALLOC_P(mem_ctx, DOM_SID);
- if (*domain_sid) {
- sid_copy(*domain_sid, &r.dom.id5.dom_sid.sid);
+ if (!*domain_sid) {
+ return NT_STATUS_NO_MEMORY;
}
+ sid_copy(*domain_sid, &r.ctr.info.id5.dom_sid.sid);
}
break;
@@ -483,35 +580,48 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
ZERO_STRUCTP(domain_guid);
- if (domain_name && r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
+ if (domain_name && r.ctr.info.id12.hdr_nb_dom_name.buffer) {
*domain_name = unistr2_tdup(mem_ctx,
- &r.info.dns_dom_info
+ &r.ctr.info.id12
.uni_nb_dom_name);
+ if (!*domain_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
- if (dns_name && r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
+ if (dns_name && r.ctr.info.id12.hdr_dns_dom_name.buffer) {
*dns_name = unistr2_tdup(mem_ctx,
- &r.info.dns_dom_info
+ &r.ctr.info.id12
.uni_dns_dom_name);
+ if (!*dns_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
- if (forest_name && r.info.dns_dom_info.hdr_forest_name.buffer) {
+ if (forest_name && r.ctr.info.id12.hdr_forest_name.buffer) {
*forest_name = unistr2_tdup(mem_ctx,
- &r.info.dns_dom_info
+ &r.ctr.info.id12
.uni_forest_name);
+ if (!*forest_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
if (domain_guid) {
*domain_guid = TALLOC_P(mem_ctx, struct uuid);
+ if (!*domain_guid) {
+ return NT_STATUS_NO_MEMORY;
+ }
memcpy(*domain_guid,
- &r.info.dns_dom_info.dom_guid,
+ &r.ctr.info.id12.dom_guid,
sizeof(struct uuid));
}
- if (domain_sid && r.info.dns_dom_info.ptr_dom_sid != 0) {
+ if (domain_sid && r.ctr.info.id12.ptr_dom_sid != 0) {
*domain_sid = TALLOC_P(mem_ctx, DOM_SID);
- if (*domain_sid) {
- sid_copy(*domain_sid,
- &r.info.dns_dom_info.dom_sid.sid);
+ if (!*domain_sid) {
+ return NT_STATUS_NO_MEMORY;
}
+ sid_copy(*domain_sid,
+ &r.ctr.info.id12.dom_sid.sid);
}
done:
@@ -519,6 +629,41 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
return result;
}
+NTSTATUS rpccli_lsa_set_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol, uint16 info_class,
+ LSA_INFO_CTR ctr)
+{
+ prs_struct qbuf, rbuf;
+ LSA_Q_SET_INFO q;
+ LSA_R_SET_INFO r;
+ NTSTATUS result;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ init_q_set(&q, pol, info_class, ctr);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_SETINFOPOLICY,
+ q, r,
+ qbuf, rbuf,
+ lsa_io_q_set,
+ lsa_io_r_set,
+ NT_STATUS_UNSUCCESSFUL);
+
+ result = r.status;
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Return output parameters */
+
+ done:
+
+ return result;
+}
+
+
/**
* Enumerate list of trusted domains
*
@@ -1298,6 +1443,42 @@ done:
return result;
}
+NTSTATUS rpccli_lsa_open_trusted_domain_by_name(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol, const char *name, uint32 access_mask,
+ POLICY_HND *trustdom_pol)
+{
+ prs_struct qbuf, rbuf;
+ LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME q;
+ LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME r;
+ NTSTATUS result;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise input parameters */
+
+ init_lsa_q_open_trusted_domain_by_name(&q, pol, name, access_mask);
+
+ /* Marshall data and send request */
+
+ CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENTRUSTDOMBYNAME,
+ q, r,
+ qbuf, rbuf,
+ lsa_io_q_open_trusted_domain_by_name,
+ lsa_io_r_open_trusted_domain_by_name,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (NT_STATUS_IS_OK(result)) {
+ *trustdom_pol = r.handle;
+ }
+
+ return result;
+}
+
NTSTATUS rpccli_lsa_query_trusted_domain_info_by_sid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol,
@@ -1372,3 +1553,39 @@ done:
return result;
}
+
+NTSTATUS cli_lsa_query_domain_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol,
+ uint16 info_class, LSA_DOM_INFO_UNION **info)
+{
+ prs_struct qbuf, rbuf;
+ LSA_Q_QUERY_DOM_INFO_POLICY q;
+ LSA_R_QUERY_DOM_INFO_POLICY r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ init_q_query_dom_info(&q, pol, info_class);
+
+ CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYDOMINFOPOL,
+ q, r,
+ qbuf, rbuf,
+ lsa_io_q_query_dom_info,
+ lsa_io_r_query_dom_info,
+ NT_STATUS_UNSUCCESSFUL);
+
+ result = r.status;
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ *info = r.info;
+
+done:
+ return result;
+}
+
diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c
index b5addf33751..33f1d1d25ba 100644
--- a/source/rpc_client/cli_netlogon.c
+++ b/source/rpc_client/cli_netlogon.c
@@ -301,7 +301,8 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
}
/* Calculate the session key and client credentials */
- creds_client_init(dc,
+ creds_client_init(*neg_flags_inout,
+ dc,
&clnt_chal_send,
&srv_chal_recv,
machine_pwd,
@@ -468,8 +469,8 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
if (dc_unc != NULL) {
char *tmp;
- if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp,
- &r.uni_dc_unc) < 0) {
+ tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dc_unc);
+ if (tmp == NULL) {
return WERR_GENERAL_FAILURE;
}
if (*tmp == '\\') tmp += 1;
@@ -485,8 +486,8 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
if (dc_address != NULL) {
char *tmp;
- if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp,
- &r.uni_dc_address) < 0) {
+ tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dc_address);
+ if (tmp == NULL) {
return WERR_GENERAL_FAILURE;
}
if (*tmp == '\\') tmp += 1;
@@ -509,14 +510,14 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
}
if ((domain_name_out != NULL) &&
- (rpcstr_pull_unistr2_talloc(mem_ctx, domain_name_out,
- &r.uni_domain_name) < 1)) {
+ ((*domain_name_out = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &r.uni_domain_name)) == NULL)) {
return WERR_GENERAL_FAILURE;
}
if ((forest_name != NULL) &&
- (rpcstr_pull_unistr2_talloc(mem_ctx, forest_name,
- &r.uni_forest_name) < 1)) {
+ ((*forest_name = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &r.uni_forest_name)) == NULL)) {
return WERR_GENERAL_FAILURE;
}
@@ -525,14 +526,14 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
}
if ((dc_site_name != NULL) &&
- (rpcstr_pull_unistr2_talloc(mem_ctx, dc_site_name,
- &r.uni_dc_site_name) < 1)) {
+ ((*dc_site_name = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &r.uni_dc_site_name)) == NULL)) {
return WERR_GENERAL_FAILURE;
}
if ((client_site_name != NULL) &&
- (rpcstr_pull_unistr2_talloc(mem_ctx, client_site_name,
- &r.uni_client_site_name) < 1)) {
+ ((*client_site_name = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &r.uni_client_site_name)) == NULL)) {
return WERR_GENERAL_FAILURE;
}
@@ -571,8 +572,8 @@ WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
}
if ((site_name != NULL) &&
- (rpcstr_pull_unistr2_talloc(mem_ctx, site_name,
- &r.uni_site_name) < 1)) {
+ ((*site_name = rpcstr_pull_unistr2_talloc(
+ mem_ctx, &r.uni_site_name)) == NULL)) {
return WERR_GENERAL_FAILURE;
}
@@ -883,7 +884,6 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
memset(info3->lm_sess_key, '\0', 8);
}
- memset(&info3->acct_flags, '\0', 4);
for (i=0; i < 7; i++) {
memset(&info3->unknown[i], '\0', 4);
}
diff --git a/source/rpc_client/cli_pipe.c b/source/rpc_client/cli_pipe.c
index c5c3b49d15d..11eb21df446 100644
--- a/source/rpc_client/cli_pipe.c
+++ b/source/rpc_client/cli_pipe.c
@@ -619,7 +619,7 @@ static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_H
DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
"pipe %s fnum 0x%x!\n",
- nt_errstr(fault_resp.status),
+ dcerpc_errstr(NT_STATUS_V(fault_resp.status)),
cli->cli->desthost,
cli->pipe_name,
(unsigned int)cli->fnum));
@@ -744,8 +744,8 @@ static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
char *rparam = NULL;
uint32 rparam_len = 0;
uint16 setup[2];
- char *pdata = data ? prs_data_p(data) : NULL;
- uint32 data_len = data ? prs_offset(data) : 0;
+ char *pdata = prs_data_p(data);
+ uint32 data_len = prs_offset(data);
char *prdata = NULL;
uint32 rdata_len = 0;
uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : RPC_MAX_PDU_FRAG_LEN;
@@ -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);
+ &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL);
if (ret) {
DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
@@ -1090,7 +1090,7 @@ static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
Creates the internals of a DCE/RPC bind request or alter context PDU.
********************************************************************/
-static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type,
+static NTSTATUS create_bind_or_alt_ctx_internal(enum RPC_PKT_TYPE pkt_type,
prs_struct *rpc_out,
uint32 rpc_call_id,
RPC_IFACE *abstract,
@@ -2141,6 +2141,24 @@ static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
return NT_STATUS_INVALID_INFO_CLASS;
}
+ /* For NTLMSSP ensure the server gave us the auth_level we wanted. */
+ if (auth_type == PIPE_AUTH_TYPE_NTLMSSP || auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
+ if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+ if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP signing and server refused.\n"));
+ prs_mem_free(&rbuf);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+ if (!(cli->auth.a_u.ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+ DEBUG(0,("cli_finish_bind_auth: requested NTLMSSSP sealing and server refused.\n"));
+ prs_mem_free(&rbuf);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+
/* Pipe is bound - set up auth_type and auth_level data. */
cli->auth.auth_type = auth_type;
@@ -2171,6 +2189,13 @@ static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe
*perr = NT_STATUS_NO_MEMORY;
+ /* sanity check to protect against crashes */
+
+ if ( !cli ) {
+ *perr = NT_STATUS_INVALID_HANDLE;
+ return NULL;
+ }
+
/* The pipe name index must fall within our array */
SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
@@ -2703,7 +2728,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
/* Only get a new TGT if username/password are given. */
if (username && password) {
- int ret = kerberos_kinit_password(username, password, 0, NULL, NULL);
+ int ret = kerberos_kinit_password(username, password, 0, NULL);
if (ret) {
cli_rpc_pipe_close(result);
return NULL;
@@ -2741,7 +2766,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
Close an open named pipe over SMB. Free any authentication data.
****************************************************************************/
-void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
+ void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
{
if (!cli_close(cli->cli, cli->fnum)) {
DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c
index fb95da97aef..07b876cc22c 100644
--- a/source/rpc_client/cli_samr.c
+++ b/source/rpc_client/cli_samr.c
@@ -360,7 +360,8 @@ NTSTATUS rpccli_samr_del_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
NTSTATUS rpccli_samr_query_userinfo(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
- POLICY_HND *user_pol, uint16 switch_value,
+ const POLICY_HND *user_pol,
+ uint16 switch_value,
SAM_USERINFO_CTR **ctr)
{
prs_struct qbuf, rbuf;
@@ -639,7 +640,7 @@ NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli,
**/
NTSTATUS rpccli_samr_enum_dom_users(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *pol, uint32 *start_idx, uint16 acb_mask,
+ POLICY_HND *pol, uint32 *start_idx, uint32 acb_mask,
uint32 size, char ***dom_users, uint32 **rids,
uint32 *num_dom_users)
{
@@ -660,7 +661,7 @@ NTSTATUS rpccli_samr_enum_dom_users(struct rpc_pipe_client *cli, TALLOC_CTX *mem
/* Fill query structure with parameters */
- init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, 0, size);
+ init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, size);
CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_USERS,
q, r,
@@ -1123,6 +1124,46 @@ NTSTATUS rpccli_samr_query_dom_info(struct rpc_pipe_client *cli,
return result;
}
+/* Set domain info */
+
+NTSTATUS rpccli_samr_set_domain_info(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ POLICY_HND *domain_pol,
+ uint16 switch_value,
+ SAM_UNK_CTR *ctr)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_SET_DOMAIN_INFO q;
+ SAMR_R_SET_DOMAIN_INFO r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DEBUG(10,("cli_samr_set_domain_info\n"));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ init_samr_q_set_domain_info(&q, domain_pol, switch_value, ctr);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_DOMAIN_INFO,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_set_domain_info,
+ samr_io_r_set_domain_info,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ if (!NT_STATUS_IS_OK(result = r.status)) {
+ goto done;
+ }
+
+ done:
+
+ return result;
+}
+
/* User change password */
NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
@@ -1212,13 +1253,12 @@ NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
const char *username,
const char *newpassword,
const char *oldpassword,
- SAM_UNK_INFO_1 **info,
- SAMR_CHANGE_REJECT **reject)
+ SAM_UNK_INFO_1 *info,
+ SAMR_CHANGE_REJECT *reject)
{
prs_struct qbuf, rbuf;
- SAMR_Q_CHGPASSWD3 q;
- SAMR_R_CHGPASSWD3 r;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ SAMR_Q_CHGPASSWD_USER3 q;
+ SAMR_R_CHGPASSWD_USER3 r;
uchar new_nt_password[516];
uchar new_lm_password[516];
@@ -1232,14 +1272,11 @@ NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
- DEBUG(10,("rpccli_samr_chgpasswd3\n"));
+ DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
ZERO_STRUCT(q);
ZERO_STRUCT(r);
- *info = NULL;
- *reject = NULL;
-
/* Calculate the MD4 hash (NT compatible) of the password */
E_md4hash(oldpassword, old_nt_hash);
E_md4hash(newpassword, new_nt_hash);
@@ -1268,30 +1305,24 @@ NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
/* Marshall data and send request */
- init_samr_q_chgpasswd3(&q, srv_name_slash, username,
- new_nt_password,
- old_nt_hash_enc,
- new_lm_password,
- old_lanman_hash_enc);
+ init_samr_q_chgpasswd_user3(&q, srv_name_slash, username,
+ new_nt_password,
+ old_nt_hash_enc,
+ new_lm_password,
+ old_lanman_hash_enc);
+ r.info = info;
+ r.reject = reject;
- CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD3,
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD_USER3,
q, r,
qbuf, rbuf,
- samr_io_q_chgpasswd3,
- samr_io_r_chgpasswd3,
+ samr_io_q_chgpasswd_user3,
+ samr_io_r_chgpasswd_user3,
NT_STATUS_UNSUCCESSFUL);
/* Return output parameters */
- if (!NT_STATUS_IS_OK(result = r.status)) {
- *info = &r.info;
- *reject = &r.reject;
- goto done;
- }
-
- done:
-
- return result;
+ return r.status;
}
/* This function returns the bizzare set of (max_entries, max_size) required
@@ -1549,7 +1580,7 @@ NTSTATUS rpccli_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *me
/* Set userinfo */
NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *user_pol, uint16 switch_value,
+ const POLICY_HND *user_pol, uint16 switch_value,
DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
{
prs_struct qbuf, rbuf;
@@ -1600,7 +1631,7 @@ NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
/* Set userinfo2 */
NTSTATUS rpccli_samr_set_userinfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *user_pol, uint16 switch_value,
+ const POLICY_HND *user_pol, uint16 switch_value,
DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
{
prs_struct qbuf, rbuf;
@@ -1777,7 +1808,7 @@ NTSTATUS rpccli_samr_remove_sid_foreign_domain(struct rpc_pipe_client *cli,
/* Query user security object */
NTSTATUS rpccli_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *user_pol, uint16 switch_value,
+ POLICY_HND *user_pol, uint32 sec_info,
TALLOC_CTX *ctx, SEC_DESC_BUF **sec_desc_buf)
{
prs_struct qbuf, rbuf;
@@ -1792,7 +1823,7 @@ NTSTATUS rpccli_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_
/* Marshall data and send request */
- init_samr_q_query_sec_obj(&q, user_pol, switch_value);
+ init_samr_q_query_sec_obj(&q, user_pol, sec_info);
CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_SEC_OBJECT,
q, r,
@@ -1809,6 +1840,41 @@ NTSTATUS rpccli_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_
return result;
}
+/* Set user security object */
+
+NTSTATUS rpccli_samr_set_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *user_pol, uint32 sec_info,
+ SEC_DESC_BUF *sec_desc_buf)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_SET_SEC_OBJ q;
+ SAMR_R_SET_SEC_OBJ r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DEBUG(10,("cli_samr_set_sec_obj\n"));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ init_samr_q_set_sec_obj(&q, user_pol, sec_info, sec_desc_buf);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_SEC_OBJECT,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_set_sec_obj,
+ samr_io_r_set_sec_obj,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ return result;
+}
+
+
/* Get domain password info */
NTSTATUS rpccli_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
@@ -1849,6 +1915,50 @@ NTSTATUS rpccli_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem
return result;
}
+/* Get domain password info */
+
+NTSTATUS rpccli_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol, uint16 *min_pwd_length,
+ uint32 *password_properties, uint32 *unknown1)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_GET_USRDOM_PWINFO q;
+ SAMR_R_GET_USRDOM_PWINFO r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DEBUG(10,("cli_samr_get_usrdom_pwinfo\n"));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ init_samr_q_get_usrdom_pwinfo(&q, pol);
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_GET_USRDOM_PWINFO,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_get_usrdom_pwinfo,
+ samr_io_r_get_usrdom_pwinfo,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (NT_STATUS_IS_OK(result)) {
+ if (min_pwd_length)
+ *min_pwd_length = r.min_pwd_length;
+ if (password_properties)
+ *password_properties = r.password_properties;
+ if (unknown1)
+ *unknown1 = r.unknown_1;
+ }
+
+ return result;
+}
+
+
/* Lookup Domain Name */
NTSTATUS rpccli_samr_lookup_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
diff --git a/source/rpc_client/cli_spoolss.c b/source/rpc_client/cli_spoolss.c
index 749885dbb4f..d6d4417da37 100644
--- a/source/rpc_client/cli_spoolss.c
+++ b/source/rpc_client/cli_spoolss.c
@@ -338,7 +338,7 @@ static BOOL decode_jobs_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
uint32 i;
*jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_1, num_jobs);
- if (!jobs) {
+ if (*jobs == NULL) {
return False;
}
prs_set_offset(&buffer->prs,0);
@@ -361,7 +361,7 @@ static BOOL decode_jobs_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
uint32 i;
*jobs = TALLOC_ARRAY(mem_ctx, JOB_INFO_2, num_jobs);
- if (!jobs) {
+ if (*jobs == NULL) {
return False;
}
prs_set_offset(&buffer->prs,0);
@@ -384,7 +384,7 @@ static BOOL decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
int i;
*forms = TALLOC_ARRAY(mem_ctx, FORM_1, num_forms);
- if (!forms) {
+ if (*forms == NULL) {
return False;
}
prs_set_offset(&buffer->prs,0);
diff --git a/source/rpc_parse/parse_buffer.c b/source/rpc_parse/parse_buffer.c
index 36d8eda8474..21dddfa3cf5 100644
--- a/source/rpc_parse/parse_buffer.c
+++ b/source/rpc_parse/parse_buffer.c
@@ -47,7 +47,7 @@ BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buff
{
prs_debug(ps, depth, desc, "prs_rpcbuffer");
depth++;
-
+
/* reading */
if (UNMARSHALLING(ps)) {
buffer->size=0;
@@ -115,10 +115,15 @@ BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **b
if ( !data_p )
return True;
-
+
if ( UNMARSHALLING(ps) ) {
if ( !(*buffer = PRS_ALLOC_MEM(ps, RPC_BUFFER, 1)) )
return False;
+ } else {
+ /* Marshalling case. - coverity paranoia - should already be ok if data_p != 0 */
+ if (!*buffer) {
+ return True;
+ }
}
return prs_rpcbuffer( desc, ps, depth, *buffer);
@@ -138,7 +143,11 @@ BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size)
if ( buffer_size == 0x0 )
return True;
-
+
+ if (!buffer) {
+ return False;
+ }
+
ps= &buffer->prs;
/* damn, I'm doing the reverse operation of prs_grow() :) */
@@ -371,19 +380,14 @@ BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16
/* we're going to add two more bytes here in case this
is the last string in the array and we need to add
an extra NULL for termination */
- if (l_chaine > 0)
- {
- uint16 *tc2;
-
+ if (l_chaine > 0) {
realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);
/* Yes this should be realloc - it's freed below. JRA */
- if((tc2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) {
- SAFE_FREE(chaine2);
+ if((chaine2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) {
return False;
}
- else chaine2 = tc2;
memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16));
l_chaine2+=l_chaine+1;
}
diff --git a/source/rpc_parse/parse_dfs.c b/source/rpc_parse/parse_dfs.c
index f102e950042..f1d07053025 100644
--- a/source/rpc_parse/parse_dfs.c
+++ b/source/rpc_parse/parse_dfs.c
@@ -1,24 +1,6 @@
-/*
- * Unix SMB/CIFS implementation.
- * MSDfs RPC Pipe client / server routines
- * Copyright (C) Andrew Tridgell 1992-2000,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
- * Copyright (C) Shirish Kalele 2000.
- * Copyright (C) Jeremy Allison 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.
+/*
+ * Unix SMB/CIFS implementation.
+ * parser auto-generated by pidl. DO NOT MODIFY!
*/
#include "includes.h"
@@ -26,519 +8,2660 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_PARSE
-/*******************************************************************
-Make a DFS_Q_DFS_QUERY structure
-*******************************************************************/
-
-void init_dfs_q_dfs_exist(DFS_Q_DFS_EXIST *q_d)
+/* netdfs structures */
+BOOL init_netdfs_dfs_Info0(NETDFS_DFS_INFO0 *v)
{
- q_d->dummy = 0;
+ DEBUG(5,("init_netdfs_dfs_Info0\n"));
+
+ return True;
}
-/*************************************************************
- Read/write a DFS_Q_DFS_EXIST structure - dummy...
- ************************************************************/
+BOOL netdfs_io_dfs_Info0_p(const char *desc, NETDFS_DFS_INFO0 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info0_p");
+ depth++;
+ return True;
+}
-BOOL dfs_io_q_dfs_exist(const char *desc, DFS_Q_DFS_EXIST *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info0_d(const char *desc, NETDFS_DFS_INFO0 *v, prs_struct *ps, int depth)
{
- if(q_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_q_dfs_exist");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info0_d");
+ depth++;
+ return True;
+}
+BOOL init_netdfs_dfs_Info1(NETDFS_DFS_INFO1 *v, const char *path)
+{
+ DEBUG(5,("init_netdfs_dfs_Info1\n"));
+
+ if (path) {
+ v->ptr0_path = 1;
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_path = 0;
+ }
+
return True;
}
-
-/*************************************************************
- Read/write a DFS_R_DFS_EXIST structure
- ************************************************************/
-BOOL dfs_io_r_dfs_exist(const char *desc, DFS_R_DFS_EXIST *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info1_p(const char *desc, NETDFS_DFS_INFO1 *v, prs_struct *ps, int depth)
{
- if(q_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_r_dfs_exist");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info1_p");
depth++;
-
- if(!prs_align(ps))
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
+
+
+ return True;
+}
- if(!prs_uint32("exist flag", ps, 0, &q_d->status))
+BOOL netdfs_io_dfs_Info1_d(const char *desc, NETDFS_DFS_INFO1 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
-
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info1_d");
+ depth++;
+ if (v->ptr0_path) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+ return False;
+ }
+
return True;
}
-
-/*******************************************************************
-Make a DFS_Q_DFS_REMOVE structure
-*******************************************************************/
-BOOL init_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, const char *entrypath,
- const char *servername, const char *sharename)
+BOOL init_netdfs_dfs_Info2(NETDFS_DFS_INFO2 *v, const char *path, const char *comment, uint32 state, uint32 num_stores)
{
- DEBUG(5,("init_dfs_q_dfs_remove\n"));
- init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE);
- init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE);
- init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE);
- q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
+ DEBUG(5,("init_netdfs_dfs_Info2\n"));
+
+ if (path) {
+ v->ptr0_path = 1;
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_path = 0;
+ }
+
+ if (comment) {
+ v->ptr0_comment = 1;
+ init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_comment = 0;
+ }
+
+ v->state = state;
+
+ v->num_stores = num_stores;
+
return True;
}
-/*******************************************************************
-Read/write a DFS_Q_DFS_REMOVE structure
-*******************************************************************/
-
-BOOL dfs_io_q_dfs_remove(const char *desc, DFS_Q_DFS_REMOVE *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info2_p(const char *desc, NETDFS_DFS_INFO2 *v, prs_struct *ps, int depth)
{
- if(q_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_q_dfs_remove");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info2_p");
depth++;
-
- if(!prs_align(ps))
- return False;
-
- if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
-
- if(!prs_align(ps))
+
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
-
- if(!prs_uint32("ptr_ServerName", ps, depth, &q_d->ptr_ServerName))
+
+
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
- if(q_d->ptr_ServerName)
- if (!smb_io_unistr2("ServerName",&q_d->ServerName, q_d->ptr_ServerName, ps, depth))
- return False;
- if(!prs_align(ps))
+
+ if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
return False;
+
+ return True;
+}
- if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
+BOOL netdfs_io_dfs_Info2_d(const char *desc, NETDFS_DFS_INFO2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(q_d->ptr_ShareName)
- if (!smb_io_unistr2("ShareName",&q_d->ShareName, q_d->ptr_ShareName, ps, depth))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info2_d");
+ depth++;
+ if (v->ptr0_path) {
+ if (!prs_align_custom(ps, 4))
return False;
- if(!prs_align(ps))
- return False;
-
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+ return False;
+ }
+
+ if (v->ptr0_comment) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+ return False;
+ }
+
+
+
return True;
}
-/*******************************************************************
-Read/write a DFS_R_DFS_REMOVE structure
-*******************************************************************/
+BOOL init_netdfs_dfs_StorageInfo(NETDFS_DFS_STORAGEINFO *v, uint32 state, const char *server, const char *share)
+{
+ DEBUG(5,("init_netdfs_dfs_StorageInfo\n"));
+
+ v->state = state;
+
+ if (server) {
+ v->ptr0_server = 1;
+ init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_server = 0;
+ }
+
+ if (share) {
+ v->ptr0_share = 1;
+ init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_share = 0;
+ }
+
+ return True;
+}
-BOOL dfs_io_r_dfs_remove(const char *desc, DFS_R_DFS_REMOVE *r_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_StorageInfo_p(const char *desc, NETDFS_DFS_STORAGEINFO *v, prs_struct *ps, int depth)
{
- if(r_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_r_dfs_remove");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_StorageInfo_p");
depth++;
-
- if(!prs_werror("status", ps, depth, &r_d->status))
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
-
+
+ if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
+ return False;
+
+
+ if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+ return False;
+
+
return True;
}
-/*******************************************************************
-Make a DFS_Q_DFS_ADD structure
-*******************************************************************/
+BOOL netdfs_io_dfs_StorageInfo_d(const char *desc, NETDFS_DFS_STORAGEINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_StorageInfo_d");
+ depth++;
+
+ if (v->ptr0_server) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+ return False;
+ }
+
+ if (v->ptr0_share) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
+ return False;
+ }
+
+ return True;
+}
-BOOL init_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, const char *entrypath,
- const char *servername, const char *sharename,
- const char *comment, uint32 flags)
+BOOL init_netdfs_dfs_Info3(NETDFS_DFS_INFO3 *v, const char *path, const char *comment, uint32 state, uint32 num_stores, NETDFS_DFS_STORAGEINFO **stores)
{
- DEBUG(5,("init_dfs_q_dfs_add\n"));
- q_d->ptr_DfsEntryPath = q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
- init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE);
- init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE);
- init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE);
- if(comment != NULL) {
- init_unistr2(&q_d->Comment, comment,UNI_STR_TERMINATE);
- q_d->ptr_Comment = 1;
+ DEBUG(5,("init_netdfs_dfs_Info3\n"));
+
+ if (path) {
+ v->ptr0_path = 1;
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
} else {
- q_d->ptr_Comment = 0;
+ v->ptr0_path = 0;
}
-
- q_d->Flags = flags;
+
+ if (comment) {
+ v->ptr0_comment = 1;
+ init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_comment = 0;
+ }
+
+ v->state = state;
+
+ v->num_stores = num_stores;
+
+ if (stores) {
+ v->ptr0_stores = 1;
+ v->stores = *stores;
+ } else {
+ v->ptr0_stores = 0;
+ }
+
return True;
}
-/************************************************************
- Read/write a DFS_Q_DFS_ADD structure
- ************************************************************/
-
-BOOL dfs_io_q_dfs_add(const char *desc, DFS_Q_DFS_ADD *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info3_p(const char *desc, NETDFS_DFS_INFO3 *v, prs_struct *ps, int depth)
{
- if(q_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_q_dfs_add");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info3_p");
depth++;
-
- if(!prs_align(ps))
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
-
- if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
+
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
- if(!prs_align(ps))
+
+
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
-
- if(!smb_io_unistr2("ServerName",&q_d->ServerName, 1, ps, depth))
+
+ if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
return False;
- if(!prs_align(ps))
+
+ if (!prs_uint32("ptr0_stores", ps, depth, &v->ptr0_stores))
return False;
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info3_d(const char *desc, NETDFS_DFS_INFO3 *v, prs_struct *ps, int depth)
+{
+ uint32 i_stores_1;
+
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info3_d");
+ depth++;
+ if (v->ptr0_path) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+ return False;
+ }
+
+ if (v->ptr0_comment) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+ return False;
+ }
+
+
+
+ if (v->ptr0_stores) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_stores", ps, depth, &v->size_stores))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->stores = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->stores)*v->num_stores);
+ }
+ for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+ if (!netdfs_io_dfs_StorageInfo_p("stores", &v->stores[i_stores_1], ps, depth))
+ return False;
+ }
+ for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+ if (!netdfs_io_dfs_StorageInfo_d("stores", &v->stores[i_stores_1], ps, depth))
+ return False;
+ }
+ }
+
+ return True;
+}
- if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
+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)
+{
+ DEBUG(5,("init_netdfs_dfs_Info4\n"));
+
+ if (path) {
+ v->ptr0_path = 1;
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_path = 0;
+ }
+
+ if (comment) {
+ v->ptr0_comment = 1;
+ init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_comment = 0;
+ }
+
+ v->state = state;
+
+ v->timeout = timeout;
+
+
+
+ v->num_stores = num_stores;
+
+ if (stores) {
+ v->ptr0_stores = 1;
+ v->stores = *stores;
+ } else {
+ v->ptr0_stores = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info4_p(const char *desc, NETDFS_DFS_INFO4 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!smb_io_unistr2("ShareName",&q_d->ShareName, 1, ps, depth))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info4_p");
+ depth++;
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
- if(!prs_align(ps))
+
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
-
- if(!prs_uint32("ptr_Comment", ps, depth, &q_d->ptr_Comment))
+
+
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
- if(!smb_io_unistr2("",&q_d->Comment, q_d->ptr_Comment , ps, depth))
+
+ if (!prs_uint32("timeout", ps, depth, &v->timeout))
return False;
- if(!prs_align(ps))
+
+ if (!smb_io_uuid("guid", &v->guid, ps, depth))
return False;
+
+ if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
+ return False;
+
+ if (!prs_uint32("ptr0_stores", ps, depth, &v->ptr0_stores))
+ return False;
+
+
+ return True;
+}
- if(!prs_uint32("Flags", ps, depth, &q_d->Flags))
- return True;
-
+BOOL netdfs_io_dfs_Info4_d(const char *desc, NETDFS_DFS_INFO4 *v, prs_struct *ps, int depth)
+{
+ uint32 i_stores_1;
+
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info4_d");
+ depth++;
+ if (v->ptr0_path) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+ return False;
+ }
+
+ if (v->ptr0_comment) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+ return False;
+ }
+
+
+
+
+
+ if (v->ptr0_stores) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_stores", ps, depth, &v->size_stores))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->stores = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->stores)*v->num_stores);
+ }
+ for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+ if (!netdfs_io_dfs_StorageInfo_p("stores", &v->stores[i_stores_1], ps, depth))
+ return False;
+ }
+ for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+ if (!netdfs_io_dfs_StorageInfo_d("stores", &v->stores[i_stores_1], ps, depth))
+ return False;
+ }
+ }
+
return True;
}
-/************************************************************
- Read/write a DFS_R_DFS_ADD structure
- ************************************************************/
+BOOL init_netdfs_dfs_Info100(NETDFS_DFS_INFO100 *v, const char *comment)
+{
+ DEBUG(5,("init_netdfs_dfs_Info100\n"));
+
+ if (comment) {
+ v->ptr0_comment = 1;
+ init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_comment = 0;
+ }
+
+ return True;
+}
-BOOL dfs_io_r_dfs_add(const char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info100_p(const char *desc, NETDFS_DFS_INFO100 *v, prs_struct *ps, int depth)
{
- if(r_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_r_dfs_add");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info100_p");
depth++;
-
- if(!prs_werror("status", ps, depth, &r_d->status))
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
-
+
+
return True;
}
-BOOL init_dfs_q_dfs_get_info(DFS_Q_DFS_GET_INFO *q_d, const char *entrypath,
- const char *servername, const char *sharename,
- uint32 info_level)
+BOOL netdfs_io_dfs_Info100_d(const char *desc, NETDFS_DFS_INFO100 *v, prs_struct *ps, int depth)
{
- DEBUG(5,("init_dfs_q2_get_info\n"));
- init_unistr2(&q_d->uni_path, entrypath, UNI_STR_TERMINATE);
- init_unistr2(&q_d->uni_server, servername, UNI_STR_TERMINATE);
- init_unistr2(&q_d->uni_share, sharename, UNI_STR_TERMINATE);
- q_d->level = info_level;
- q_d->ptr_server = q_d->ptr_share = 1;
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info100_d");
+ depth++;
+ if (v->ptr0_comment) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+ return False;
+ }
+
return True;
}
-/************************************************************
- Read/write a DFS_Q_GET_INFO structure
- ************************************************************/
+BOOL init_netdfs_dfs_Info101(NETDFS_DFS_INFO101 *v, uint32 state)
+{
+ DEBUG(5,("init_netdfs_dfs_Info101\n"));
+
+ v->state = state;
+
+ return True;
+}
-BOOL dfs_io_q_dfs_get_info(const char *desc, DFS_Q_DFS_GET_INFO* q_i, prs_struct* ps, int depth)
+BOOL netdfs_io_dfs_Info101_p(const char *desc, NETDFS_DFS_INFO101 *v, prs_struct *ps, int depth)
{
- if(q_i == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_q_dfs_get_info");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info101_p");
depth++;
-
- if(!smb_io_unistr2("",&q_i->uni_path, 1, ps, depth))
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
+
+ return True;
+}
- if(!prs_align(ps))
+BOOL netdfs_io_dfs_Info101_d(const char *desc, NETDFS_DFS_INFO101 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info101_d");
+ depth++;
+
+ return True;
+}
- if(!prs_uint32("ptr_server", ps, depth, &q_i->ptr_server))
+BOOL init_netdfs_dfs_Info102(NETDFS_DFS_INFO102 *v, uint32 timeout)
+{
+ DEBUG(5,("init_netdfs_dfs_Info102\n"));
+
+ v->timeout = timeout;
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info102_p(const char *desc, NETDFS_DFS_INFO102 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info102_p");
+ depth++;
+ if (!prs_uint32("timeout", ps, depth, &v->timeout))
+ return False;
+
+ return True;
+}
- if(q_i->ptr_server)
- if (!smb_io_unistr2("",&q_i->uni_server, q_i->ptr_server, ps, depth))
- return False;
- if(!prs_align(ps))
+BOOL netdfs_io_dfs_Info102_d(const char *desc, NETDFS_DFS_INFO102 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info102_d");
+ depth++;
+
+ return True;
+}
- if(!prs_uint32("ptr_share", ps, depth, &q_i->ptr_share))
+BOOL init_netdfs_dfs_Info200(NETDFS_DFS_INFO200 *v, const char *dom_root)
+{
+ DEBUG(5,("init_netdfs_dfs_Info200\n"));
+
+ if (dom_root) {
+ v->ptr0_dom_root = 1;
+ init_unistr2(&v->dom_root, dom_root, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_dom_root = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info200_p(const char *desc, NETDFS_DFS_INFO200 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(q_i->ptr_share)
- if(!smb_io_unistr2("", &q_i->uni_share, q_i->ptr_share, ps, depth))
- return False;
- if(!prs_align(ps))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info200_p");
+ depth++;
+ if (!prs_uint32("ptr0_dom_root", ps, depth, &v->ptr0_dom_root))
return False;
+
+
+ return True;
+}
- if(!prs_uint32("level", ps, depth, &q_i->level))
+BOOL netdfs_io_dfs_Info200_d(const char *desc, NETDFS_DFS_INFO200 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info200_d");
+ depth++;
+ if (v->ptr0_dom_root) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("dom_root", &v->dom_root, 1, ps, depth))
+ return False;
+ }
+
return True;
}
-/************************************************************
- Read/write a DFS_R_GET_INFO structure
- ************************************************************/
+BOOL init_netdfs_dfs_Info300(NETDFS_DFS_INFO300 *v, uint32 flags, const char *dom_root)
+{
+ DEBUG(5,("init_netdfs_dfs_Info300\n"));
+
+ v->flags = flags;
+
+ if (dom_root) {
+ v->ptr0_dom_root = 1;
+ init_unistr2(&v->dom_root, dom_root, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_dom_root = 0;
+ }
+
+ return True;
+}
-BOOL dfs_io_r_dfs_get_info(const char *desc, DFS_R_DFS_GET_INFO* r_i, prs_struct* ps, int depth)
+BOOL netdfs_io_dfs_Info300_p(const char *desc, NETDFS_DFS_INFO300 *v, prs_struct *ps, int depth)
{
- if(r_i == NULL)
+ if (v == NULL)
return False;
-
- if(!prs_uint32("level", ps, depth, &r_i->level))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info300_p");
+ depth++;
+ if (!prs_uint32("flags", ps, depth, &v->flags))
return False;
- if(!prs_uint32("ptr_ctr", ps, depth, &r_i->ptr_ctr))
+
+ if (!prs_uint32("ptr0_dom_root", ps, depth, &v->ptr0_dom_root))
return False;
+
+
+ return True;
+}
- if(!dfs_io_dfs_info_ctr("", &r_i->ctr, 1, r_i->level, ps, depth))
+BOOL netdfs_io_dfs_Info300_d(const char *desc, NETDFS_DFS_INFO300 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!prs_werror("status", ps, depth, &r_i->status))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info300_d");
+ depth++;
+
+ if (v->ptr0_dom_root) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("dom_root", &v->dom_root, 1, ps, depth))
+ return False;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info_p(const char *desc, NETDFS_DFS_INFO_CTR* v, prs_struct *ps, int depth)
+{
+ if (!prs_uint32("switch_value", ps, depth, &v->switch_value))
return False;
+
+ switch (v->switch_value) {
+ case 0:
+ depth++;
+ if (!prs_uint32("ptr0_info0", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 1:
+ depth++;
+ if (!prs_uint32("ptr0_info1", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 2:
+ depth++;
+ if (!prs_uint32("ptr0_info2", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 3:
+ depth++;
+ if (!prs_uint32("ptr0_info3", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 4:
+ depth++;
+ if (!prs_uint32("ptr0_info4", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 100:
+ depth++;
+ if (!prs_uint32("ptr0_info100", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 101:
+ depth++;
+ if (!prs_uint32("ptr0_info101", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ case 102:
+ depth++;
+ if (!prs_uint32("ptr0_info102", ps, depth, &v->ptr0))
+ return False;
+
+ depth--;
+ break;
+
+ default:
+ return False;
+
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info_d(const char *desc, NETDFS_DFS_INFO_CTR* v, prs_struct *ps, int depth)
+{
+ switch (v->switch_value) {
+ case 0:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 1))
+ return False;
+
+ if (!netdfs_io_dfs_Info0_p("info0", &v->u.info0, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info0_d("info0", &v->u.info0, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 1:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info1_p("info1", &v->u.info1, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info1_d("info1", &v->u.info1, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 2:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info2_p("info2", &v->u.info2, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info2_d("info2", &v->u.info2, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 3:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info3_p("info3", &v->u.info3, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info3_d("info3", &v->u.info3, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 4:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info4_p("info4", &v->u.info4, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info4_d("info4", &v->u.info4, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 100:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info100_p("info100", &v->u.info100, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info100_d("info100", &v->u.info100, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 101:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info101_p("info101", &v->u.info101, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info101_d("info101", &v->u.info101, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 102:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_Info102_p("info102", &v->u.info102, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info102_d("info102", &v->u.info102, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ }
+
return True;
}
-
-/************************************************************
- Make a DFS_Q_DFS_ENUM structure
- ************************************************************/
-BOOL init_dfs_q_dfs_enum(DFS_Q_DFS_ENUM *q_d, uint32 level, DFS_INFO_CTR *ctr)
+BOOL init_netdfs_dfs_EnumArray1(NETDFS_DFS_ENUMARRAY1 *v, uint32 count, NETDFS_DFS_INFO1 **s)
{
- q_d->level = level;
- q_d->maxpreflen = -1;
- q_d->ptr_buffer = 1;
- q_d->level2 = level;
-
- q_d->ptr_num_entries = 1;
- q_d->num_entries = 0;
- q_d->num_entries2 = 0;
- q_d->reshnd.ptr_hnd = 1;
- q_d->reshnd.handle = 0;
+ DEBUG(5,("init_netdfs_dfs_EnumArray1\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 0;
+ }
+
return True;
}
-
-/************************************************************
- Read or write the DFS_Q_DFS_ENUM structure
- ************************************************************/
-BOOL dfs_io_q_dfs_enum(const char *desc, DFS_Q_DFS_ENUM *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_EnumArray1_p(const char *desc, NETDFS_DFS_ENUMARRAY1 *v, prs_struct *ps, int depth)
{
- if(q_d == NULL)
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "dfs_io_q_dfs_enum");
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray1_p");
depth++;
-
- if(!prs_align(ps))
+ if (!prs_uint32("count", ps, depth, &v->count))
return False;
-
- if(!prs_uint32("level", ps, depth, &q_d->level))
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
return False;
- if(!prs_uint32("maxpreflen", ps, depth, &q_d->maxpreflen))
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray1_d(const char *desc, NETDFS_DFS_ENUMARRAY1 *v, prs_struct *ps, int depth)
+{
+ uint32 i_s_1;
+
+ if (v == NULL)
return False;
- if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray1_d");
+ depth++;
+
+ if (v->ptr0_s) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_s", ps, depth, &v->size_s))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info1_p("s", &v->s[i_s_1], ps, depth))
+ return False;
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info1_d("s", &v->s[i_s_1], ps, depth))
+ return False;
+ }
+ }
+
+ return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray2(NETDFS_DFS_ENUMARRAY2 *v, uint32 count, NETDFS_DFS_INFO2 **s)
+{
+ DEBUG(5,("init_netdfs_dfs_EnumArray2\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray2_p(const char *desc, NETDFS_DFS_ENUMARRAY2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!prs_uint32("level2", ps, depth, &q_d->level2))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray2_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
return False;
- if(!prs_uint32("level3", ps, depth, &q_d->level2))
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
return False;
-
- if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray2_d(const char *desc, NETDFS_DFS_ENUMARRAY2 *v, prs_struct *ps, int depth)
+{
+ uint32 i_s_1;
+
+ if (v == NULL)
return False;
- if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray2_d");
+ depth++;
+
+ if (v->ptr0_s) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_s", ps, depth, &v->size_s))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info2_p("s", &v->s[i_s_1], ps, depth))
+ return False;
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info2_d("s", &v->s[i_s_1], ps, depth))
+ return False;
+ }
+ }
+
+ return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray3(NETDFS_DFS_ENUMARRAY3 *v, uint32 count, NETDFS_DFS_INFO3 **s)
+{
+ DEBUG(5,("init_netdfs_dfs_EnumArray3\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray3_p(const char *desc, NETDFS_DFS_ENUMARRAY3 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!prs_uint32("num_entries2", ps, depth, &q_d->num_entries2))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray3_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
return False;
- if(!smb_io_enum_hnd("resume_hnd",&q_d->reshnd, ps, depth))
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
return False;
+
+
return True;
}
-/************************************************************
- Read/write a DFS_INFO_CTR structure
- ************************************************************/
-
-BOOL dfs_io_dfs_info_ctr(const char *desc, DFS_INFO_CTR* ctr, uint32 num_entries, uint32 level, prs_struct* ps, int depth)
+BOOL netdfs_io_dfs_EnumArray3_d(const char *desc, NETDFS_DFS_ENUMARRAY3 *v, prs_struct *ps, int depth)
{
- int i=0;
-
- switch(level) {
- case 1:
- depth++;
- /* should depend on whether marshalling or unmarshalling! */
- if(UNMARSHALLING(ps)) {
- ctr->dfs.info1 = PRS_ALLOC_MEM(ps, DFS_INFO_1, num_entries);
- if (!ctr->dfs.info1)
- return False;
+ uint32 i_s_1;
+
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray3_d");
+ depth++;
+
+ if (v->ptr0_s) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_s", ps, depth, &v->size_s))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
}
-
- for(i=0;i<num_entries;i++) {
- if(!prs_uint32("ptr_entrypath",ps, depth, &ctr->dfs.info1[i].ptr_entrypath))
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info3_p("s", &v->s[i_s_1], ps, depth))
return False;
}
- for(i=0;i<num_entries;i++) {
- if(!smb_io_unistr2("", &ctr->dfs.info1[i].entrypath, ctr->dfs.info1[i].ptr_entrypath, ps, depth))
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info3_d("s", &v->s[i_s_1], ps, depth))
return False;
- if(!prs_align(ps))
+ }
+ }
+
+ return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray4(NETDFS_DFS_ENUMARRAY4 *v, uint32 count, NETDFS_DFS_INFO4 **s)
+{
+ DEBUG(5,("init_netdfs_dfs_EnumArray4\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray4_p(const char *desc, NETDFS_DFS_ENUMARRAY4 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray4_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
+ return False;
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+ return False;
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray4_d(const char *desc, NETDFS_DFS_ENUMARRAY4 *v, prs_struct *ps, int depth)
+{
+ uint32 i_s_1;
+
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray4_d");
+ depth++;
+
+ if (v->ptr0_s) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_s", ps, depth, &v->size_s))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info4_p("s", &v->s[i_s_1], ps, depth))
return False;
}
- depth--;
- break;
- case 2:
- depth++;
- if(UNMARSHALLING(ps)) {
- ctr->dfs.info2 = PRS_ALLOC_MEM(ps, DFS_INFO_2, num_entries);
- if (!ctr->dfs.info2)
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info4_d("s", &v->s[i_s_1], ps, depth))
return False;
}
+ }
+
+ return True;
+}
- for(i=0;i<num_entries;i++) {
- if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info2[i].ptr_entrypath))
- return False;
- if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info2[i].ptr_comment))
- return False;
- if(!prs_uint32("state", ps, depth, &ctr->dfs.info2[i].state))
- return False;
- if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info2[i].num_storages))
- return False;
+BOOL init_netdfs_dfs_EnumArray200(NETDFS_DFS_ENUMARRAY200 *v, uint32 count, NETDFS_DFS_INFO200 **s)
+{
+ DEBUG(5,("init_netdfs_dfs_EnumArray200\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray200_p(const char *desc, NETDFS_DFS_ENUMARRAY200 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray200_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
+ return False;
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+ return False;
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray200_d(const char *desc, NETDFS_DFS_ENUMARRAY200 *v, prs_struct *ps, int depth)
+{
+ uint32 i_s_1;
+
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray200_d");
+ depth++;
+
+ if (v->ptr0_s) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_s", ps, depth, &v->size_s))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
}
- for(i=0;i<num_entries;i++) {
- if(!smb_io_unistr2("", &ctr->dfs.info2[i].entrypath, ctr->dfs.info2[i].ptr_entrypath, ps, depth))
- return False;
- if(!prs_align(ps))
- return False;
- if(!smb_io_unistr2("",&ctr->dfs.info2[i].comment, ctr->dfs.info2[i].ptr_comment, ps, depth))
- return False;
- if(!prs_align(ps))
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info200_p("s", &v->s[i_s_1], ps, depth))
return False;
}
- depth--;
- break;
- case 3:
- depth++;
- if(UNMARSHALLING(ps)) {
- ctr->dfs.info3 = PRS_ALLOC_MEM(ps, DFS_INFO_3, num_entries);
- if (!ctr->dfs.info3)
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info200_d("s", &v->s[i_s_1], ps, depth))
return False;
}
+ }
+
+ return True;
+}
- for(i=0;i<num_entries;i++) {
- if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info3[i].ptr_entrypath))
- return False;
- if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info3[i].ptr_comment))
- return False;
- if(!prs_uint32("state", ps, depth, &ctr->dfs.info3[i].state))
- return False;
- if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info3[i].num_storages))
+BOOL init_netdfs_dfs_EnumArray300(NETDFS_DFS_ENUMARRAY300 *v, uint32 count, NETDFS_DFS_INFO300 **s)
+{
+ DEBUG(5,("init_netdfs_dfs_EnumArray300\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray300_p(const char *desc, NETDFS_DFS_ENUMARRAY300 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray300_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
+ return False;
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+ return False;
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray300_d(const char *desc, NETDFS_DFS_ENUMARRAY300 *v, prs_struct *ps, int depth)
+{
+ uint32 i_s_1;
+
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray300_d");
+ depth++;
+
+ if (v->ptr0_s) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("size_s", ps, depth, &v->size_s))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info300_p("s", &v->s[i_s_1], ps, depth))
return False;
- if(!prs_uint32("ptr_storages", ps, depth, &ctr->dfs.info3[i].ptr_storages))
+ }
+ for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+ if (!netdfs_io_dfs_Info300_d("s", &v->s[i_s_1], ps, depth))
return False;
}
- for(i=0;i<num_entries;i++) {
- if(!smb_io_unistr2("", &ctr->dfs.info3[i].entrypath, ctr->dfs.info3[i].ptr_entrypath, ps, depth))
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_EnumInfo_p(const char *desc, NETDFS_DFS_ENUMINFO_CTR* v, prs_struct *ps, int depth)
+{
+ if (!prs_uint32("switch_value", ps, depth, &v->switch_value))
+ return False;
+
+ switch (v->switch_value) {
+ case 1:
+ depth++;
+ if (!prs_uint32("ptr0_info1", ps, depth, &v->ptr0))
return False;
- if(!prs_align(ps))
+
+ depth--;
+ break;
+
+ case 2:
+ depth++;
+ if (!prs_uint32("ptr0_info2", ps, depth, &v->ptr0))
return False;
- if(!smb_io_unistr2("", &ctr->dfs.info3[i].comment, ctr->dfs.info3[i].ptr_comment, ps, depth))
+
+ depth--;
+ break;
+
+ case 3:
+ depth++;
+ if (!prs_uint32("ptr0_info3", ps, depth, &v->ptr0))
return False;
- if(!prs_align(ps))
+
+ depth--;
+ break;
+
+ case 4:
+ depth++;
+ if (!prs_uint32("ptr0_info4", ps, depth, &v->ptr0))
return False;
- if(!prs_uint32("num_storage_infos", ps, depth, &ctr->dfs.info3[i].num_storage_infos))
+
+ depth--;
+ break;
+
+ case 200:
+ depth++;
+ if (!prs_uint32("ptr0_info200", ps, depth, &v->ptr0))
return False;
-
- if(!dfs_io_dfs_storage_info("storage_info", &ctr->dfs.info3[i], ps, depth))
+
+ depth--;
+ break;
+
+ case 300:
+ depth++;
+ if (!prs_uint32("ptr0_info300", ps, depth, &v->ptr0))
return False;
- }
+
+ depth--;
+ break;
+
+ default:
+ return False;
+
}
+
+ return True;
+}
+BOOL netdfs_io_dfs_EnumInfo_d(const char *desc, NETDFS_DFS_ENUMINFO_CTR* v, prs_struct *ps, int depth)
+{
+ switch (v->switch_value) {
+ case 1:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_EnumArray1_p("info1", &v->u.info1, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumArray1_d("info1", &v->u.info1, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 2:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_EnumArray2_p("info2", &v->u.info2, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumArray2_d("info2", &v->u.info2, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 3:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_EnumArray3_p("info3", &v->u.info3, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumArray3_d("info3", &v->u.info3, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 4:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_EnumArray4_p("info4", &v->u.info4, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumArray4_d("info4", &v->u.info4, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 200:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_EnumArray200_p("info200", &v->u.info200, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumArray200_d("info200", &v->u.info200, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ case 300:
+ depth++;
+ if (v->ptr0) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!netdfs_io_dfs_EnumArray300_p("info300", &v->u.info300, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumArray300_d("info300", &v->u.info300, ps, depth))
+ return False;
+ }
+ depth--;
+ break;
+
+ }
+
+ return True;
+}
+BOOL init_netdfs_dfs_EnumStruct(NETDFS_DFS_ENUMSTRUCT *v, uint32 level, NETDFS_DFS_ENUMINFO_CTR e)
+{
+ DEBUG(5,("init_netdfs_dfs_EnumStruct\n"));
+
+ v->level = level;
+
+ v->e = e;
+ v->e.switch_value = v->level;
+
return True;
}
-/************************************************************
- Read/write a DFS_R_DFS_ENUM structure
- ************************************************************/
+BOOL netdfs_io_dfs_EnumStruct_p(const char *desc, NETDFS_DFS_ENUMSTRUCT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumStruct_p");
+ depth++;
+ if (!prs_uint32("level", ps, depth, &v->level))
+ return False;
+
+ if (!netdfs_io_dfs_EnumInfo_p("e", &v->e, ps, depth))
+ return False;
+
+ return True;
+}
-BOOL dfs_io_r_dfs_enum(const char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_EnumStruct_d(const char *desc, NETDFS_DFS_ENUMSTRUCT *v, prs_struct *ps, int depth)
{
- DFS_INFO_CTR *ctr;
- if(q_d == NULL)
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumStruct_d");
+ depth++;
+
+ if (!prs_align_custom(ps, 4))
return False;
- ctr = q_d->ctr;
- if(ctr == NULL)
+
+ if (!netdfs_io_dfs_EnumInfo_d("e", &v->e, ps, depth))
return False;
+
+ return True;
+}
- prs_debug(ps, depth, desc, "dfs_io_r_dfs_enum");
+/* netdfs functions */
+BOOL init_netdfs_q_dfs_GetManagerVersion(NETDFS_Q_DFS_GETMANAGERVERSION *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_GetManagerVersion\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_GetManagerVersion(const char *desc, NETDFS_Q_DFS_GETMANAGERVERSION *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_GetManagerVersion");
depth++;
+ return True;
+}
- if(!prs_align(ps))
+BOOL init_netdfs_r_dfs_GetManagerVersion(NETDFS_R_DFS_GETMANAGERVERSION *v, uint32 *exist_flag)
+{
+ DEBUG(5,("init_netdfs_r_dfs_GetManagerVersion\n"));
+
+ if (!exist_flag)
return False;
+
+ v->exist_flag = *exist_flag;
+
+ return True;
+}
- if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
+BOOL netdfs_io_r_dfs_GetManagerVersion(const char *desc, NETDFS_R_DFS_GETMANAGERVERSION *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!prs_uint32("level", ps, depth, &q_d->level))
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_GetManagerVersion");
+ depth++;
+ if (!prs_uint32("exist_flag", ps, depth, &v->exist_flag))
return False;
- if(!prs_uint32("level2", ps, depth, &ctr->switch_value))
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_Add(NETDFS_Q_DFS_ADD *v, const char *path, const char *server, const char *share, const char *comment, uint32 flags)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Add\n"));
+
+ if (!path)
+ return False;
+
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+
+ if (!server)
+ return False;
+
+ init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+
+ if (share) {
+ v->ptr0_share = 1;
+ init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_share = 0;
+ }
+
+ if (comment) {
+ v->ptr0_comment = 1;
+ init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_comment = 0;
+ }
+
+ v->flags = flags;
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_Add(const char *desc, NETDFS_Q_DFS_ADD *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Add");
+ depth++;
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
return False;
- if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
+
+ if (!prs_align_custom(ps, 4))
return False;
- if(q_d->ptr_num_entries)
- if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
+
+ if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+ return False;
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+ return False;
+
+ if (v->ptr0_share) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
return False;
- if(!prs_uint32("ptr_num_entries2", ps, depth, &q_d->ptr_num_entries2))
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
- if(q_d->ptr_num_entries2)
- if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries))
+
+ if (v->ptr0_comment) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
return False;
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("flags", ps, depth, &v->flags))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_Add(NETDFS_R_DFS_ADD *v, const char *path, const char *server, const char *share, const char *comment, uint32 flags, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_Add\n"));
+
+ v->status = status;
+
+ return True;
+}
- if(!dfs_io_dfs_info_ctr("", ctr, q_d->num_entries, q_d->level, ps, depth))
+BOOL netdfs_io_r_dfs_Add(const char *desc, NETDFS_R_DFS_ADD *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Add");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
- if(!smb_io_enum_hnd("resume_hnd", &q_d->reshnd, ps, depth))
+BOOL init_netdfs_q_dfs_Remove(NETDFS_Q_DFS_REMOVE *v, const char *path, const char *server, const char *share)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Remove\n"));
+
+ if (!path)
+ return False;
+
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+
+ if (server) {
+ v->ptr0_server = 1;
+ init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_server = 0;
+ }
+
+ if (share) {
+ v->ptr0_share = 1;
+ init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_share = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_Remove(const char *desc, NETDFS_Q_DFS_REMOVE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Remove");
+ depth++;
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+ return False;
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
return False;
- if(!prs_werror("status", ps, depth, &q_d->status))
+
+ if (v->ptr0_server) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+ return False;
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
return False;
+
+ if (v->ptr0_share) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
+ return False;
+ }
+
return True;
}
-BOOL dfs_io_dfs_storage_info(const char *desc, DFS_INFO_3* info3, prs_struct *ps, int depth)
+BOOL init_netdfs_r_dfs_Remove(NETDFS_R_DFS_REMOVE *v, const char *path, const char *server, const char *share, WERROR status)
{
- int i=0;
- if(info3 == NULL)
+ DEBUG(5,("init_netdfs_r_dfs_Remove\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_Remove(const char *desc, NETDFS_R_DFS_REMOVE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
-
- prs_debug(ps, depth, desc, "smb_io_dfs_storage_info");
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Remove");
depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
- if(UNMARSHALLING(ps)) {
- info3->storages = PRS_ALLOC_MEM(ps, DFS_STORAGE_INFO, info3->num_storage_infos);
- if (!info3->storages)
- return False;
+BOOL init_netdfs_q_dfs_SetInfo(NETDFS_Q_DFS_SETINFO *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_SetInfo\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_SetInfo(const char *desc, NETDFS_Q_DFS_SETINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_SetInfo");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_SetInfo(NETDFS_R_DFS_SETINFO *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_SetInfo\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_SetInfo(const char *desc, NETDFS_R_DFS_SETINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_SetInfo");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_GetInfo(NETDFS_Q_DFS_GETINFO *v, const char *path, const char *server, const char *share, uint32 level)
+{
+ DEBUG(5,("init_netdfs_q_dfs_GetInfo\n"));
+
+ if (!path)
+ return False;
+
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+
+ if (server) {
+ v->ptr0_server = 1;
+ init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_server = 0;
+ }
+
+ if (share) {
+ v->ptr0_share = 1;
+ init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+ } else {
+ v->ptr0_share = 0;
}
+
+ v->level = level;
+
+ return True;
+}
- for(i=0;i<info3->num_storage_infos;i++) {
- if(!prs_uint32("storage_state", ps, depth, &info3->storages[i].state))
+BOOL netdfs_io_q_dfs_GetInfo(const char *desc, NETDFS_Q_DFS_GETINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_GetInfo");
+ depth++;
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+ return False;
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
+ return False;
+
+ if (v->ptr0_server) {
+ if (!prs_align_custom(ps, 4))
return False;
- if(!prs_uint32("ptr_servername", ps, depth, &info3->storages[i].ptr_servername))
+
+ if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
return False;
- if(!prs_uint32("ptr_sharename", ps, depth, &info3->storages[i].ptr_sharename))
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+ return False;
+
+ if (v->ptr0_share) {
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
return False;
}
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("level", ps, depth, &v->level))
+ return False;
+
+ return True;
+}
- for(i=0;i<info3->num_storage_infos;i++) {
- if(!smb_io_unistr2("servername", &info3->storages[i].servername, info3->storages[i].ptr_servername, ps, depth))
+BOOL init_netdfs_r_dfs_GetInfo(NETDFS_R_DFS_GETINFO *v, const char *path, const char *server, const char *share, uint32 level, NETDFS_DFS_INFO_CTR *info, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_GetInfo\n"));
+
+ if (!info)
+ return False;
+
+ v->info = *info;
+ v->info.switch_value = level;
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_GetInfo(const char *desc, NETDFS_R_DFS_GETINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_GetInfo");
+ depth++;
+ if (!netdfs_io_dfs_Info_p("info", &v->info, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_Info_d("info", &v->info, ps, depth))
+ return False;
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_Enum(NETDFS_Q_DFS_ENUM *v, uint32 level, uint32 bufsize, NETDFS_DFS_ENUMSTRUCT *info, uint32 *unknown, uint32 *total)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Enum\n"));
+
+ v->level = level;
+
+ v->bufsize = bufsize;
+
+ if (info) {
+ v->ptr0_info = 1;
+ v->info = *info;
+ } else {
+ v->ptr0_info = 0;
+ }
+
+ if (unknown) {
+ v->ptr0_unknown = 1;
+ v->unknown = *unknown;
+ } else {
+ v->ptr0_unknown = 0;
+ }
+
+ if (total) {
+ v->ptr0_total = 1;
+ v->total = *total;
+ } else {
+ v->ptr0_total = 0;
+ }
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_Enum(const char *desc, NETDFS_Q_DFS_ENUM *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Enum");
+ depth++;
+ if (!prs_uint32("level", ps, depth, &v->level))
+ return False;
+
+ if (!prs_uint32("bufsize", ps, depth, &v->bufsize))
+ return False;
+
+ if (!prs_uint32("ptr0_info", ps, depth, &v->ptr0_info))
+ return False;
+
+ if (v->ptr0_info) {
+ if (!netdfs_io_dfs_EnumStruct_p("info", &v->info, ps, depth))
return False;
- if(!prs_align(ps))
+ if (!netdfs_io_dfs_EnumStruct_d("info", &v->info, ps, depth))
return False;
- if(!smb_io_unistr2("sharename", &info3->storages[i].sharename, info3->storages[i].ptr_sharename, ps, depth))
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_unknown", ps, depth, &v->ptr0_unknown))
+ return False;
+
+ if (v->ptr0_unknown) {
+ if (!prs_uint32("unknown", ps, depth, &v->unknown))
return False;
- if(!prs_align(ps))
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_total", ps, depth, &v->ptr0_total))
+ return False;
+
+ if (v->ptr0_total) {
+ if (!prs_uint32("total", ps, depth, &v->total))
return False;
}
+
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_Enum(NETDFS_R_DFS_ENUM *v, uint32 level, uint32 bufsize, NETDFS_DFS_ENUMSTRUCT *info, uint32 *unknown, uint32 *total, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_Enum\n"));
+
+ if (info) {
+ v->ptr0_info = 1;
+ v->info = *info;
+ } else {
+ v->ptr0_info = 0;
+ }
+
+ if (total) {
+ v->ptr0_total = 1;
+ v->total = *total;
+ } else {
+ v->ptr0_total = 0;
+ }
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_Enum(const char *desc, NETDFS_R_DFS_ENUM *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Enum");
+ depth++;
+ if (!prs_uint32("ptr0_info", ps, depth, &v->ptr0_info))
+ return False;
+
+ if (v->ptr0_info) {
+ if (!netdfs_io_dfs_EnumStruct_p("info", &v->info, ps, depth))
+ return False;
+ if (!netdfs_io_dfs_EnumStruct_d("info", &v->info, ps, depth))
+ return False;
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_total", ps, depth, &v->ptr0_total))
+ return False;
+
+ if (v->ptr0_total) {
+ if (!prs_uint32("total", ps, depth, &v->total))
+ return False;
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_Rename(NETDFS_Q_DFS_RENAME *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Rename\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_Rename(const char *desc, NETDFS_Q_DFS_RENAME *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Rename");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_Rename(NETDFS_R_DFS_RENAME *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_Rename\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_Rename(const char *desc, NETDFS_R_DFS_RENAME *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Rename");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_Move(NETDFS_Q_DFS_MOVE *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Move\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_Move(const char *desc, NETDFS_Q_DFS_MOVE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Move");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_Move(NETDFS_R_DFS_MOVE *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_Move\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_Move(const char *desc, NETDFS_R_DFS_MOVE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Move");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_ManagerGetConfigInfo(NETDFS_Q_DFS_MANAGERGETCONFIGINFO *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_ManagerGetConfigInfo\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_ManagerGetConfigInfo(const char *desc, NETDFS_Q_DFS_MANAGERGETCONFIGINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_ManagerGetConfigInfo");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_ManagerGetConfigInfo(NETDFS_R_DFS_MANAGERGETCONFIGINFO *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_ManagerGetConfigInfo\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_ManagerGetConfigInfo(const char *desc, NETDFS_R_DFS_MANAGERGETCONFIGINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_ManagerGetConfigInfo");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_ManagerSendSiteInfo(NETDFS_Q_DFS_MANAGERSENDSITEINFO *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_ManagerSendSiteInfo\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_ManagerSendSiteInfo(const char *desc, NETDFS_Q_DFS_MANAGERSENDSITEINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_ManagerSendSiteInfo");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_ManagerSendSiteInfo(NETDFS_R_DFS_MANAGERSENDSITEINFO *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_ManagerSendSiteInfo\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_ManagerSendSiteInfo(const char *desc, NETDFS_R_DFS_MANAGERSENDSITEINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_ManagerSendSiteInfo");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_AddFtRoot(NETDFS_Q_DFS_ADDFTROOT *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_AddFtRoot\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_AddFtRoot(const char *desc, NETDFS_Q_DFS_ADDFTROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_AddFtRoot");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_AddFtRoot(NETDFS_R_DFS_ADDFTROOT *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_AddFtRoot\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_AddFtRoot(const char *desc, NETDFS_R_DFS_ADDFTROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_AddFtRoot");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_RemoveFtRoot(NETDFS_Q_DFS_REMOVEFTROOT *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_RemoveFtRoot\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_RemoveFtRoot(const char *desc, NETDFS_Q_DFS_REMOVEFTROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_RemoveFtRoot");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_RemoveFtRoot(NETDFS_R_DFS_REMOVEFTROOT *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_RemoveFtRoot\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_RemoveFtRoot(const char *desc, NETDFS_R_DFS_REMOVEFTROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_RemoveFtRoot");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_AddStdRoot(NETDFS_Q_DFS_ADDSTDROOT *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_AddStdRoot\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_AddStdRoot(const char *desc, NETDFS_Q_DFS_ADDSTDROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_AddStdRoot");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_AddStdRoot(NETDFS_R_DFS_ADDSTDROOT *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_AddStdRoot\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_AddStdRoot(const char *desc, NETDFS_R_DFS_ADDSTDROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_AddStdRoot");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_RemoveStdRoot(NETDFS_Q_DFS_REMOVESTDROOT *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_RemoveStdRoot\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_RemoveStdRoot(const char *desc, NETDFS_Q_DFS_REMOVESTDROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_RemoveStdRoot");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_RemoveStdRoot(NETDFS_R_DFS_REMOVESTDROOT *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_RemoveStdRoot\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_RemoveStdRoot(const char *desc, NETDFS_R_DFS_REMOVESTDROOT *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_RemoveStdRoot");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_ManagerInitialize(NETDFS_Q_DFS_MANAGERINITIALIZE *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_ManagerInitialize\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_ManagerInitialize(const char *desc, NETDFS_Q_DFS_MANAGERINITIALIZE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_ManagerInitialize");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_ManagerInitialize(NETDFS_R_DFS_MANAGERINITIALIZE *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_ManagerInitialize\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_ManagerInitialize(const char *desc, NETDFS_R_DFS_MANAGERINITIALIZE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_ManagerInitialize");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_AddStdRootForced(NETDFS_Q_DFS_ADDSTDROOTFORCED *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_AddStdRootForced\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_AddStdRootForced(const char *desc, NETDFS_Q_DFS_ADDSTDROOTFORCED *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_AddStdRootForced");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_AddStdRootForced(NETDFS_R_DFS_ADDSTDROOTFORCED *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_AddStdRootForced\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_AddStdRootForced(const char *desc, NETDFS_R_DFS_ADDSTDROOTFORCED *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_AddStdRootForced");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_GetDcAddress(NETDFS_Q_DFS_GETDCADDRESS *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_GetDcAddress\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_GetDcAddress(const char *desc, NETDFS_Q_DFS_GETDCADDRESS *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_GetDcAddress");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_GetDcAddress(NETDFS_R_DFS_GETDCADDRESS *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_GetDcAddress\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_GetDcAddress(const char *desc, NETDFS_R_DFS_GETDCADDRESS *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_GetDcAddress");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_SetDcAddress(NETDFS_Q_DFS_SETDCADDRESS *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_SetDcAddress\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_SetDcAddress(const char *desc, NETDFS_Q_DFS_SETDCADDRESS *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_SetDcAddress");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_SetDcAddress(NETDFS_R_DFS_SETDCADDRESS *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_SetDcAddress\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_SetDcAddress(const char *desc, NETDFS_R_DFS_SETDCADDRESS *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_SetDcAddress");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_FlushFtTable(NETDFS_Q_DFS_FLUSHFTTABLE *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_FlushFtTable\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_FlushFtTable(const char *desc, NETDFS_Q_DFS_FLUSHFTTABLE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_FlushFtTable");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_FlushFtTable(NETDFS_R_DFS_FLUSHFTTABLE *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_FlushFtTable\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_FlushFtTable(const char *desc, NETDFS_R_DFS_FLUSHFTTABLE *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_FlushFtTable");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_Add2(NETDFS_Q_DFS_ADD2 *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Add2\n"));
+
+ return True;
+}
+BOOL netdfs_io_q_dfs_Add2(const char *desc, NETDFS_Q_DFS_ADD2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Add2");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_Add2(NETDFS_R_DFS_ADD2 *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_Add2\n"));
+
+ v->status = status;
+
return True;
}
+
+BOOL netdfs_io_r_dfs_Add2(const char *desc, NETDFS_R_DFS_ADD2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Add2");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_Remove2(NETDFS_Q_DFS_REMOVE2 *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_Remove2\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_Remove2(const char *desc, NETDFS_Q_DFS_REMOVE2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Remove2");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_Remove2(NETDFS_R_DFS_REMOVE2 *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_Remove2\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_Remove2(const char *desc, NETDFS_R_DFS_REMOVE2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Remove2");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_EnumEx(NETDFS_Q_DFS_ENUMEX *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_EnumEx\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_EnumEx(const char *desc, NETDFS_Q_DFS_ENUMEX *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_EnumEx");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_EnumEx(NETDFS_R_DFS_ENUMEX *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_EnumEx\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_EnumEx(const char *desc, NETDFS_R_DFS_ENUMEX *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_EnumEx");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
+BOOL init_netdfs_q_dfs_SetInfo2(NETDFS_Q_DFS_SETINFO2 *v)
+{
+ DEBUG(5,("init_netdfs_q_dfs_SetInfo2\n"));
+
+ return True;
+}
+
+BOOL netdfs_io_q_dfs_SetInfo2(const char *desc, NETDFS_Q_DFS_SETINFO2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_q_dfs_SetInfo2");
+ depth++;
+ return True;
+}
+
+BOOL init_netdfs_r_dfs_SetInfo2(NETDFS_R_DFS_SETINFO2 *v, WERROR status)
+{
+ DEBUG(5,("init_netdfs_r_dfs_SetInfo2\n"));
+
+ v->status = status;
+
+ return True;
+}
+
+BOOL netdfs_io_r_dfs_SetInfo2(const char *desc, NETDFS_R_DFS_SETINFO2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_SetInfo2");
+ depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
+
diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c
index 3d28b657f33..ffc0f04332d 100644
--- a/source/rpc_parse/parse_lsa.c
+++ b/source/rpc_parse/parse_lsa.c
@@ -29,6 +29,7 @@
#define DBGC_CLASS DBGC_RPC_PARSE
static BOOL lsa_io_trans_names(const char *desc, LSA_TRANS_NAME_ENUM *trn, prs_struct *ps, int depth);
+static BOOL lsa_io_trans_names2(const char *desc, LSA_TRANS_NAME_ENUM2 *trn, prs_struct *ps, int depth);
/*******************************************************************
Inits a LSA_TRANS_NAME structure.
@@ -70,6 +71,48 @@ static BOOL lsa_io_trans_name(const char *desc, LSA_TRANS_NAME *trn, prs_struct
}
/*******************************************************************
+ Inits a LSA_TRANS_NAME2 structure.
+********************************************************************/
+
+void init_lsa_trans_name2(LSA_TRANS_NAME2 *trn, UNISTR2 *uni_name,
+ uint16 sid_name_use, const char *name, uint32 idx)
+{
+ trn->sid_name_use = sid_name_use;
+ init_unistr2(uni_name, name, UNI_FLAGS_NONE);
+ init_uni_hdr(&trn->hdr_name, uni_name);
+ trn->domain_idx = idx;
+ trn->unknown = 0;
+}
+
+/*******************************************************************
+ Reads or writes a LSA_TRANS_NAME2 structure.
+********************************************************************/
+
+static BOOL lsa_io_trans_name2(const char *desc, LSA_TRANS_NAME2 *trn, prs_struct *ps,
+ int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_trans_name2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint16("sid_name_use", ps, depth, &trn->sid_name_use))
+ return False;
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_unihdr ("hdr_name", &trn->hdr_name, ps, depth))
+ return False;
+ if(!prs_uint32("domain_idx ", ps, depth, &trn->domain_idx))
+ return False;
+ if(!prs_uint32("unknown ", ps, depth, &trn->unknown))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
Reads or writes a DOM_R_REF structure.
********************************************************************/
@@ -508,8 +551,9 @@ BOOL lsa_io_q_enum_trust_dom(const char *desc, LSA_Q_ENUM_TRUST_DOM *q_e,
Inits an LSA_R_ENUM_TRUST_DOM structure.
********************************************************************/
-void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out, uint32 enum_context,
- uint32 req_num_domains, uint32 num_domains, TRUSTDOM **td)
+void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out,
+ uint32 enum_context, uint32 num_domains,
+ struct trustdom_info **td)
{
unsigned int i;
@@ -523,9 +567,16 @@ void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out, uint32 en
/* allocate container memory */
out->domlist = TALLOC_P( ctx, DOMAIN_LIST );
- out->domlist->domains = TALLOC_ARRAY( ctx, DOMAIN_INFO, out->count );
+
+ if ( !out->domlist ) {
+ out->status = NT_STATUS_NO_MEMORY;
+ return;
+ }
+
+ out->domlist->domains = TALLOC_ARRAY( ctx, DOMAIN_INFO,
+ out->count );
- if ( !out->domlist || !out->domlist->domains ) {
+ if ( !out->domlist->domains ) {
out->status = NT_STATUS_NO_MEMORY;
return;
}
@@ -535,13 +586,21 @@ void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out, uint32 en
/* initialize the list of domains and their sid */
for (i = 0; i < num_domains; i++) {
- if ( !(out->domlist->domains[i].sid = TALLOC_P(ctx, DOM_SID2)) ) {
+ smb_ucs2_t *name;
+ if ( !(out->domlist->domains[i].sid =
+ TALLOC_P(ctx, DOM_SID2)) ) {
out->status = NT_STATUS_NO_MEMORY;
return;
}
- init_dom_sid2(out->domlist->domains[i].sid, &(td[i])->sid);
- init_unistr4_w(ctx, &out->domlist->domains[i].name, (td[i])->name);
+ init_dom_sid2(out->domlist->domains[i].sid,
+ &(td[i])->sid);
+ if (push_ucs2_talloc(ctx, &name, (td[i])->name) < 0){
+ out->status = NT_STATUS_NO_MEMORY;
+ return;
+ }
+ init_unistr4_w(ctx, &out->domlist->domains[i].name,
+ name);
}
}
@@ -615,15 +674,89 @@ BOOL lsa_io_r_enum_trust_dom(const char *desc, LSA_R_ENUM_TRUST_DOM *out,
}
/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL lsa_io_dom_query_1(const char *desc, DOM_QUERY_1 *d_q, prs_struct *ps, int depth)
+{
+ if (d_q == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_1");
+ depth++;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("percent_full", ps, depth, &d_q->percent_full))
+ return False;
+ if (!prs_uint32("log_size", ps, depth, &d_q->log_size))
+ return False;
+ if (!smb_io_nttime("retention_time", ps, depth, &d_q->retention_time))
+ return False;
+ if (!prs_uint8("shutdown_in_progress", ps, depth, &d_q->shutdown_in_progress))
+ return False;
+ if (!smb_io_nttime("time_to_shutdown", ps, depth, &d_q->time_to_shutdown))
+ return False;
+ if (!prs_uint32("next_audit_record", ps, depth, &d_q->next_audit_record))
+ return False;
+ if (!prs_uint32("unknown", ps, depth, &d_q->unknown))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL lsa_io_dom_query_2(const char *desc, DOM_QUERY_2 *d_q, prs_struct *ps, int depth)
+{
+ if (d_q == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_2");
+ depth++;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("auditing_enabled", ps, depth, &d_q->auditing_enabled))
+ return False;
+ if (!prs_uint32("ptr ", ps, depth, &d_q->ptr))
+ return False;
+ if (!prs_uint32("count1", ps, depth, &d_q->count1))
+ return False;
+
+ if (d_q->ptr) {
+
+ if (!prs_uint32("count2", ps, depth, &d_q->count2))
+ return False;
+
+ if (d_q->count1 != d_q->count2)
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ d_q->auditsettings = TALLOC_ZERO_ARRAY(ps->mem_ctx, uint32, d_q->count2);
+ }
+
+ if (!prs_uint32s(False, "auditsettings", ps, depth, d_q->auditsettings, d_q->count2))
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
reads or writes a dom query structure.
********************************************************************/
-static BOOL lsa_io_dom_query(const char *desc, DOM_QUERY *d_q, prs_struct *ps, int depth)
+static BOOL lsa_io_dom_query_3(const char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth)
{
if (d_q == NULL)
return False;
- prs_debug(ps, depth, desc, "lsa_io_dom_query");
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_3");
depth++;
if(!prs_align(ps))
@@ -656,79 +789,235 @@ static BOOL lsa_io_dom_query(const char *desc, DOM_QUERY *d_q, prs_struct *ps, i
}
/*******************************************************************
-reads or writes a structure.
+ Reads or writes a dom query structure.
********************************************************************/
-static BOOL lsa_io_dom_query_2(const char *desc, DOM_QUERY_2 *d_q, prs_struct *ps, int depth)
+static BOOL lsa_io_dom_query_5(const char *desc, DOM_QUERY_5 *d_q, prs_struct *ps, int depth)
{
- uint32 ptr = 1;
+ return lsa_io_dom_query_3("", d_q, ps, depth);
+}
+/*******************************************************************
+ Reads or writes a dom query structure.
+********************************************************************/
+
+static BOOL lsa_io_dom_query_6(const char *desc, DOM_QUERY_6 *d_q, prs_struct *ps, int depth)
+{
if (d_q == NULL)
return False;
- prs_debug(ps, depth, desc, "lsa_io_dom_query_2");
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_6");
depth++;
- if (!prs_align(ps))
+ if (!prs_uint16("server_role", ps, depth, &d_q->server_role))
return False;
- if (!prs_uint32("auditing_enabled", ps, depth, &d_q->auditing_enabled))
- return False;
- if (!prs_uint32("ptr ", ps, depth, &ptr))
- return False;
- if (!prs_uint32("count1", ps, depth, &d_q->count1))
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a dom query structure.
+********************************************************************/
+
+static BOOL lsa_io_dom_query_10(const char *desc, DOM_QUERY_10 *d_q, prs_struct *ps, int depth)
+{
+ if (d_q == NULL)
return False;
- if (!prs_uint32("count2", ps, depth, &d_q->count2))
+
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_10");
+ depth++;
+
+ if (!prs_uint8("shutdown_on_full", ps, depth, &d_q->shutdown_on_full))
return False;
- if (UNMARSHALLING(ps)) {
- d_q->auditsettings = TALLOC_ZERO_ARRAY(ps->mem_ctx, uint32, d_q->count2);
- }
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a dom query structure.
+********************************************************************/
- if (d_q->auditsettings == NULL) {
- DEBUG(1, ("lsa_io_dom_query_2: NULL auditsettings!\n"));
+static BOOL lsa_io_dom_query_11(const char *desc, DOM_QUERY_11 *d_q, prs_struct *ps, int depth)
+{
+ if (d_q == NULL)
return False;
- }
- if (!prs_uint32s(False, "auditsettings", ps, depth, d_q->auditsettings, d_q->count2))
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_11");
+ depth++;
+
+ if (!prs_uint16("unknown", ps, depth, &d_q->unknown))
+ return False;
+ if (!prs_uint8("shutdown_on_full", ps, depth, &d_q->shutdown_on_full))
+ return False;
+ if (!prs_uint8("log_is_full", ps, depth, &d_q->log_is_full))
return False;
- return True;
+ return True;
}
/*******************************************************************
- Reads or writes a dom query structure.
+ Reads or writes an LSA_DNS_DOM_INFO structure.
********************************************************************/
-static BOOL lsa_io_dom_query_3(const char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth)
+BOOL lsa_io_dom_query_12(const char *desc, DOM_QUERY_12 *info, prs_struct *ps, int depth)
{
- return lsa_io_dom_query("", d_q, ps, depth);
+ prs_debug(ps, depth, desc, "lsa_io_dom_query_12");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unihdr("nb_name", &info->hdr_nb_dom_name, ps, depth))
+ return False;
+ if(!smb_io_unihdr("dns_name", &info->hdr_dns_dom_name, ps, depth))
+ return False;
+ if(!smb_io_unihdr("forest", &info->hdr_forest_name, ps, depth))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if ( !smb_io_uuid("dom_guid", &info->dom_guid, ps, depth) )
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("dom_sid", ps, depth, &info->ptr_dom_sid))
+ return False;
+
+ if(!smb_io_unistr2("nb_name", &info->uni_nb_dom_name,
+ info->hdr_nb_dom_name.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("dns_name", &info->uni_dns_dom_name,
+ info->hdr_dns_dom_name.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("forest", &info->uni_forest_name,
+ info->hdr_forest_name.buffer, ps, depth))
+ return False;
+
+ if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth))
+ return False;
+
+ return True;
+
}
/*******************************************************************
- Reads or writes a dom query structure.
+ Inits an LSA_Q_QUERY_INFO structure.
********************************************************************/
-static BOOL lsa_io_dom_query_5(const char *desc, DOM_QUERY_5 *d_q, prs_struct *ps, int depth)
+void init_q_set(LSA_Q_SET_INFO *in, POLICY_HND *hnd, uint16 info_class, LSA_INFO_CTR ctr)
{
- return lsa_io_dom_query("", d_q, ps, depth);
+ DEBUG(5,("init_q_set\n"));
+
+ in->info_class = info_class;
+
+ in->pol = *hnd;
+
+ in->ctr = ctr;
+ in->ctr.info_class = info_class;
}
/*******************************************************************
- Reads or writes a dom query structure.
+reads or writes a structure.
********************************************************************/
-static BOOL lsa_io_dom_query_6(const char *desc, DOM_QUERY_6 *d_q, prs_struct *ps, int depth)
+static BOOL lsa_io_query_info_ctr2(const char *desc, prs_struct *ps, int depth, LSA_INFO_CTR2 *ctr)
{
- if (d_q == NULL)
+ prs_debug(ps, depth, desc, "lsa_io_query_info_ctr2");
+ depth++;
+
+ if(!prs_uint16("info_class", ps, depth, &ctr->info_class))
return False;
- prs_debug(ps, depth, desc, "lsa_io_dom_query_6");
+ switch (ctr->info_class) {
+ case 1:
+ if(!lsa_io_dom_query_1("", &ctr->info.id1, ps, depth))
+ return False;
+ break;
+ case 2:
+ if(!lsa_io_dom_query_2("", &ctr->info.id2, ps, depth))
+ return False;
+ break;
+ case 3:
+ if(!lsa_io_dom_query_3("", &ctr->info.id3, ps, depth))
+ return False;
+ break;
+ case 5:
+ if(!lsa_io_dom_query_5("", &ctr->info.id5, ps, depth))
+ return False;
+ break;
+ case 6:
+ if(!lsa_io_dom_query_6("", &ctr->info.id6, ps, depth))
+ return False;
+ break;
+ case 10:
+ if(!lsa_io_dom_query_10("", &ctr->info.id10, ps, depth))
+ return False;
+ break;
+ case 11:
+ if(!lsa_io_dom_query_11("", &ctr->info.id11, ps, depth))
+ return False;
+ break;
+ case 12:
+ if(!lsa_io_dom_query_12("", &ctr->info.id12, ps, depth))
+ return False;
+ break;
+ default:
+ DEBUG(0,("invalid info_class: %d\n", ctr->info_class));
+ return False;
+ break;
+ }
+
+ return True;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL lsa_io_query_info_ctr(const char *desc, prs_struct *ps, int depth, LSA_INFO_CTR *ctr)
+{
+ prs_debug(ps, depth, desc, "lsa_io_query_info_ctr");
depth++;
- if (!prs_uint16("server_role", ps, depth, &d_q->server_role))
+ if(!prs_uint16("info_class", ps, depth, &ctr->info_class))
return False;
+ switch (ctr->info_class) {
+ case 1:
+ if(!lsa_io_dom_query_1("", &ctr->info.id1, ps, depth))
+ return False;
+ break;
+ case 2:
+ if(!lsa_io_dom_query_2("", &ctr->info.id2, ps, depth))
+ return False;
+ break;
+ case 3:
+ if(!lsa_io_dom_query_3("", &ctr->info.id3, ps, depth))
+ return False;
+ break;
+ case 5:
+ if(!lsa_io_dom_query_5("", &ctr->info.id5, ps, depth))
+ return False;
+ break;
+ case 6:
+ if(!lsa_io_dom_query_6("", &ctr->info.id6, ps, depth))
+ return False;
+ break;
+ case 10:
+ if(!lsa_io_dom_query_10("", &ctr->info.id10, ps, depth))
+ return False;
+ break;
+ case 11:
+ if(!lsa_io_dom_query_11("", &ctr->info.id11, ps, depth))
+ return False;
+ break;
+ default:
+ DEBUG(0,("invalid info_class: %d\n", ctr->info_class));
+ return False;
+ break;
+ }
+
return True;
}
@@ -738,40 +1027,20 @@ static BOOL lsa_io_dom_query_6(const char *desc, DOM_QUERY_6 *d_q, prs_struct *p
BOOL lsa_io_r_query(const char *desc, LSA_R_QUERY_INFO *out, prs_struct *ps, int depth)
{
+
prs_debug(ps, depth, desc, "lsa_io_r_query");
depth++;
- if(!prs_uint32("undoc_buffer", ps, depth, &out->undoc_buffer))
+ if(!prs_align(ps))
return False;
- if (out->undoc_buffer != 0) {
- if(!prs_uint16("info_class", ps, depth, &out->info_class))
- return False;
+ if(!prs_uint32("dom_ptr", ps, depth, &out->dom_ptr))
+ return False;
- if(!prs_align(ps))
- return False;
+ if (out->dom_ptr) {
- switch (out->info_class) {
- case 2:
- if(!lsa_io_dom_query_2("", &out->dom.id2, ps, depth))
- return False;
- break;
- case 3:
- if(!lsa_io_dom_query_3("", &out->dom.id3, ps, depth))
- return False;
- break;
- case 5:
- if(!lsa_io_dom_query_5("", &out->dom.id5, ps, depth))
- return False;
- break;
- case 6:
- if(!lsa_io_dom_query_6("", &out->dom.id6, ps, depth))
- return False;
- break;
- default:
- /* PANIC! */
- break;
- }
+ if(!lsa_io_query_info_ctr("", ps, depth, &out->ctr))
+ return False;
}
if(!prs_align(ps))
@@ -784,6 +1053,49 @@ BOOL lsa_io_r_query(const char *desc, LSA_R_QUERY_INFO *out, prs_struct *ps, int
}
/*******************************************************************
+ Reads or writes an LSA_Q_SET_INFO structure.
+********************************************************************/
+
+BOOL lsa_io_q_set(const char *desc, LSA_Q_SET_INFO *in, prs_struct *ps,
+ int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_set");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("", &in->pol, ps, depth))
+ return False;
+
+ if(!prs_uint16("info_class", ps, depth, &in->info_class))
+ return False;
+
+ if(!lsa_io_query_info_ctr("", ps, depth, &in->ctr))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_SET_INFO structure.
+********************************************************************/
+
+BOOL lsa_io_r_set(const char *desc, LSA_R_SET_INFO *out, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_set");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_ntstatus("status", ps, depth, &out->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
Inits a LSA_SID_ENUM structure.
********************************************************************/
@@ -938,6 +1250,75 @@ BOOL lsa_io_q_lookup_sids(const char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct *
}
/*******************************************************************
+ Reads or writes a LSA_Q_LOOKUP_SIDS2 structure.
+********************************************************************/
+
+BOOL lsa_io_q_lookup_sids2(const char *desc, LSA_Q_LOOKUP_SIDS2 *q_s, prs_struct *ps,
+ int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_lookup_sids2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("pol_hnd", &q_s->pol, ps, depth)) /* policy handle */
+ return False;
+ if(!lsa_io_sid_enum("sids ", &q_s->sids, ps, depth)) /* sids to be looked up */
+ return False;
+ if(!lsa_io_trans_names2("names ", &q_s->names, ps, depth)) /* translated names */
+ return False;
+
+ if(!prs_uint16("level", ps, depth, &q_s->level)) /* lookup level */
+ return False;
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("mapped_count", ps, depth, &q_s->mapped_count))
+ return False;
+ if(!prs_uint32("unknown1", ps, depth, &q_s->unknown1))
+ return False;
+ if(!prs_uint32("unknown2", ps, depth, &q_s->unknown2))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a LSA_Q_LOOKUP_SIDS3 structure.
+********************************************************************/
+
+BOOL lsa_io_q_lookup_sids3(const char *desc, LSA_Q_LOOKUP_SIDS3 *q_s, prs_struct *ps,
+ int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_lookup_sids3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!lsa_io_sid_enum("sids ", &q_s->sids, ps, depth)) /* sids to be looked up */
+ return False;
+ if(!lsa_io_trans_names2("names ", &q_s->names, ps, depth)) /* translated names */
+ return False;
+
+ if(!prs_uint16("level", ps, depth, &q_s->level)) /* lookup level */
+ return False;
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("mapped_count", ps, depth, &q_s->mapped_count))
+ return False;
+ if(!prs_uint32("unknown1", ps, depth, &q_s->unknown1))
+ return False;
+ if(!prs_uint32("unknown2", ps, depth, &q_s->unknown2))
+ return False;
+
+ return True;
+}
+
+
+/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -998,6 +1379,64 @@ static BOOL lsa_io_trans_names(const char *desc, LSA_TRANS_NAME_ENUM *trn,
Reads or writes a structure.
********************************************************************/
+static BOOL lsa_io_trans_names2(const char *desc, LSA_TRANS_NAME_ENUM2 *trn,
+ prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_trans_names2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("num_entries ", ps, depth, &trn->num_entries))
+ return False;
+ if(!prs_uint32("ptr_trans_names", ps, depth, &trn->ptr_trans_names))
+ return False;
+
+ if (trn->ptr_trans_names != 0) {
+ if(!prs_uint32("num_entries2 ", ps, depth,
+ &trn->num_entries2))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ if ((trn->name = PRS_ALLOC_MEM(ps, LSA_TRANS_NAME2, trn->num_entries)) == NULL) {
+ return False;
+ }
+
+ if ((trn->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, trn->num_entries)) == NULL) {
+ return False;
+ }
+ }
+
+ for (i = 0; i < trn->num_entries2; i++) {
+ fstring t;
+ slprintf(t, sizeof(t) - 1, "name[%d] ", i);
+
+ if(!lsa_io_trans_name2(t, &trn->name[i], ps, depth)) /* translated name */
+ return False;
+ }
+
+ for (i = 0; i < trn->num_entries2; i++) {
+ fstring t;
+ slprintf(t, sizeof(t) - 1, "name[%d] ", i);
+
+ if(!smb_io_unistr2(t, &trn->uni_name[i], trn->name[i].hdr_name.buffer, ps, depth))
+ return False;
+ if(!prs_align(ps))
+ return False;
+ }
+ }
+
+ return True;
+}
+
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
BOOL lsa_io_r_lookup_sids(const char *desc, LSA_R_LOOKUP_SIDS *r_s,
prs_struct *ps, int depth)
{
@@ -1030,6 +1469,77 @@ BOOL lsa_io_r_lookup_sids(const char *desc, LSA_R_LOOKUP_SIDS *r_s,
}
/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL lsa_io_r_lookup_sids2(const char *desc, LSA_R_LOOKUP_SIDS2 *r_s,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_lookup_sids2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_dom_ref", ps, depth, &r_s->ptr_dom_ref))
+ return False;
+
+ if (r_s->ptr_dom_ref != 0)
+ if(!lsa_io_dom_r_ref ("dom_ref", r_s->dom_ref, ps, depth)) /* domain reference info */
+ return False;
+
+ if(!lsa_io_trans_names2("names ", r_s->names, ps, depth)) /* translated names */
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("mapped_count", ps, depth, &r_s->mapped_count))
+ return False;
+
+ if(!prs_ntstatus("status ", ps, depth, &r_s->status))
+ return False;
+
+ return True;
+}
+
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL lsa_io_r_lookup_sids3(const char *desc, LSA_R_LOOKUP_SIDS3 *r_s,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_lookup_sids3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_dom_ref", ps, depth, &r_s->ptr_dom_ref))
+ return False;
+
+ if (r_s->ptr_dom_ref != 0)
+ if(!lsa_io_dom_r_ref ("dom_ref", r_s->dom_ref, ps, depth)) /* domain reference info */
+ return False;
+
+ if(!lsa_io_trans_names2("names ", r_s->names, ps, depth)) /* translated names */
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("mapped_count", ps, depth, &r_s->mapped_count))
+ return False;
+
+ if(!prs_ntstatus("status ", ps, depth, &r_s->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
makes a structure.
********************************************************************/
@@ -1117,7 +1627,9 @@ BOOL lsa_io_q_lookup_names(const char *desc, LSA_Q_LOOKUP_NAMES *q_r,
return False;
if(!prs_uint32("ptr_trans_sids ", ps, depth, &q_r->ptr_trans_sids))
return False;
- if(!prs_uint32("lookup_level ", ps, depth, &q_r->lookup_level))
+ if(!prs_uint16("lookup_level ", ps, depth, &q_r->lookup_level))
+ return False;
+ if(!prs_align(ps))
return False;
if(!prs_uint32("mapped_count ", ps, depth, &q_r->mapped_count))
return False;
@@ -1161,7 +1673,7 @@ BOOL lsa_io_r_lookup_names(const char *desc, LSA_R_LOOKUP_NAMES *out, prs_struct
}
if (UNMARSHALLING(ps)) {
- if ((out->dom_rid = PRS_ALLOC_MEM(ps, DOM_RID2, out->num_entries2))
+ if ((out->dom_rid = PRS_ALLOC_MEM(ps, DOM_RID, out->num_entries2))
== NULL) {
DEBUG(3, ("lsa_io_r_lookup_names(): out of memory\n"));
return False;
@@ -1169,6 +1681,131 @@ BOOL lsa_io_r_lookup_names(const char *desc, LSA_R_LOOKUP_NAMES *out, prs_struct
}
for (i = 0; i < out->num_entries2; i++)
+ if(!smb_io_dom_rid("", &out->dom_rid[i], ps, depth)) /* domain RIDs being looked up */
+ return False;
+ }
+
+ if(!prs_uint32("mapped_count", ps, depth, &out->mapped_count))
+ return False;
+
+ if(!prs_ntstatus("status ", ps, depth, &out->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL lsa_io_q_lookup_names2(const char *desc, LSA_Q_LOOKUP_NAMES2 *q_r,
+ prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_q_lookup_names2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("", &q_r->pol, ps, depth)) /* policy handle */
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("num_entries ", ps, depth, &q_r->num_entries))
+ return False;
+ if(!prs_uint32("num_entries2 ", ps, depth, &q_r->num_entries2))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ if (q_r->num_entries) {
+ if ((q_r->hdr_name = PRS_ALLOC_MEM(ps, UNIHDR, q_r->num_entries)) == NULL)
+ return False;
+ if ((q_r->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, q_r->num_entries)) == NULL)
+ return False;
+ }
+ }
+
+ for (i = 0; i < q_r->num_entries; i++) {
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unihdr("hdr_name", &q_r->hdr_name[i], ps, depth)) /* pointer names */
+ return False;
+ }
+
+ for (i = 0; i < q_r->num_entries; i++) {
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unistr2("dom_name", &q_r->uni_name[i], q_r->hdr_name[i].buffer, ps, depth)) /* names to be looked up */
+ return False;
+ }
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("num_trans_entries ", ps, depth, &q_r->num_trans_entries))
+ return False;
+ if(!prs_uint32("ptr_trans_sids ", ps, depth, &q_r->ptr_trans_sids))
+ return False;
+ if(!prs_uint16("lookup_level ", ps, depth, &q_r->lookup_level))
+ return False;
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("mapped_count ", ps, depth, &q_r->mapped_count))
+ return False;
+ if(!prs_uint32("unknown1 ", ps, depth, &q_r->unknown1))
+ return False;
+ if(!prs_uint32("unknown2 ", ps, depth, &q_r->unknown2))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL lsa_io_r_lookup_names2(const char *desc, LSA_R_LOOKUP_NAMES2 *out, prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_r_lookup_names2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_dom_ref", ps, depth, &out->ptr_dom_ref))
+ return False;
+
+ if (out->ptr_dom_ref != 0)
+ if(!lsa_io_dom_r_ref("", out->dom_ref, ps, depth))
+ return False;
+
+ if(!prs_uint32("num_entries", ps, depth, &out->num_entries))
+ return False;
+ if(!prs_uint32("ptr_entries", ps, depth, &out->ptr_entries))
+ return False;
+
+ if (out->ptr_entries != 0) {
+ if(!prs_uint32("num_entries2", ps, depth, &out->num_entries2))
+ return False;
+
+ if (out->num_entries2 != out->num_entries) {
+ /* RPC fault */
+ return False;
+ }
+
+ if (UNMARSHALLING(ps)) {
+ if ((out->dom_rid = PRS_ALLOC_MEM(ps, DOM_RID2, out->num_entries2))
+ == NULL) {
+ DEBUG(3, ("lsa_io_r_lookup_names2(): out of memory\n"));
+ return False;
+ }
+ }
+
+ for (i = 0; i < out->num_entries2; i++)
if(!smb_io_dom_rid2("", &out->dom_rid[i], ps, depth)) /* domain RIDs being looked up */
return False;
}
@@ -1182,6 +1819,297 @@ BOOL lsa_io_r_lookup_names(const char *desc, LSA_R_LOOKUP_NAMES *out, prs_struct
return True;
}
+/*******************************************************************
+ Internal lsa data type io.
+ Following pass must read DOM_SID2 types.
+********************************************************************/
+
+BOOL smb_io_lsa_translated_sids3(const char *desc, LSA_TRANSLATED_SID3 *q_r,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "smb_io_lsa_translated_sids3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint8 ("sid_type ", ps, depth, &q_r->sid_type ))
+ return False;
+ if(!prs_align(ps))
+ return False;
+ /* Second pass will read/write these. */
+ if (!smb_io_dom_sid2_p("sid_header", ps, depth, &q_r->sid2))
+ return False;
+ if(!prs_uint32("sid_idx ", ps, depth, &q_r->sid_idx ))
+ return False;
+ if(!prs_uint32("unknown ", ps, depth, &q_r->unknown ))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Identical to lsa_io_q_lookup_names2.
+********************************************************************/
+
+BOOL lsa_io_q_lookup_names3(const char *desc, LSA_Q_LOOKUP_NAMES3 *q_r,
+ prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_q_lookup_names3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("", &q_r->pol, ps, depth)) /* policy handle */
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("num_entries ", ps, depth, &q_r->num_entries))
+ return False;
+ if(!prs_uint32("num_entries2 ", ps, depth, &q_r->num_entries2))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ if (q_r->num_entries) {
+ if ((q_r->hdr_name = PRS_ALLOC_MEM(ps, UNIHDR, q_r->num_entries)) == NULL)
+ return False;
+ if ((q_r->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, q_r->num_entries)) == NULL)
+ return False;
+ }
+ }
+
+ for (i = 0; i < q_r->num_entries; i++) {
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unihdr("hdr_name", &q_r->hdr_name[i], ps, depth)) /* pointer names */
+ return False;
+ }
+
+ for (i = 0; i < q_r->num_entries; i++) {
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unistr2("dom_name", &q_r->uni_name[i], q_r->hdr_name[i].buffer, ps, depth)) /* names to be looked up */
+ return False;
+ }
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("num_trans_entries ", ps, depth, &q_r->num_trans_entries))
+ return False;
+ if(!prs_uint32("ptr_trans_sids ", ps, depth, &q_r->ptr_trans_sids))
+ return False;
+ if(!prs_uint16("lookup_level ", ps, depth, &q_r->lookup_level))
+ return False;
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("mapped_count ", ps, depth, &q_r->mapped_count))
+ return False;
+ if(!prs_uint32("unknown1 ", ps, depth, &q_r->unknown1))
+ return False;
+ if(!prs_uint32("unknown2 ", ps, depth, &q_r->unknown2))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL lsa_io_r_lookup_names3(const char *desc, LSA_R_LOOKUP_NAMES3 *out, prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_r_lookup_names3");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_dom_ref", ps, depth, &out->ptr_dom_ref))
+ return False;
+
+ if (out->ptr_dom_ref != 0)
+ if(!lsa_io_dom_r_ref("", out->dom_ref, ps, depth))
+ return False;
+
+ if(!prs_uint32("num_entries", ps, depth, &out->num_entries))
+ return False;
+ if(!prs_uint32("ptr_entries", ps, depth, &out->ptr_entries))
+ return False;
+
+ if (out->ptr_entries != 0) {
+ if(!prs_uint32("num_entries2", ps, depth, &out->num_entries2))
+ return False;
+
+ if (out->num_entries2 != out->num_entries) {
+ /* RPC fault */
+ return False;
+ }
+
+ if (UNMARSHALLING(ps)) {
+ if ((out->trans_sids = PRS_ALLOC_MEM(ps, LSA_TRANSLATED_SID3, out->num_entries2))
+ == NULL) {
+ DEBUG(3, ("lsa_io_r_lookup_names3(): out of memory\n"));
+ return False;
+ }
+ }
+
+ for (i = 0; i < out->num_entries2; i++) {
+ if(!smb_io_lsa_translated_sids3("", &out->trans_sids[i], ps, depth)) {
+ return False;
+ }
+ }
+ /* Now process the DOM_SID2 entries. */
+ for (i = 0; i < out->num_entries2; i++) {
+ if (out->trans_sids[i].sid2) {
+ if( !smb_io_dom_sid2("sid2", out->trans_sids[i].sid2, ps, depth) ) {
+ return False;
+ }
+ }
+ }
+ }
+
+ if(!prs_uint32("mapped_count", ps, depth, &out->mapped_count))
+ return False;
+
+ if(!prs_ntstatus("status ", ps, depth, &out->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL lsa_io_q_lookup_names4(const char *desc, LSA_Q_LOOKUP_NAMES4 *q_r,
+ prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_q_lookup_names4");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("num_entries ", ps, depth, &q_r->num_entries))
+ return False;
+ if(!prs_uint32("num_entries2 ", ps, depth, &q_r->num_entries2))
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ if (q_r->num_entries) {
+ if ((q_r->hdr_name = PRS_ALLOC_MEM(ps, UNIHDR, q_r->num_entries)) == NULL)
+ return False;
+ if ((q_r->uni_name = PRS_ALLOC_MEM(ps, UNISTR2, q_r->num_entries)) == NULL)
+ return False;
+ }
+ }
+
+ for (i = 0; i < q_r->num_entries; i++) {
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unihdr("hdr_name", &q_r->hdr_name[i], ps, depth)) /* pointer names */
+ return False;
+ }
+
+ for (i = 0; i < q_r->num_entries; i++) {
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unistr2("dom_name", &q_r->uni_name[i], q_r->hdr_name[i].buffer, ps, depth)) /* names to be looked up */
+ return False;
+ }
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("num_trans_entries ", ps, depth, &q_r->num_trans_entries))
+ return False;
+ if(!prs_uint32("ptr_trans_sids ", ps, depth, &q_r->ptr_trans_sids))
+ return False;
+ if(!prs_uint16("lookup_level ", ps, depth, &q_r->lookup_level))
+ return False;
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("mapped_count ", ps, depth, &q_r->mapped_count))
+ return False;
+ if(!prs_uint32("unknown1 ", ps, depth, &q_r->unknown1))
+ return False;
+ if(!prs_uint32("unknown2 ", ps, depth, &q_r->unknown2))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Identical to lsa_io_r_lookup_names3.
+********************************************************************/
+
+BOOL lsa_io_r_lookup_names4(const char *desc, LSA_R_LOOKUP_NAMES4 *out, prs_struct *ps, int depth)
+{
+ unsigned int i;
+
+ prs_debug(ps, depth, desc, "lsa_io_r_lookup_names4");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_dom_ref", ps, depth, &out->ptr_dom_ref))
+ return False;
+
+ if (out->ptr_dom_ref != 0)
+ if(!lsa_io_dom_r_ref("", out->dom_ref, ps, depth))
+ return False;
+
+ if(!prs_uint32("num_entries", ps, depth, &out->num_entries))
+ return False;
+ if(!prs_uint32("ptr_entries", ps, depth, &out->ptr_entries))
+ return False;
+
+ if (out->ptr_entries != 0) {
+ if(!prs_uint32("num_entries2", ps, depth, &out->num_entries2))
+ return False;
+
+ if (out->num_entries2 != out->num_entries) {
+ /* RPC fault */
+ return False;
+ }
+
+ if (UNMARSHALLING(ps)) {
+ if ((out->trans_sids = PRS_ALLOC_MEM(ps, LSA_TRANSLATED_SID3, out->num_entries2))
+ == NULL) {
+ DEBUG(3, ("lsa_io_r_lookup_names4(): out of memory\n"));
+ return False;
+ }
+ }
+
+ for (i = 0; i < out->num_entries2; i++) {
+ if(!smb_io_lsa_translated_sids3("", &out->trans_sids[i], ps, depth)) {
+ return False;
+ }
+ }
+ /* Now process the DOM_SID2 entries. */
+ for (i = 0; i < out->num_entries2; i++) {
+ if (out->trans_sids[i].sid2) {
+ if( !smb_io_dom_sid2("sid2", out->trans_sids[i].sid2, ps, depth) ) {
+ return False;
+ }
+ }
+ }
+ }
+
+ if(!prs_uint32("mapped_count", ps, depth, &out->mapped_count))
+ return False;
+
+ if(!prs_ntstatus("status ", ps, depth, &out->status))
+ return False;
+
+ return True;
+}
/*******************************************************************
Inits an LSA_Q_CLOSE structure.
@@ -2177,52 +3105,6 @@ BOOL policy_handle_is_valid(const POLICY_HND *hnd)
}
/*******************************************************************
- Reads or writes an LSA_DNS_DOM_INFO structure.
-********************************************************************/
-
-BOOL lsa_io_dns_dom_info(const char *desc, LSA_DNS_DOM_INFO *info,
- prs_struct *ps, int depth)
-{
- prs_debug(ps, depth, desc, "lsa_io_dns_dom_info");
- depth++;
-
- if(!prs_align(ps))
- return False;
- if(!smb_io_unihdr("nb_name", &info->hdr_nb_dom_name, ps, depth))
- return False;
- if(!smb_io_unihdr("dns_name", &info->hdr_dns_dom_name, ps, depth))
- return False;
- if(!smb_io_unihdr("forest", &info->hdr_forest_name, ps, depth))
- return False;
-
- if(!prs_align(ps))
- return False;
- if ( !smb_io_uuid("dom_guid", &info->dom_guid, ps, depth) )
- return False;
-
- if(!prs_align(ps))
- return False;
- if(!prs_uint32("dom_sid", ps, depth, &info->ptr_dom_sid))
- return False;
-
- if(!smb_io_unistr2("nb_name", &info->uni_nb_dom_name,
- info->hdr_nb_dom_name.buffer, ps, depth))
- return False;
- if(!smb_io_unistr2("dns_name", &info->uni_dns_dom_name,
- info->hdr_dns_dom_name.buffer, ps, depth))
- return False;
- if(!smb_io_unistr2("forest", &info->uni_forest_name,
- info->hdr_forest_name.buffer, ps, depth))
- return False;
-
- if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth))
- return False;
-
- return True;
-
-}
-
-/*******************************************************************
Inits an LSA_Q_QUERY_INFO2 structure.
********************************************************************/
@@ -2269,20 +3151,13 @@ BOOL lsa_io_r_query_info2(const char *desc, LSA_R_QUERY_INFO2 *out,
if(!prs_align(ps))
return False;
- if(!prs_uint32("ptr", ps, depth, &out->ptr))
- return False;
- if(!prs_uint16("info_class", ps, depth, &out->info_class))
+ if(!prs_uint32("dom_ptr", ps, depth, &out->dom_ptr))
return False;
- switch(out->info_class) {
- case 0x000c:
- if (!lsa_io_dns_dom_info("info12", &out->info.dns_dom_info,
- ps, depth))
+
+ if (out->dom_ptr) {
+
+ if(!lsa_io_query_info_ctr2("", ps, depth, &out->ctr))
return False;
- break;
- default:
- DEBUG(0,("lsa_io_r_query_info2: unknown info class %d\n",
- out->info_class));
- return False;
}
if(!prs_align(ps))
@@ -2326,6 +3201,9 @@ NTSTATUS init_r_enum_acct_rights( LSA_R_ENUM_ACCT_RIGHTS *out, PRIVILEGE_SET *pr
if ( num_priv ) {
out->rights = TALLOC_P( get_talloc_ctx(), UNISTR4_ARRAY );
+ if (!out->rights) {
+ return NT_STATUS_NO_MEMORY;
+ }
if ( !init_unistr4_array( out->rights, num_priv, privname_array ) )
return NT_STATUS_NO_MEMORY;
@@ -2394,6 +3272,10 @@ void init_q_add_acct_rights( LSA_Q_ADD_ACCT_RIGHTS *in, POLICY_HND *hnd,
init_dom_sid2(&in->sid, sid);
in->rights = TALLOC_P( get_talloc_ctx(), UNISTR4_ARRAY );
+ if (!in->rights) {
+ smb_panic("init_q_add_acct_rights: talloc fail\n");
+ return;
+ }
init_unistr4_array( in->rights, count, rights );
in->count = count;
@@ -2437,10 +3319,10 @@ BOOL lsa_io_r_add_acct_rights(const char *desc, LSA_R_ADD_ACCT_RIGHTS *out, prs_
return True;
}
-
/*******************************************************************
Inits an LSA_Q_REMOVE_ACCT_RIGHTS structure.
********************************************************************/
+
void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *in,
POLICY_HND *hnd,
DOM_SID *sid,
@@ -2458,13 +3340,17 @@ void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *in,
in->count = count;
in->rights = TALLOC_P( get_talloc_ctx(), UNISTR4_ARRAY );
+ if (!in->rights) {
+ smb_panic("init_q_remove_acct_rights: talloc fail\n");
+ return;
+ }
init_unistr4_array( in->rights, count, rights );
}
-
/*******************************************************************
reads or writes a LSA_Q_REMOVE_ACCT_RIGHTS structure.
********************************************************************/
+
BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *in, prs_struct *ps, int depth)
{
prs_debug(ps, depth, desc, "lsa_io_q_remove_acct_rights");
@@ -2539,8 +3425,78 @@ BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *i
}
#endif
+
+/*******************************************************************
+ Inits an LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME structure.
+********************************************************************/
+
+void init_lsa_q_open_trusted_domain_by_name(LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME *q,
+ POLICY_HND *hnd,
+ const char *name,
+ uint32 desired_access)
+{
+ memcpy(&q->pol, hnd, sizeof(q->pol));
+
+ init_lsa_string(&q->name, name);
+ q->access_mask = desired_access;
+}
+
+/*******************************************************************
+********************************************************************/
+
+
+/*******************************************************************
+ Reads or writes an LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME structure.
+********************************************************************/
+
+BOOL lsa_io_q_open_trusted_domain_by_name(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME *q_o, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_open_trusted_domain_by_name");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("pol", &q_o->pol, ps, depth))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_lsa_string("name", &q_o->name, ps, depth))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("access", ps, depth, &q_o->access_mask))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME structure.
+********************************************************************/
+
+BOOL lsa_io_r_open_trusted_domain_by_name(const char *desc, LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME *out, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_open_trusted_domain_by_name");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if (!smb_io_pol_hnd("handle", &out->handle, ps, depth))
+ return False;
+
+ if(!prs_ntstatus("status", ps, depth, &out->status))
+ return False;
+
+ return True;
+}
+
/*******************************************************************
- Reads or writes an LSA_Q_OPEN_TRUSTED_DOMAIN structure.
********************************************************************/
BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *q_o, prs_struct *ps, int depth)
@@ -3111,3 +4067,128 @@ BOOL lsa_io_r_query_trusted_domain_info(const char *desc,
return True;
}
+/*******************************************************************
+ Inits an LSA_Q_QUERY_DOM_INFO_POLICY structure.
+********************************************************************/
+
+void init_q_query_dom_info(LSA_Q_QUERY_DOM_INFO_POLICY *in, POLICY_HND *hnd, uint16 info_class)
+{
+ DEBUG(5, ("init_q_query_dom_info\n"));
+
+ memcpy(&in->pol, hnd, sizeof(in->pol));
+
+ in->info_class = info_class;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_Q_QUERY_DOM_INFO_POLICY structure.
+********************************************************************/
+
+BOOL lsa_io_q_query_dom_info(const char *desc, LSA_Q_QUERY_DOM_INFO_POLICY *in, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_query_dom_info");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("pol", &in->pol, ps, depth))
+ return False;
+
+ if(!prs_uint16("info_class", ps, depth, &in->info_class))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_QUERY_DOM_INFO_POLICY structure.
+********************************************************************/
+
+static BOOL lsa_io_dominfo_query_3(const char *desc, LSA_DOM_INFO_POLICY_KERBEROS *krb_policy,
+ prs_struct *ps, int depth)
+{
+ if (!prs_align_uint64(ps))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("enforce_restrictions", ps, depth, &krb_policy->enforce_restrictions))
+ return False;
+
+ if (!prs_align_uint64(ps))
+ return False;
+
+ if (!smb_io_nttime("service_tkt_lifetime", ps, depth, &krb_policy->service_tkt_lifetime))
+ return False;
+
+ if (!prs_align_uint64(ps))
+ return False;
+
+ if (!smb_io_nttime("user_tkt_lifetime", ps, depth, &krb_policy->user_tkt_lifetime))
+ return False;
+
+ if (!prs_align_uint64(ps))
+ return False;
+
+ if (!smb_io_nttime("user_tkt_renewaltime", ps, depth, &krb_policy->user_tkt_renewaltime))
+ return False;
+
+ if (!prs_align_uint64(ps))
+ return False;
+
+ if (!smb_io_nttime("clock_skew", ps, depth, &krb_policy->clock_skew))
+ return False;
+
+ if (!prs_align_uint64(ps))
+ return False;
+
+ if (!smb_io_nttime("unknown6", ps, depth, &krb_policy->unknown6))
+ return False;
+
+ return True;
+}
+
+static BOOL lsa_io_dom_info_query(const char *desc, prs_struct *ps, int depth, LSA_DOM_INFO_UNION *info)
+{
+ prs_debug(ps, depth, desc, "lsa_io_dom_info_query");
+ depth++;
+
+ if(!prs_align_uint16(ps))
+ return False;
+
+ if(!prs_uint16("info_class", ps, depth, &info->info_class))
+ return False;
+
+ switch (info->info_class) {
+ case 3:
+ if (!lsa_io_dominfo_query_3("krb_policy", &info->krb_policy, ps, depth))
+ return False;
+ break;
+ default:
+ DEBUG(0,("unsupported info-level: %d\n", info->info_class));
+ return False;
+ break;
+ }
+
+ return True;
+}
+
+
+BOOL lsa_io_r_query_dom_info(const char *desc, LSA_R_QUERY_DOM_INFO_POLICY *out,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_query_dom_info");
+ depth++;
+
+ if (!prs_pointer("dominfo", ps, depth, (void**)&out->info,
+ sizeof(LSA_DOM_INFO_UNION),
+ (PRS_POINTER_CAST)lsa_io_dom_info_query) )
+ return False;
+
+ if(!prs_ntstatus("status", ps, depth, &out->status))
+ return False;
+
+ return True;
+}
diff --git a/source/rpc_parse/parse_misc.c b/source/rpc_parse/parse_misc.c
index 26da87b280a..8cd6553a033 100644
--- a/source/rpc_parse/parse_misc.c
+++ b/source/rpc_parse/parse_misc.c
@@ -49,7 +49,7 @@ static TALLOC_CTX *main_loop_talloc = NULL;
free up temporary memory - called from the main loop
********************************************************************/
-void main_loop_talloc_free(void)
+void main_loop_TALLOC_FREE(void)
{
if (!main_loop_talloc)
return;
@@ -597,7 +597,7 @@ void init_rpc_blob_str(RPC_DATA_BLOB *str, const char *buf, int len)
/* set up string lengths. */
str->buf_len = create_rpc_blob(str, len*2);
- rpcstr_push(str->buffer, buf, str->buf_len, STR_TERMINATE);
+ rpcstr_push(str->buffer, buf, (size_t)str->buf_len, STR_TERMINATE);
}
@@ -762,6 +762,11 @@ void init_string2(STRING2 *str, const char *buf, size_t max_len, size_t str_len)
/* set up string lengths. */
SMB_ASSERT(max_len >= str_len);
+ /* Ensure buf is valid if str_len was set. Coverity check. */
+ if (str_len && !buf) {
+ return;
+ }
+
str->str_max_len = max_len;
str->offset = 0;
str->str_str_len = str_len;
@@ -879,6 +884,10 @@ void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags)
void init_unistr4(UNISTR4 *uni4, const char *buf, enum unistr2_term_codes flags)
{
uni4->string = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+ if (!uni4->string) {
+ smb_panic("init_unistr4: talloc fail\n");
+ return;
+ }
init_unistr2( uni4->string, buf, flags );
uni4->length = 2 * (uni4->string->uni_str_len);
@@ -888,6 +897,10 @@ void init_unistr4(UNISTR4 *uni4, const char *buf, enum unistr2_term_codes flags)
void init_unistr4_w( TALLOC_CTX *ctx, UNISTR4 *uni4, const smb_ucs2_t *buf )
{
uni4->string = TALLOC_P( ctx, UNISTR2 );
+ if (!uni4->string) {
+ smb_panic("init_unistr4_w: talloc fail\n");
+ return;
+ }
init_unistr2_w( ctx, uni4->string, buf );
uni4->length = 2 * (uni4->string->uni_str_len);
@@ -903,7 +916,7 @@ void init_unistr4_w( TALLOC_CTX *ctx, UNISTR4 *uni4, const smb_ucs2_t *buf )
void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf)
{
- uint32 len = strlen_w(buf);
+ uint32 len = buf ? strlen_w(buf) : 0;
ZERO_STRUCTP(str);
@@ -914,7 +927,7 @@ void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf)
str->buffer = TALLOC_ZERO_ARRAY(ctx, uint16, len + 1);
if (str->buffer == NULL) {
- smb_panic("init_unistr2_w: malloc fail\n");
+ smb_panic("init_unistr2_w: talloc fail\n");
return;
}
@@ -1251,23 +1264,50 @@ BOOL smb_io_account_lockout_str(const char *desc, LOCKOUT_STRING *account_lockou
}
/*******************************************************************
- Inits a DOM_RID2 structure.
+ Inits a DOM_RID structure.
********************************************************************/
-void init_dom_rid2(DOM_RID2 *rid2, uint32 rid, uint8 type, uint32 idx)
+void init_dom_rid(DOM_RID *prid, uint32 rid, uint16 type, uint32 idx)
{
- rid2->type = type;
- rid2->rid = rid;
- rid2->rid_idx = idx;
+ prid->type = type;
+ prid->rid = rid;
+ prid->rid_idx = idx;
+}
+
+/*******************************************************************
+ Reads or writes a DOM_RID structure.
+********************************************************************/
+
+BOOL smb_io_dom_rid(const char *desc, DOM_RID *rid, prs_struct *ps, int depth)
+{
+ if (rid == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "smb_io_dom_rid");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint16("type ", ps, depth, &rid->type))
+ return False;
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("rid ", ps, depth, &rid->rid))
+ return False;
+ if(!prs_uint32("rid_idx", ps, depth, &rid->rid_idx))
+ return False;
+
+ return True;
}
/*******************************************************************
Reads or writes a DOM_RID2 structure.
********************************************************************/
-BOOL smb_io_dom_rid2(const char *desc, DOM_RID2 *rid2, prs_struct *ps, int depth)
+BOOL smb_io_dom_rid2(const char *desc, DOM_RID2 *rid, prs_struct *ps, int depth)
{
- if (rid2 == NULL)
+ if (rid == NULL)
return False;
prs_debug(ps, depth, desc, "smb_io_dom_rid2");
@@ -1276,18 +1316,21 @@ BOOL smb_io_dom_rid2(const char *desc, DOM_RID2 *rid2, prs_struct *ps, int depth
if(!prs_align(ps))
return False;
- if(!prs_uint8("type ", ps, depth, &rid2->type))
+ if(!prs_uint16("type ", ps, depth, &rid->type))
return False;
if(!prs_align(ps))
return False;
- if(!prs_uint32("rid ", ps, depth, &rid2->rid))
+ if(!prs_uint32("rid ", ps, depth, &rid->rid))
+ return False;
+ if(!prs_uint32("rid_idx", ps, depth, &rid->rid_idx))
return False;
- if(!prs_uint32("rid_idx", ps, depth, &rid2->rid_idx))
+ if(!prs_uint32("unknown", ps, depth, &rid->unknown))
return False;
return True;
}
+
/*******************************************************************
creates a DOM_RID3 structure.
********************************************************************/
@@ -1368,7 +1411,7 @@ static void init_clnt_srv(DOM_CLNT_SRV *logcln, const char *logon_srv, const cha
Inits or writes a DOM_CLNT_SRV structure.
********************************************************************/
-static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *logcln, prs_struct *ps, int depth)
+BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *logcln, prs_struct *ps, int depth)
{
if (logcln == NULL)
return False;
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index 3bd6977dbb1..e168f5abbd3 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -1295,7 +1295,7 @@ static BOOL net_io_id_info_ctr(const char *desc, NET_ID_INFO_CTR **pp_ctr, prs_s
{
NET_ID_INFO_CTR *ctr = *pp_ctr;
- prs_debug(ps, depth, desc, "smb_io_sam_info");
+ prs_debug(ps, depth, desc, "smb_io_sam_info_ctr");
depth++;
if (UNMARSHALLING(ps)) {
@@ -1323,7 +1323,7 @@ static BOOL net_io_id_info_ctr(const char *desc, NET_ID_INFO_CTR **pp_ctr, prs_s
break;
default:
/* PANIC! */
- DEBUG(4,("smb_io_sam_info: unknown switch_value!\n"));
+ DEBUG(4,("smb_io_sam_info_ctr: unknown switch_value!\n"));
break;
}
@@ -1350,7 +1350,38 @@ static BOOL smb_io_sam_info(const char *desc, DOM_SAM_INFO *sam, prs_struct *ps,
if(!prs_uint32("ptr_rtn_cred ", ps, depth, &sam->ptr_rtn_cred))
return False;
- if(!smb_io_cred("", &sam->rtn_cred, ps, depth))
+ if (sam->ptr_rtn_cred) {
+ if(!smb_io_cred("", &sam->rtn_cred, ps, depth))
+ return False;
+ }
+
+ if(!prs_uint16("logon_level ", ps, depth, &sam->logon_level))
+ return False;
+
+ if (sam->logon_level != 0) {
+ if(!net_io_id_info_ctr("logon_info", &sam->ctr, ps, depth))
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a DOM_SAM_INFO_EX structure.
+ ********************************************************************/
+
+static BOOL smb_io_sam_info_ex(const char *desc, DOM_SAM_INFO_EX *sam, prs_struct *ps, int depth)
+{
+ if (sam == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "smb_io_sam_info_ex");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_clnt_srv("", &sam->client, ps, depth))
return False;
if(!prs_uint16("logon_level ", ps, depth, &sam->logon_level))
@@ -1393,10 +1424,11 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
uint16 logon_count, uint16 bad_pw_count,
uint32 num_groups, const DOM_GID *gids,
- uint32 user_flgs, uchar user_session_key[16],
+ uint32 user_flgs, uint32 acct_flags,
+ uchar user_session_key[16],
uchar lm_session_key[16],
const char *logon_srv, const char *logon_dom,
- const DOM_SID *dom_sid, const char *other_sids)
+ const DOM_SID *dom_sid)
{
/* only cope with one "other" sid, right now. */
/* need to count the number of space-delimited sids */
@@ -1435,6 +1467,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
usr->buffer_groups = 1; /* indicates fill in groups, below, even if there are none */
usr->user_flgs = user_flgs;
+ usr->acct_flags = acct_flags;
if (user_session_key != NULL)
memcpy(usr->user_sess_key, user_session_key, sizeof(usr->user_sess_key));
@@ -1444,7 +1477,6 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
memset((char *)usr->lm_sess_key, '\0', sizeof(usr->lm_sess_key));
- memset(&usr->acct_flags, '\0', sizeof(usr->acct_flags));
for (i=0; i<7; i++) {
memset(&usr->unknown[i], '\0', sizeof(usr->unknown));
@@ -1454,7 +1486,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
memcpy(usr->lm_sess_key, lm_session_key, sizeof(usr->lm_sess_key));
}
- num_other_sids = init_dom_sid2s(ctx, other_sids, &usr->other_sids);
+ num_other_sids = init_dom_sid2s(ctx, NULL, &usr->other_sids);
usr->num_other_sids = num_other_sids;
usr->buffer_other_sids = (num_other_sids != 0) ? 1 : 0;
@@ -1490,6 +1522,59 @@ 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) {
+
+ int lvl = 10;
+ DEBUG(lvl,("dump_acct_flags\n"));
+ if (acct_flags & ACB_NORMAL) {
+ DEBUGADD(lvl,("\taccount has ACB_NORMAL\n"));
+ }
+ if (acct_flags & ACB_PWNOEXP) {
+ DEBUGADD(lvl,("\taccount has ACB_PWNOEXP\n"));
+ }
+ if (acct_flags & ACB_ENC_TXT_PWD_ALLOWED) {
+ DEBUGADD(lvl,("\taccount has ACB_ENC_TXT_PWD_ALLOWED\n"));
+ }
+ if (acct_flags & ACB_NOT_DELEGATED) {
+ DEBUGADD(lvl,("\taccount has ACB_NOT_DELEGATED\n"));
+ }
+ if (acct_flags & ACB_USE_DES_KEY_ONLY) {
+ DEBUGADD(lvl,("\taccount has ACB_USE_DES_KEY_ONLY set, sig verify wont work\n"));
+ }
+ if (acct_flags & ACB_NO_AUTH_DATA_REQD) {
+ DEBUGADD(lvl,("\taccount has ACB_NO_AUTH_DATA_REQD set\n"));
+ }
+ if (acct_flags & ACB_PWEXPIRED) {
+ DEBUGADD(lvl,("\taccount has ACB_PWEXPIRED set\n"));
+ }
+}
+
+ void dump_user_flgs(uint32 user_flags) {
+
+ int lvl = 10;
+ DEBUG(lvl,("dump_user_flgs\n"));
+ if (user_flags & LOGON_EXTRA_SIDS) {
+ DEBUGADD(lvl,("\taccount has LOGON_EXTRA_SIDS\n"));
+ }
+ if (user_flags & LOGON_RESOURCE_GROUPS) {
+ DEBUGADD(lvl,("\taccount has LOGON_RESOURCE_GROUPS\n"));
+ }
+ if (user_flags & LOGON_NTLMV2_ENABLED) {
+ DEBUGADD(lvl,("\taccount has LOGON_NTLMV2_ENABLED\n"));
+ }
+ if (user_flags & LOGON_CACHED_ACCOUNT) {
+ DEBUGADD(lvl,("\taccount has LOGON_CACHED_ACCOUNT\n"));
+ }
+ if (user_flags & LOGON_PROFILE_PATH_RETURNED) {
+ DEBUGADD(lvl,("\taccount has LOGON_PROFILE_PATH_RETURNED\n"));
+ }
+ if (user_flags & LOGON_SERVER_TRUST_ACCOUNT) {
+ DEBUGADD(lvl,("\taccount has LOGON_SERVER_TRUST_ACCOUNT\n"));
+ }
+
+
+}
+
/*******************************************************************
This code has been modified to cope with a NET_USER_INFO_2 - which is
exactly the same as a NET_USER_INFO_3, minus the other sids parameters.
@@ -1562,7 +1647,7 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
return False;
if(!prs_uint32("user_flgs ", ps, depth, &usr->user_flgs)) /* user flags */
return False;
-
+ dump_user_flgs(usr->user_flgs);
if(!prs_uint8s(False, "user_sess_key", ps, depth, usr->user_sess_key, 16)) /* user session key */
return False;
@@ -1579,7 +1664,7 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
if(!prs_uint32("acct_flags ", ps, depth, &usr->acct_flags)) /* Account flags */
return False;
-
+ dump_acct_flags(usr->acct_flags);
for (i = 0; i < 7; i++)
{
if (!prs_uint32("unkown", ps, depth, &usr->unknown[i])) /* unknown */
@@ -1659,7 +1744,7 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
if(!smb_io_dom_sid2("", &usr->dom_sid, ps, depth)) /* domain SID */
return False;
- if (usr->buffer_other_sids) {
+ if (validation_level == 3 && usr->buffer_other_sids) {
uint32 num_other_sids = usr->num_other_sids;
@@ -1735,7 +1820,7 @@ BOOL net_io_q_sam_logon(const char *desc, NET_Q_SAM_LOGON *q_l, prs_struct *ps,
if(!prs_align_uint16(ps))
return False;
-
+
if(!prs_uint16("validation_level", ps, depth, &q_l->validation_level))
return False;
@@ -1792,6 +1877,79 @@ BOOL net_io_r_sam_logon(const char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps,
Reads or writes a structure.
********************************************************************/
+BOOL net_io_q_sam_logon_ex(const char *desc, NET_Q_SAM_LOGON_EX *q_l, prs_struct *ps, int depth)
+{
+ if (q_l == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "net_io_q_sam_logon_ex");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_sam_info_ex("", &q_l->sam_id, ps, depth))
+ return False;
+
+ if(!prs_align_uint16(ps))
+ return False;
+
+ if(!prs_uint16("validation_level", ps, depth, &q_l->validation_level))
+ return False;
+
+ if(!prs_uint32("flags ", ps, depth, &q_l->flags))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL net_io_r_sam_logon_ex(const char *desc, NET_R_SAM_LOGON_EX *r_l, prs_struct *ps, int depth)
+{
+ if (r_l == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "net_io_r_sam_logon_ex");
+ depth++;
+
+ if(!prs_uint16("switch_value", ps, depth, &r_l->switch_value))
+ return False;
+ if(!prs_align(ps))
+ return False;
+
+#if 1 /* W2k always needs this - even for bad passwd. JRA */
+ if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False))
+ return False;
+#else
+ if (r_l->switch_value != 0) {
+ if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False))
+ return False;
+ }
+#endif
+
+ if(!prs_uint32("auth_resp ", ps, depth, &r_l->auth_resp)) /* 1 - Authoritative response; 0 - Non-Auth? */
+ return False;
+
+ if(!prs_uint32("flags ", ps, depth, &r_l->flags))
+ return False;
+
+ if(!prs_ntstatus("status ", ps, depth, &r_l->status))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+
+ return True;
+}
+
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
BOOL net_io_q_sam_logoff(const char *desc, NET_Q_SAM_LOGOFF *q_l, prs_struct *ps, int depth)
{
if (q_l == NULL)
@@ -2091,86 +2249,6 @@ static BOOL net_io_sam_passwd_info(const char *desc, SAM_PWD * pwd,
}
/*******************************************************************
-makes a SAM_ACCOUNT_INFO structure.
-********************************************************************/
-BOOL make_sam_account_info(SAM_ACCOUNT_INFO * info,
- const UNISTR2 *user_name,
- const UNISTR2 *full_name,
- uint32 user_rid, uint32 group_rid,
- const UNISTR2 *home_dir,
- const UNISTR2 *dir_drive,
- const UNISTR2 *log_scr,
- const UNISTR2 *desc,
- uint32 acb_info,
- const UNISTR2 *prof_path,
- const UNISTR2 *wkstas,
- const UNISTR2 *unk_str, const UNISTR2 *mung_dial)
-{
- int len_user_name = user_name != NULL ? user_name->uni_str_len : 0;
- int len_full_name = full_name != NULL ? full_name->uni_str_len : 0;
- int len_home_dir = home_dir != NULL ? home_dir->uni_str_len : 0;
- int len_dir_drive = dir_drive != NULL ? dir_drive->uni_str_len : 0;
- int len_logon_script = log_scr != NULL ? log_scr->uni_str_len : 0;
- int len_profile_path = prof_path != NULL ? prof_path->uni_str_len : 0;
- int len_description = desc != NULL ? desc->uni_str_len : 0;
- int len_workstations = wkstas != NULL ? wkstas->uni_str_len : 0;
- int len_unknown_str = unk_str != NULL ? unk_str->uni_str_len : 0;
- int len_munged_dial = mung_dial != NULL ? mung_dial->uni_str_len : 0;
-
- DEBUG(5, ("make_sam_account_info\n"));
-
- make_uni_hdr(&info->hdr_acct_name, len_user_name);
- make_uni_hdr(&info->hdr_full_name, len_full_name);
- make_uni_hdr(&info->hdr_home_dir, len_home_dir);
- make_uni_hdr(&info->hdr_dir_drive, len_dir_drive);
- make_uni_hdr(&info->hdr_logon_script, len_logon_script);
- make_uni_hdr(&info->hdr_profile, len_profile_path);
- make_uni_hdr(&info->hdr_acct_desc, len_description);
- make_uni_hdr(&info->hdr_workstations, len_workstations);
- make_uni_hdr(&info->hdr_comment, len_unknown_str);
- make_uni_hdr(&info->hdr_parameters, len_munged_dial);
-
- /* not present */
- make_bufhdr2(&info->hdr_sec_desc, 0, 0, 0);
-
- info->user_rid = user_rid;
- info->group_rid = group_rid;
-
- init_nt_time(&info->logon_time);
- init_nt_time(&info->logoff_time);
- init_nt_time(&info->pwd_last_set_time);
- init_nt_time(&info->acct_expiry_time);
-
- info->logon_divs = 0xA8;
- info->ptr_logon_hrs = 0; /* Don't care right now */
-
- info->bad_pwd_count = 0;
- info->logon_count = 0;
- info->acb_info = acb_info;
- info->nt_pwd_present = 0;
- info->lm_pwd_present = 0;
- info->pwd_expired = 0;
- info->country = 0;
- info->codepage = 0;
-
- info->unknown1 = 0x4EC;
- info->unknown2 = 0;
-
- copy_unistr2(&info->uni_acct_name, user_name);
- copy_unistr2(&info->uni_full_name, full_name);
- copy_unistr2(&info->uni_home_dir, home_dir);
- copy_unistr2(&info->uni_dir_drive, dir_drive);
- copy_unistr2(&info->uni_logon_script, log_scr);
- copy_unistr2(&info->uni_profile, prof_path);
- copy_unistr2(&info->uni_acct_desc, desc);
- copy_unistr2(&info->uni_workstations, wkstas);
- copy_unistr2(&info->uni_comment, unk_str);
- copy_unistr2(&info->uni_parameters, mung_dial);
-
- return True;
-}
-
-/*******************************************************************
reads or writes a structure.
********************************************************************/
static BOOL net_io_sam_account_info(const char *desc, SAM_ACCOUNT_INFO *info,
diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c
index 7c84ee800b9..f2b002c48cf 100644
--- a/source/rpc_parse/parse_prs.c
+++ b/source/rpc_parse/parse_prs.c
@@ -207,16 +207,21 @@ BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize)
return prs_force_grow(ps, newsize - ps->buffer_size);
if (newsize < ps->buffer_size) {
- char *new_data_p = SMB_REALLOC(ps->data_p, newsize);
- /* if newsize is zero, Realloc acts like free() & returns NULL*/
- if (new_data_p == NULL && newsize != 0) {
- DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
- (unsigned int)newsize));
- DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno)));
- return False;
- }
- ps->data_p = new_data_p;
ps->buffer_size = newsize;
+
+ /* newsize == 0 acts as a free and set pointer to NULL */
+ if (newsize == 0) {
+ SAFE_FREE(ps->data_p);
+ } else {
+ ps->data_p = SMB_REALLOC(ps->data_p, newsize);
+
+ if (ps->data_p == NULL) {
+ DEBUG(0,("prs_set_buffer_size: Realloc failure for size %u.\n",
+ (unsigned int)newsize));
+ DEBUG(0,("prs_set_buffer_size: Reason %s\n",strerror(errno)));
+ return False;
+ }
+ }
}
return True;
@@ -230,7 +235,6 @@ BOOL prs_set_buffer_size(prs_struct *ps, uint32 newsize)
BOOL prs_grow(prs_struct *ps, uint32 extra_space)
{
uint32 new_size;
- char *new_data;
ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
@@ -261,11 +265,11 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space);
- if((new_data = SMB_MALLOC(new_size)) == NULL) {
+ if((ps->data_p = SMB_MALLOC(new_size)) == NULL) {
DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
return False;
}
- memset(new_data, '\0', (size_t)new_size );
+ memset(ps->data_p, '\0', (size_t)new_size );
} else {
/*
* If the current buffer size is bigger than the space needed, just
@@ -273,16 +277,15 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
*/
new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);
- if ((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) {
+ if ((ps->data_p = SMB_REALLOC(ps->data_p, new_size)) == NULL) {
DEBUG(0,("prs_grow: Realloc failure for size %u.\n",
(unsigned int)new_size));
return False;
}
- memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
+ memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
}
ps->buffer_size = new_size;
- ps->data_p = new_data;
return True;
}
@@ -296,7 +299,6 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
BOOL prs_force_grow(prs_struct *ps, uint32 extra_space)
{
uint32 new_size = ps->buffer_size + extra_space;
- char *new_data;
if(!UNMARSHALLING(ps) || !ps->is_dynamic) {
DEBUG(0,("prs_force_grow: Buffer overflow - unable to expand buffer by %u bytes.\n",
@@ -304,16 +306,15 @@ BOOL prs_force_grow(prs_struct *ps, uint32 extra_space)
return False;
}
- if((new_data = SMB_REALLOC(ps->data_p, new_size)) == NULL) {
+ if((ps->data_p = 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;
}
- memset(&new_data[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
+ memset(&ps->data_p[ps->buffer_size], '\0', (size_t)(new_size - ps->buffer_size));
ps->buffer_size = new_size;
- ps->data_p = new_data;
return True;
}
@@ -606,12 +607,12 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
if (q == NULL)
return False;
- if (UNMARSHALLING(ps))
+ if (UNMARSHALLING(ps))
*data8 = CVAL(q,0);
else
SCVAL(q,0,*data8);
- DEBUG(5,("%s%04x %s: %02x\n", tab_depth(depth), ps->data_offset, name, *data8));
+ DEBUG(5,("%s%04x %s: %02x\n", tab_depth(depth), ps->data_offset, name, *data8));
ps->data_offset += 1;
@@ -767,6 +768,37 @@ BOOL prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status)
}
/*******************************************************************
+ Stream a DCE error code
+ ********************************************************************/
+
+BOOL prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status)
+{
+ char *q = prs_mem_get(ps, sizeof(uint32));
+ if (q == NULL)
+ return False;
+
+ if (UNMARSHALLING(ps)) {
+ if (ps->bigendian_data)
+ *status = NT_STATUS(RIVAL(q,0));
+ else
+ *status = NT_STATUS(IVAL(q,0));
+ } else {
+ if (ps->bigendian_data)
+ RSIVAL(q,0,NT_STATUS_V(*status));
+ else
+ SIVAL(q,0,NT_STATUS_V(*status));
+ }
+
+ DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name,
+ dcerpc_errstr(NT_STATUS_V(*status))));
+
+ ps->data_offset += sizeof(uint32);
+
+ return True;
+}
+
+
+/*******************************************************************
Stream a WERROR
********************************************************************/
@@ -1303,6 +1335,35 @@ BOOL prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_
return True;
}
+BOOL prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str)
+{
+ size_t len;
+ char *tmp_str;
+
+ if (UNMARSHALLING(ps)) {
+ len = strlen(&ps->data_p[ps->data_offset]);
+ } else {
+ len = strlen(*str);
+ }
+
+ tmp_str = PRS_ALLOC_MEM(ps, char, len+1);
+
+ if (tmp_str == NULL) {
+ return False;
+ }
+
+ if (MARSHALLING(ps)) {
+ strncpy(tmp_str, *str, len);
+ }
+
+ if (!prs_string(name, ps, depth, tmp_str, len+1)) {
+ return False;
+ }
+
+ *str = tmp_str;
+ return True;
+}
+
/*******************************************************************
prs_uint16 wrapper. Call this and it sets up a pointer to where the
uint16 should be stored, or gets the size if reading.
diff --git a/source/rpc_parse/parse_reg.c b/source/rpc_parse/parse_reg.c
index 295fead1035..fef1332e5c7 100644
--- a/source/rpc_parse/parse_reg.c
+++ b/source/rpc_parse/parse_reg.c
@@ -54,6 +54,10 @@ void init_reg_q_open_hive( REG_Q_OPEN_HIVE *q_o, uint32 access_desired )
{
q_o->server = TALLOC_P( get_talloc_ctx(), uint16);
+ if (!q_o->server) {
+ smb_panic("init_reg_q_open_hive: talloc fail.\n");
+ return;
+ }
*q_o->server = 0x1;
q_o->access = access_desired;
@@ -221,6 +225,10 @@ void init_reg_q_create_key_ex(REG_Q_CREATE_KEY_EX *q_c, POLICY_HND *hnd,
q_c->access = access_desired;
q_c->sec_info = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!q_c->sec_info) {
+ smb_panic("init_reg_q_create_key_ex: talloc fail\n");
+ return;
+ }
*q_c->sec_info = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
q_c->data = sec_buf;
@@ -228,6 +236,10 @@ void init_reg_q_create_key_ex(REG_Q_CREATE_KEY_EX *q_c, POLICY_HND *hnd,
init_buf_hdr(&q_c->hdr_sec, sec_buf->len, sec_buf->len);
q_c->ptr3 = 1;
q_c->disposition = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!q_c->disposition) {
+ smb_panic("init_reg_q_create_key_ex: talloc fail\n");
+ return;
+ }
}
/*******************************************************************
@@ -997,14 +1009,23 @@ BOOL init_reg_r_query_value(uint32 include_keyval, REG_R_QUERY_VALUE *r_u,
return False;
r_u->type = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!r_u->type) {
+ return False;
+ }
*r_u->type = val->type;
buf_len = reg_init_regval_buffer( &buf2, val );
r_u->buf_max_len = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!r_u->buf_max_len) {
+ return False;
+ }
*r_u->buf_max_len = buf_len;
r_u->buf_len = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!r_u->buf_len) {
+ return False;
+ }
*r_u->buf_len = buf_len;
/* if include_keyval is not set, don't send the key value, just
@@ -1012,6 +1033,9 @@ BOOL init_reg_r_query_value(uint32 include_keyval, REG_R_QUERY_VALUE *r_u,
if ( include_keyval ) {
r_u->value = TALLOC_P( get_talloc_ctx(), REGVAL_BUFFER );
+ if (!r_u->value) {
+ return False;
+ }
/* steal the memory */
*r_u->value = buf2;
}
@@ -1071,18 +1095,39 @@ void init_reg_q_enum_val(REG_Q_ENUM_VALUE *q_u, POLICY_HND *pol,
q_u->name.size = max_name_len*2;
q_u->name.string = TALLOC_ZERO_P( get_talloc_ctx(), UNISTR2 );
+ if (!q_u->name.string) {
+ smb_panic("init_reg_q_enum_val: talloc fail\n");
+ return;
+ }
q_u->name.string->uni_max_len = max_name_len;
q_u->type = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!q_u->type) {
+ smb_panic("init_reg_q_enum_val: talloc fail\n");
+ return;
+ }
*q_u->type = 0x0;
q_u->value = TALLOC_ZERO_P( get_talloc_ctx(), REGVAL_BUFFER );
+ if (!q_u->value) {
+ smb_panic("init_reg_q_enum_val: talloc fail\n");
+ return;
+ }
+
q_u->value->buf_max_len = max_buf_len;
- q_u->buffer_len = TALLOC_P( get_talloc_ctx(), uint32 );
+ q_u->buffer_len = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!q_u->buffer_len) {
+ smb_panic("init_reg_q_enum_val: talloc fail\n");
+ return;
+ }
*q_u->buffer_len = max_buf_len;
- q_u->name_len = TALLOC_P( get_talloc_ctx(), uint32 );
+ q_u->name_len = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!q_u->name_len) {
+ smb_panic("init_reg_q_enum_val: talloc fail\n");
+ return;
+ }
*q_u->name_len = 0x0;
}
@@ -1105,18 +1150,34 @@ void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val )
/* type */
r_u->type = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!r_u->type) {
+ smb_panic("init_reg_r_enum_val: talloc fail\n");
+ return;
+ }
*r_u->type = val->type;
/* REG_SZ & REG_MULTI_SZ must be converted to UNICODE */
r_u->value = TALLOC_P( get_talloc_ctx(), REGVAL_BUFFER );
+ if (!r_u->value) {
+ smb_panic("init_reg_r_enum_val: talloc fail\n");
+ return;
+ }
real_size = reg_init_regval_buffer( r_u->value, val );
/* lengths */
- r_u->buffer_len1 = TALLOC_P( get_talloc_ctx(), uint32 );
+ r_u->buffer_len1 = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!r_u->buffer_len1) {
+ smb_panic("init_reg_r_enum_val: talloc fail\n");
+ return;
+ }
*r_u->buffer_len1 = real_size;
- r_u->buffer_len2 = TALLOC_P( get_talloc_ctx(), uint32 );
+ r_u->buffer_len2 = TALLOC_P( get_talloc_ctx(), uint32 );
+ if (!r_u->buffer_len2) {
+ smb_panic("init_reg_r_enum_val: talloc fail\n");
+ return;
+ }
*r_u->buffer_len2 = real_size;
}
@@ -1312,7 +1373,15 @@ void init_reg_r_enum_key(REG_R_ENUM_KEY *r_u, char *subkey )
init_unistr4( &r_u->keyname, subkey, UNI_STR_TERMINATE );
r_u->classname = TALLOC_ZERO_P( get_talloc_ctx(), UNISTR4 );
- r_u->time = TALLOC_ZERO_P( get_talloc_ctx(), NTTIME );
+ if (!r_u->classname) {
+ smb_panic("init_reg_r_enum_key: talloc fail\n");
+ return;
+ }
+ r_u->time = TALLOC_ZERO_P( get_talloc_ctx(), NTTIME );
+ if (!r_u->time) {
+ smb_panic("init_reg_r_enum_key: talloc fail\n");
+ return;
+ }
}
/*******************************************************************
@@ -1482,9 +1551,17 @@ void init_reg_q_shutdown(REG_Q_SHUTDOWN *q_u, const char *msg,
uint32 timeout, BOOL do_reboot, BOOL force)
{
q_u->server = TALLOC_P( get_talloc_ctx(), uint16 );
+ if (!q_u->server) {
+ smb_panic("init_reg_q_shutdown: talloc fail\n");
+ return;
+ }
*q_u->server = 0x1;
q_u->message = TALLOC_ZERO_P( get_talloc_ctx(), UNISTR4 );
+ if (!q_u->message) {
+ smb_panic("init_reg_q_shutdown: talloc fail\n");
+ return;
+ }
if ( msg && *msg ) {
init_unistr4( q_u->message, msg, UNI_FLAGS_NONE );
@@ -1652,20 +1729,24 @@ BOOL reg_io_r_shutdown_ex(const char *desc, REG_R_SHUTDOWN_EX *r_u, prs_struct *
return True;
}
-
-
/*******************************************************************
Inits a structure.
********************************************************************/
+
void init_reg_q_abort_shutdown(REG_Q_ABORT_SHUTDOWN *q_u)
{
q_u->server = TALLOC_P( get_talloc_ctx(), uint16 );
+ if (!q_u->server) {
+ smb_panic("init_reg_q_abort_shutdown: talloc fail\n");
+ return;
+ }
*q_u->server = 0x1;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
+
BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN *q_u,
prs_struct *ps, int depth)
{
diff --git a/source/rpc_parse/parse_rpc.c b/source/rpc_parse/parse_rpc.c
index ea4ec2c8639..2d166c773b4 100644
--- a/source/rpc_parse/parse_rpc.c
+++ b/source/rpc_parse/parse_rpc.c
@@ -191,16 +191,6 @@ interface/version dce/rpc pipe identification
}, 0x00 \
}
-#define SYNT_UNIXINFO_V0 \
-{ \
- { \
- 0x9c54e310, 0xa955, 0x4885, \
- { 0xbd, 0x31 }, \
- { 0x78, 0x78, \
- 0x71, 0x47, 0xdf, 0xa6 } \
- }, 0x00 \
-}
-
#define SYNT_NTSVCS_V1 \
{ \
{ \
@@ -671,7 +661,7 @@ BOOL smb_io_rpc_hdr_fault(const char *desc, RPC_HDR_FAULT *rpc, prs_struct *ps,
prs_debug(ps, depth, desc, "smb_io_rpc_hdr_fault");
depth++;
- if(!prs_ntstatus("status ", ps, depth, &rpc->status))
+ if(!prs_dcerpc_status("status ", ps, depth, &rpc->status))
return False;
if(!prs_uint32("reserved", ps, depth, &rpc->reserved))
return False;
@@ -858,4 +848,3 @@ BOOL smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len,
return True;
}
-
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 6c2b4f4ea71..05c75fe98a4 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -344,7 +344,7 @@ void init_samr_r_get_usrdom_pwinfo(SAMR_R_GET_USRDOM_PWINFO *r_u, NTSTATUS statu
{
DEBUG(5, ("init_samr_r_get_usrdom_pwinfo\n"));
- r_u->unknown_0 = 0x0000;
+ r_u->min_pwd_length = 0x0000;
/*
* used to be
@@ -354,7 +354,7 @@ void init_samr_r_get_usrdom_pwinfo(SAMR_R_GET_USRDOM_PWINFO *r_u, NTSTATUS statu
r_u->unknown_1 = 0x01D1;
r_u->unknown_1 = 0x0015;
- r_u->unknown_2 = 0x00000000;
+ r_u->password_properties = 0x00000000;
r_u->status = status;
}
@@ -375,12 +375,13 @@ BOOL samr_io_r_get_usrdom_pwinfo(const char *desc, SAMR_R_GET_USRDOM_PWINFO * r_
if(!prs_align(ps))
return False;
- if(!prs_uint16("unknown_0", ps, depth, &r_u->unknown_0))
+ if(!prs_uint16("min_pwd_length", ps, depth, &r_u->min_pwd_length))
return False;
if(!prs_uint16("unknown_1", ps, depth, &r_u->unknown_1))
return False;
- if(!prs_uint32("unknown_2", ps, depth, &r_u->unknown_2))
+ if(!prs_uint32("password_properties", ps, depth, &r_u->password_properties))
return False;
+
if(!prs_ntstatus("status ", ps, depth, &r_u->status))
return False;
@@ -918,6 +919,21 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
}
/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+void init_samr_q_set_sec_obj(SAMR_Q_SET_SEC_OBJ * q_u,
+ POLICY_HND *pol, uint32 sec_info, SEC_DESC_BUF *buf)
+{
+ DEBUG(5, ("samr_init_samr_q_set_sec_obj\n"));
+
+ q_u->pol = *pol;
+ q_u->sec_info = sec_info;
+ q_u->buf = buf;
+}
+
+
+/*******************************************************************
reads or writes a SAMR_R_SET_SEC_OBJ structure.
********************************************************************/
@@ -1003,7 +1019,7 @@ inits a SAM_ENTRY1 structure.
static void init_sam_entry1(SAM_ENTRY1 *sam, uint32 user_idx,
UNISTR2 *sam_name, UNISTR2 *sam_full,
UNISTR2 *sam_desc, uint32 rid_user,
- uint16 acb_info)
+ uint32 acb_info)
{
DEBUG(5, ("init_sam_entry1\n"));
@@ -1039,10 +1055,7 @@ static BOOL sam_io_sam_entry1(const char *desc, SAM_ENTRY1 * sam,
if(!prs_uint32("rid_user ", ps, depth, &sam->rid_user))
return False;
- if(!prs_uint16("acb_info ", ps, depth, &sam->acb_info))
- return False;
-
- if(!prs_align(ps))
+ if(!prs_uint32("acb_info ", ps, depth, &sam->acb_info))
return False;
if (!smb_io_unihdr("hdr_acct_name", &sam->hdr_acct_name, ps, depth))
@@ -1084,7 +1097,7 @@ inits a SAM_ENTRY2 structure.
********************************************************************/
static void init_sam_entry2(SAM_ENTRY2 * sam, uint32 user_idx,
UNISTR2 *sam_name, UNISTR2 *sam_desc,
- uint32 rid_user, uint16 acb_info)
+ uint32 rid_user, uint32 acb_info)
{
DEBUG(5, ("init_sam_entry2\n"));
@@ -1117,10 +1130,7 @@ static BOOL sam_io_sam_entry2(const char *desc, SAM_ENTRY2 * sam,
if(!prs_uint32("rid_user ", ps, depth, &sam->rid_user))
return False;
- if(!prs_uint16("acb_info ", ps, depth, &sam->acb_info))
- return False;
-
- if(!prs_align(ps))
+ if(!prs_uint32("acb_info ", ps, depth, &sam->acb_info))
return False;
if(!smb_io_unihdr("unihdr", &sam->hdr_srv_name, ps, depth)) /* account name unicode string header */
@@ -1321,7 +1331,7 @@ inits a SAMR_Q_ENUM_DOM_USERS structure.
void init_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS * q_e, POLICY_HND *pol,
uint32 start_idx,
- uint16 acb_mask, uint16 unk_1, uint32 size)
+ uint32 acb_mask, uint32 size)
{
DEBUG(5, ("init_samr_q_enum_dom_users\n"));
@@ -1329,7 +1339,6 @@ void init_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS * q_e, POLICY_HND *pol,
q_e->start_idx = start_idx; /* zero indicates lots */
q_e->acb_mask = acb_mask;
- q_e->unknown_1 = unk_1;
q_e->max_size = size;
}
@@ -1354,9 +1363,7 @@ BOOL samr_io_q_enum_dom_users(const char *desc, SAMR_Q_ENUM_DOM_USERS * q_e,
if(!prs_uint32("start_idx", ps, depth, &q_e->start_idx))
return False;
- if(!prs_uint16("acb_mask ", ps, depth, &q_e->acb_mask))
- return False;
- if(!prs_uint16("unknown_1", ps, depth, &q_e->unknown_1))
+ if(!prs_uint32("acb_mask ", ps, depth, &q_e->acb_mask))
return False;
if(!prs_uint32("max_size ", ps, depth, &q_e->max_size))
@@ -2300,6 +2307,69 @@ BOOL samr_io_group_info4(const char *desc, GROUP_INFO4 * gr4,
}
/*******************************************************************
+inits a GROUP_INFO5 structure.
+********************************************************************/
+
+void init_samr_group_info5(GROUP_INFO5 * gr5,
+ char *acct_name, char *acct_desc,
+ uint32 num_members)
+{
+ DEBUG(5, ("init_samr_group_info5\n"));
+
+ gr5->group_attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT); /* why not | SE_GROUP_ENABLED ? */
+ gr5->num_members = num_members;
+
+ init_unistr2(&gr5->uni_acct_name, acct_name, UNI_FLAGS_NONE);
+ init_uni_hdr(&gr5->hdr_acct_name, &gr5->uni_acct_name);
+ init_unistr2(&gr5->uni_acct_desc, acct_desc, UNI_FLAGS_NONE);
+ init_uni_hdr(&gr5->hdr_acct_desc, &gr5->uni_acct_desc);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_group_info5(const char *desc, GROUP_INFO5 * gr5,
+ prs_struct *ps, int depth)
+{
+ uint16 dummy = 1;
+
+ if (gr5 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_group_info5");
+ depth++;
+
+ if(!prs_uint16("level", ps, depth, &dummy))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_unihdr("hdr_acct_name", &gr5->hdr_acct_name, ps, depth))
+ return False;
+
+ if(!prs_uint32("group_attr", ps, depth, &gr5->group_attr))
+ return False;
+ if(!prs_uint32("num_members", ps, depth, &gr5->num_members))
+ return False;
+
+ if(!smb_io_unihdr("hdr_acct_desc", &gr5->hdr_acct_desc, ps, depth))
+ return False;
+
+ if(!smb_io_unistr2("uni_acct_name", &gr5->uni_acct_name,
+ gr5->hdr_acct_name.buffer, ps, depth))
+ return False;
+
+ if(!smb_io_unistr2("uni_acct_desc", &gr5->uni_acct_desc,
+ gr5->hdr_acct_desc.buffer, ps, depth))
+ return False;
+
+ return True;
+}
+
+
+/*******************************************************************
reads or writes a structure.
********************************************************************/
@@ -2335,6 +2405,10 @@ static BOOL samr_group_info_ctr(const char *desc, GROUP_INFO_CTR **ctr,
if(!samr_io_group_info4("group_info4", &(*ctr)->group.info4, ps, depth))
return False;
break;
+ case 5:
+ if(!samr_io_group_info5("group_info5", &(*ctr)->group.info5, ps, depth))
+ return False;
+ break;
default:
DEBUG(0,("samr_group_info_ctr: unsupported switch level\n"));
break;
@@ -3547,6 +3621,28 @@ BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 *al3,
reads or writes a structure.
********************************************************************/
+BOOL samr_io_alias_info2(const char *desc, ALIAS_INFO2 *al2,
+ prs_struct *ps, int depth)
+{
+ if (al2 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_alias_info2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if (!prs_unistr4("name", ps, depth, &al2->name))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO_CTR * ctr)
{
if ( !ctr )
@@ -3565,6 +3661,10 @@ BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO
if(!samr_io_alias_info1("alias_info1", &ctr->alias.info1, ps, depth))
return False;
break;
+ case 2:
+ if(!samr_io_alias_info2("alias_info2", &ctr->alias.info2, ps, depth))
+ return False;
+ break;
case 3:
if(!samr_io_alias_info3("alias_info3", &ctr->alias.info3, ps, depth))
return False;
@@ -4467,6 +4567,9 @@ BOOL samr_io_r_delete_dom_alias(const char *desc, SAMR_R_DELETE_DOM_ALIAS * r_u,
if(!prs_align(ps))
return False;
+ if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth))
+ return False;
+
if(!prs_ntstatus("status", ps, depth, &r_u->status))
return False;
@@ -5031,7 +5134,7 @@ inits a SAMR_Q_QUERY_USERINFO structure.
********************************************************************/
void init_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO * q_u,
- POLICY_HND *hnd, uint16 switch_value)
+ const POLICY_HND *hnd, uint16 switch_value)
{
DEBUG(5, ("init_samr_q_query_userinfo\n"));
@@ -5404,13 +5507,41 @@ static BOOL sam_io_user_info24(const char *desc, SAM_USER_INFO_24 * usr,
if (MARSHALLING(ps) && (usr->pw_len != 0)) {
if (!prs_uint16("pw_len", ps, depth, &usr->pw_len))
return False;
+ } else if (UNMARSHALLING(ps)) {
+ if (!prs_uint16("pw_len", ps, depth, &usr->pw_len))
+ return False;
}
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_user_info26(const char *desc, SAM_USER_INFO_26 * usr,
+ prs_struct *ps, int depth)
+{
+ if (usr == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "sam_io_user_info26");
+ depth++;
+
if(!prs_align(ps))
return False;
+ if(!prs_uint8s(False, "password", ps, depth, usr->pass,
+ sizeof(usr->pass)))
+ return False;
+
+ if (!prs_uint8("pw_len", ps, depth, &usr->pw_len))
+ return False;
+
return True;
}
+
/*************************************************************************
init_sam_user_info23
@@ -5506,7 +5637,11 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
copy_unistr2(&usr->uni_munged_dial, mung_dial);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
- memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+ if (hrs) {
+ memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+ } else {
+ ZERO_STRUCT(usr->logon_hrs);
+ }
}
/*************************************************************************
@@ -5598,7 +5733,11 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
data_blob_free(&blob);
- memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+ if (hrs) {
+ memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+ } else {
+ ZERO_STRUCT(usr->logon_hrs);
+ }
}
/*******************************************************************
@@ -5937,7 +6076,11 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
copy_unistr2(&usr->uni_munged_dial, mung_dial);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
- memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+ if (hrs) {
+ memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
+ } else {
+ ZERO_STRUCT(usr->logon_hrs);
+ }
}
/*************************************************************************
@@ -5947,7 +6090,7 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
*************************************************************************/
-NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *domain_sid)
+NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, struct samu *pw, DOM_SID *domain_sid)
{
NTTIME logon_time, logoff_time, kickoff_time,
pass_last_set_time, pass_can_change_time,
@@ -6213,7 +6356,7 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
return True;
}
-void init_sam_user_info20A(SAM_USER_INFO_20 *usr, SAM_ACCOUNT *pw)
+void init_sam_user_info20A(SAM_USER_INFO_20 *usr, struct samu *pw)
{
const char *munged_dial = pdb_get_munged_dial(pw);
DATA_BLOB blob = base64_decode_data_blob(munged_dial);
@@ -6475,6 +6618,16 @@ static BOOL samr_io_userinfo_ctr(const char *desc, SAM_USERINFO_CTR **ppctr,
}
ret = sam_io_user_info25("", ctr->info.id25, ps, depth);
break;
+ case 26:
+ if (UNMARSHALLING(ps))
+ ctr->info.id26 = PRS_ALLOC_MEM(ps,SAM_USER_INFO_26,1);
+
+ if (ctr->info.id26 == NULL) {
+ DEBUG(2,("samr_io_userinfo_ctr: info pointer not initialised\n"));
+ return False;
+ }
+ ret = sam_io_user_info26("", ctr->info.id26, ps, depth);
+ break;
default:
DEBUG(2, ("samr_io_userinfo_ctr: unknown switch level 0x%x\n", ctr->switch_value));
ret = False;
@@ -6541,7 +6694,7 @@ inits a SAMR_Q_SET_USERINFO structure.
********************************************************************/
void init_samr_q_set_userinfo(SAMR_Q_SET_USERINFO * q_u,
- POLICY_HND *hnd, DATA_BLOB *sess_key,
+ const POLICY_HND *hnd, DATA_BLOB *sess_key,
uint16 switch_value, void *info)
{
DEBUG(5, ("init_samr_q_set_userinfo\n"));
@@ -6615,7 +6768,7 @@ inits a SAMR_Q_SET_USERINFO2 structure.
********************************************************************/
void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
- POLICY_HND *hnd, DATA_BLOB *sess_key,
+ const POLICY_HND *hnd, DATA_BLOB *sess_key,
uint16 switch_value, SAM_USERINFO_CTR * ctr)
{
DEBUG(5, ("init_samr_q_set_userinfo2\n"));
@@ -6965,8 +7118,7 @@ void init_samr_q_connect_anon(SAMR_Q_CONNECT_ANON * q_u)
q_u->ptr = 1;
q_u->unknown_0 = 0x5c; /* server name (?!!) */
- q_u->unknown_1 = 0x01;
- q_u->access_mask = 0x20;
+ q_u->access_mask = MAXIMUM_ALLOWED_ACCESS;
}
/*******************************************************************
@@ -6987,9 +7139,11 @@ BOOL samr_io_q_connect_anon(const char *desc, SAMR_Q_CONNECT_ANON * q_u,
if(!prs_uint32("ptr ", ps, depth, &q_u->ptr))
return False;
- if(!prs_uint16("unknown_0", ps, depth, &q_u->unknown_0))
- return False;
- if(!prs_uint16("unknown_1", ps, depth, &q_u->unknown_1))
+ if (q_u->ptr) {
+ if(!prs_uint16("unknown_0", ps, depth, &q_u->unknown_0))
+ return False;
+ }
+ if(!prs_align(ps))
return False;
if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask))
return False;
@@ -7260,7 +7414,7 @@ inits a SAMR_R_CHGPASSWD_USER structure.
void init_samr_r_chgpasswd_user(SAMR_R_CHGPASSWD_USER * r_u, NTSTATUS status)
{
- DEBUG(5, ("init_r_chgpasswd_user\n"));
+ DEBUG(5, ("init_samr_r_chgpasswd_user\n"));
r_u->status = status;
}
@@ -7291,14 +7445,14 @@ BOOL samr_io_r_chgpasswd_user(const char *desc, SAMR_R_CHGPASSWD_USER * r_u,
inits a SAMR_Q_CHGPASSWD3 structure.
********************************************************************/
-void init_samr_q_chgpasswd3(SAMR_Q_CHGPASSWD3 * q_u,
- const char *dest_host, const char *user_name,
- const uchar nt_newpass[516],
- const uchar nt_oldhash[16],
- const uchar lm_newpass[516],
- const uchar lm_oldhash[16])
+void init_samr_q_chgpasswd_user3(SAMR_Q_CHGPASSWD_USER3 * q_u,
+ const char *dest_host, const char *user_name,
+ const uchar nt_newpass[516],
+ const uchar nt_oldhash[16],
+ const uchar lm_newpass[516],
+ const uchar lm_oldhash[16])
{
- DEBUG(5, ("init_samr_q_chgpasswd3\n"));
+ DEBUG(5, ("init_samr_q_chgpasswd_user3\n"));
q_u->ptr_0 = 1;
init_unistr2(&q_u->uni_dest_host, dest_host, UNI_FLAGS_NONE);
@@ -7322,13 +7476,13 @@ void init_samr_q_chgpasswd3(SAMR_Q_CHGPASSWD3 * q_u,
reads or writes a structure.
********************************************************************/
-BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u,
- prs_struct *ps, int depth)
+BOOL samr_io_q_chgpasswd_user3(const char *desc, SAMR_Q_CHGPASSWD_USER3 * q_u,
+ prs_struct *ps, int depth)
{
if (q_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_q_chgpasswd3");
+ prs_debug(ps, depth, desc, "samr_io_q_chgpasswd_user3");
depth++;
if(!prs_align(ps))
@@ -7369,14 +7523,28 @@ BOOL samr_io_q_chgpasswd3(const char *desc, SAMR_Q_CHGPASSWD3 * q_u,
}
/*******************************************************************
-inits a SAMR_R_CHGPASSWD3 structure.
+inits a SAMR_R_CHGPASSWD_USER3 structure.
********************************************************************/
-void init_samr_r_chgpasswd3(SAMR_R_CHGPASSWD3 * r_u, NTSTATUS status)
+void init_samr_r_chgpasswd_user3(SAMR_R_CHGPASSWD_USER3 *r_u, NTSTATUS status,
+ SAMR_CHANGE_REJECT *reject, SAM_UNK_INFO_1 *info)
{
- DEBUG(5, ("init_r_chgpasswd3\n"));
+ DEBUG(5, ("init_samr_r_chgpasswd_user3\n"));
r_u->status = status;
+ r_u->info = 0;
+ r_u->ptr_info = 0;
+ r_u->reject = 0;
+ r_u->ptr_reject = 0;
+
+ if (info) {
+ r_u->info = info;
+ r_u->ptr_info = 1;
+ }
+ if (reject && (reject->reject_reason != Undefined)) {
+ r_u->reject = reject;
+ r_u->ptr_reject = 1;
+ }
}
/*******************************************************************
@@ -7413,41 +7581,37 @@ BOOL samr_io_change_reject(const char *desc, SAMR_CHANGE_REJECT *reject, prs_str
reads or writes a structure.
********************************************************************/
-BOOL samr_io_r_chgpasswd3(const char *desc, SAMR_R_CHGPASSWD3 * r_u,
- prs_struct *ps, int depth)
+BOOL samr_io_r_chgpasswd_user3(const char *desc, SAMR_R_CHGPASSWD_USER3 *r_u,
+ prs_struct *ps, int depth)
{
- uint32 ptr_info, ptr_reject;
-
if (r_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_r_chgpasswd3");
+ prs_debug(ps, depth, desc, "samr_io_r_chgpasswd_user3");
depth++;
- if(!prs_align(ps))
+ if (!prs_align(ps))
return False;
- if(!prs_uint32("ptr_info", ps, depth, &ptr_info))
+ if (!prs_uint32("ptr_info", ps, depth, &r_u->ptr_info))
return False;
- if (ptr_info) {
-
+ if (r_u->ptr_info && r_u->info != NULL) {
/* SAM_UNK_INFO_1 */
- if(!sam_io_unk_info1("info", &r_u->info, ps, depth))
+ if (!sam_io_unk_info1("info", r_u->info, ps, depth))
return False;
}
- if(!prs_uint32("ptr_reject", ps, depth, &ptr_reject))
+ if (!prs_uint32("ptr_reject", ps, depth, &r_u->ptr_reject))
return False;
- if (ptr_reject) {
-
+ if (r_u->ptr_reject && r_u->reject != NULL) {
/* SAMR_CHANGE_REJECT */
- if(!samr_io_change_reject("reject", &r_u->reject, ps, depth))
+ if (!samr_io_change_reject("reject", r_u->reject, ps, depth))
return False;
}
- if(!prs_ntstatus("status", ps, depth, &r_u->status))
+ if (!prs_ntstatus("status", ps, depth, &r_u->status))
return False;
return True;
@@ -7629,8 +7793,10 @@ BOOL samr_io_q_set_domain_info(const char *desc, SAMR_Q_SET_DOMAIN_INFO *q_u,
if(!prs_align(ps))
return False;
- if ((q_u->ctr = PRS_ALLOC_MEM(ps, SAM_UNK_CTR, 1)) == NULL)
- return False;
+ if (UNMARSHALLING(ps)) {
+ if ((q_u->ctr = PRS_ALLOC_MEM(ps, SAM_UNK_CTR, 1)) == NULL)
+ return False;
+ }
switch (q_u->switch_value) {
diff --git a/source/rpc_parse/parse_shutdown.c b/source/rpc_parse/parse_shutdown.c
index de850ca4cc8..da338077333 100644
--- a/source/rpc_parse/parse_shutdown.c
+++ b/source/rpc_parse/parse_shutdown.c
@@ -32,9 +32,18 @@ void init_shutdown_q_init(SHUTDOWN_Q_INIT *q_s, const char *msg,
uint32 timeout, BOOL do_reboot, BOOL force)
{
q_s->server = TALLOC_P( get_talloc_ctx(), uint16 );
+ if (!q_s->server) {
+ smb_panic("init_shutdown_q_init: talloc fail.\n");
+ return;
+ }
+
*q_s->server = 0x1;
q_s->message = TALLOC_ZERO_P( get_talloc_ctx(), UNISTR4 );
+ if (!q_s->message) {
+ smb_panic("init_shutdown_q_init: talloc fail.\n");
+ return;
+ }
if ( msg && *msg ) {
init_unistr4( q_s->message, msg, UNI_FLAGS_NONE );
@@ -206,6 +215,11 @@ Inits a structure.
void init_shutdown_q_abort(SHUTDOWN_Q_ABORT *q_s)
{
q_s->server = TALLOC_P( get_talloc_ctx(), uint16 );
+ if (!q_s->server) {
+ smb_panic("init_shutdown_q_abort: talloc fail.\n");
+ return;
+ }
+
*q_s->server = 0x1;
}
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index 45b683e9c60..ec2d6b84300 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -899,6 +899,9 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u,
DEBUG(5,("make_spoolss_q_open_printer_ex\n"));
q_u->printername = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+ if (!q_u->printername) {
+ return False;
+ }
init_unistr2(q_u->printername, printername, UNI_STR_TERMINATE);
q_u->printer_default.datatype_ptr = 0;
@@ -912,6 +915,9 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u,
q_u->user_ctr.level = 1;
q_u->user_ctr.user.user1 = TALLOC_P( get_talloc_ctx(), SPOOL_USER_1 );
+ if (!q_u->user_ctr.user.user1) {
+ return False;
+ }
q_u->user_ctr.user.user1->size = strlen(clientname) + strlen(user_name) + 10;
q_u->user_ctr.user.user1->build = 1381;
q_u->user_ctr.user.user1->major = 2;
@@ -919,7 +925,13 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u,
q_u->user_ctr.user.user1->processor = 0;
q_u->user_ctr.user.user1->client_name = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+ if (!q_u->user_ctr.user.user1->client_name) {
+ return False;
+ }
q_u->user_ctr.user.user1->user_name = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+ if (!q_u->user_ctr.user.user1->user_name) {
+ return False;
+ }
init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE);
init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE);
@@ -937,12 +949,15 @@ BOOL make_spoolss_q_addprinterex( TALLOC_CTX *mem_ctx, SPOOL_Q_ADDPRINTEREX *q_u
{
DEBUG(5,("make_spoolss_q_addprinterex\n"));
- if (!ctr)
+ if (!ctr || !ctr->printers_2)
return False;
ZERO_STRUCTP(q_u);
q_u->server_name = TALLOC_P( mem_ctx, UNISTR2 );
+ if (!q_u->server_name) {
+ return False;
+ }
init_unistr2(q_u->server_name, srv_name, UNI_FLAGS_NONE);
q_u->level = level;
@@ -965,14 +980,22 @@ BOOL make_spoolss_q_addprinterex( TALLOC_CTX *mem_ctx, SPOOL_Q_ADDPRINTEREX *q_u
q_u->user_ctr.level = 1;
q_u->user_ctr.user.user1 = TALLOC_P( get_talloc_ctx(), SPOOL_USER_1 );
+ if (!q_u->user_ctr.user.user1) {
+ return False;
+ }
q_u->user_ctr.user.user1->build = 1381;
q_u->user_ctr.user.user1->major = 2;
q_u->user_ctr.user.user1->minor = 0;
q_u->user_ctr.user.user1->processor = 0;
q_u->user_ctr.user.user1->client_name = TALLOC_P( mem_ctx, UNISTR2 );
+ if (!q_u->user_ctr.user.user1->client_name) {
+ return False;
+ }
q_u->user_ctr.user.user1->user_name = TALLOC_P( mem_ctx, UNISTR2 );
-
+ if (!q_u->user_ctr.user.user1->user_name) {
+ return False;
+ }
init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE);
init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE);
@@ -3733,14 +3756,14 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
SEC_DESC *secdesc;
DEVICEMODE *devmode;
- if (q_u == NULL)
+ if (!q_u || !info)
return False;
memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
q_u->level = level;
q_u->info.level = level;
- q_u->info.info_ptr = (info != NULL) ? 1 : 0;
+ q_u->info.info_ptr = 1; /* Info is != NULL, see above */
switch (level) {
/* There's no such thing as a setprinter level 1 */
@@ -4968,7 +4991,7 @@ BOOL spool_io_printer_driver_info_level_6(const char *desc, SPOOL_PRINTER_DRIVER
********************************************************************/
static BOOL uniarray_2_dosarray(BUFFER5 *buf5, fstring **ar)
{
- fstring f, *tar;
+ fstring f;
int n = 0;
char *src;
@@ -4981,11 +5004,9 @@ static BOOL uniarray_2_dosarray(BUFFER5 *buf5, fstring **ar)
while (src < ((char *)buf5->buffer) + buf5->buf_len*2) {
rpcstr_pull(f, src, sizeof(f)-1, -1, STR_TERMINATE);
src = skip_unibuf(src, 2*buf5->buf_len - PTR_DIFF(src,buf5->buffer));
- tar = SMB_REALLOC_ARRAY(*ar, fstring, n+2);
- if (!tar)
+ *ar = SMB_REALLOC_ARRAY(*ar, fstring, n+2);
+ if (!*ar)
return False;
- else
- *ar = tar;
fstrcpy((*ar)[n], f);
n++;
}
@@ -5063,13 +5084,17 @@ BOOL make_spoolss_q_addprinterdriver(TALLOC_CTX *mem_ctx,
{
DEBUG(5,("make_spoolss_q_addprinterdriver\n"));
- q_u->server_name_ptr = (srv_name!=NULL)?1:0;
+ if (!srv_name || !info) {
+ return False;
+ }
+
+ q_u->server_name_ptr = 1; /* srv_name is != NULL, see above */
init_unistr2(&q_u->server_name, srv_name, UNI_STR_TERMINATE);
q_u->level = level;
q_u->info.level = level;
- q_u->info.ptr = (info!=NULL)?1:0;
+ q_u->info.ptr = 1; /* Info is != NULL, see above */
switch (level)
{
/* info level 3 is supported by Windows 95/98, WinNT and Win2k */
@@ -7406,3 +7431,174 @@ BOOL make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
return True;
}
+
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL spoolss_io_q_xcvdataport(const char *desc, SPOOL_Q_XCVDATAPORT *q_u, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "spoolss_io_q_xcvdataport");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
+ return False;
+
+ if(!smb_io_unistr2("", &q_u->dataname, True, ps, depth))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if(!prs_rpcbuffer("", ps, depth, &q_u->indata))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("indata_len", ps, depth, &q_u->indata_len))
+ return False;
+ if (!prs_uint32("offered", ps, depth, &q_u->offered))
+ return False;
+ if (!prs_uint32("unknown", ps, depth, &q_u->unknown))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL spoolss_io_r_xcvdataport(const char *desc, SPOOL_R_XCVDATAPORT *r_u, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "spoolss_io_r_xcvdataport");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_rpcbuffer("", ps, depth, &r_u->outdata))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("needed", ps, depth, &r_u->needed))
+ return False;
+ if (!prs_uint32("unknown", ps, depth, &r_u->unknown))
+ return False;
+
+ if(!prs_werror("status", ps, depth, &r_u->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL make_monitorui_buf( RPC_BUFFER *buf, const char *dllname )
+{
+ UNISTR string;
+
+ if ( !buf )
+ return False;
+
+ init_unistr( &string, dllname );
+
+ if ( !prs_unistr( "ui_dll", &buf->prs, 0, &string ) )
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+#define PORT_DATA_1_PAD 540
+
+static BOOL smb_io_port_data_1( const char *desc, RPC_BUFFER *buf, int depth, SPOOL_PORT_DATA_1 *p1 )
+{
+ prs_struct *ps = &buf->prs;
+ uint8 padding[PORT_DATA_1_PAD];
+
+ prs_debug(ps, depth, desc, "smb_io_port_data_1");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if( !prs_uint16s(True, "portname", ps, depth, p1->portname, MAX_PORTNAME))
+ return False;
+
+ if (!prs_uint32("version", ps, depth, &p1->version))
+ return False;
+ if (!prs_uint32("protocol", ps, depth, &p1->protocol))
+ return False;
+ if (!prs_uint32("size", ps, depth, &p1->size))
+ return False;
+ if (!prs_uint32("reserved", ps, depth, &p1->reserved))
+ return False;
+
+ if( !prs_uint16s(True, "hostaddress", ps, depth, p1->hostaddress, MAX_NETWORK_NAME))
+ return False;
+ if( !prs_uint16s(True, "snmpcommunity", ps, depth, p1->snmpcommunity, MAX_SNMP_COMM_NAME))
+ return False;
+
+ if (!prs_uint32("dblspool", ps, depth, &p1->dblspool))
+ return False;
+
+ if( !prs_uint16s(True, "queue", ps, depth, p1->queue, MAX_QUEUE_NAME))
+ return False;
+ if( !prs_uint16s(True, "ipaddress", ps, depth, p1->ipaddress, MAX_IPADDR_STRING))
+ return False;
+
+ if( !prs_uint8s(False, "", ps, depth, padding, PORT_DATA_1_PAD))
+ return False;
+
+ if (!prs_uint32("port", ps, depth, &p1->port))
+ return False;
+ if (!prs_uint32("snmpenabled", ps, depth, &p1->snmpenabled))
+ return False;
+ if (!prs_uint32("snmpdevindex", ps, depth, &p1->snmpdevindex))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL convert_port_data_1( NT_PORT_DATA_1 *port1, RPC_BUFFER *buf )
+{
+ SPOOL_PORT_DATA_1 spdata_1;
+
+ ZERO_STRUCT( spdata_1 );
+
+ if ( !smb_io_port_data_1( "port_data_1", buf, 0, &spdata_1 ) )
+ return False;
+
+ rpcstr_pull(port1->name, spdata_1.portname, sizeof(port1->name), -1, 0);
+ rpcstr_pull(port1->queue, spdata_1.queue, sizeof(port1->queue), -1, 0);
+ rpcstr_pull(port1->hostaddr, spdata_1.hostaddress, sizeof(port1->hostaddr), -1, 0);
+
+ port1->port = spdata_1.port;
+
+ switch ( spdata_1.protocol ) {
+ case 1:
+ port1->protocol = PORT_PROTOCOL_DIRECT;
+ break;
+ case 2:
+ port1->protocol = PORT_PROTOCOL_LPR;
+ break;
+ default:
+ DEBUG(3,("convert_port_data_1: unknown protocol [%d]!\n",
+ spdata_1.protocol));
+ return False;
+ }
+
+ return True;
+}
+
diff --git a/source/rpc_server/srv_dfs.c b/source/rpc_server/srv_dfs.c
index 42be7c5a357..44a9c06a3ca 100644
--- a/source/rpc_server/srv_dfs.c
+++ b/source/rpc_server/srv_dfs.c
@@ -1,177 +1,602 @@
-/*
- * Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines for Dfs
- * Copyright (C) Andrew Tridgell 1992-1997,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Shirish Kalele 2000,
- * Copyright (C) Jeremy Allison 2001,
- * 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.
+/*
+ * Unix SMB/CIFS implementation.
+ * server auto-generated by pidl. DO NOT MODIFY!
*/
-/* This is the interface to the dfs pipe. */
-
#include "includes.h"
#include "nterr.h"
#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_MSDFS
+#define DBGC_CLASS DBGC_RPC
-/**********************************************************************
- api_dfs_exist
- **********************************************************************/
+/******************************************************************
+ api_dfs_GetManagerVersion
+ *****************************************************************/
-static BOOL api_dfs_exist(pipes_struct *p)
+static BOOL api_dfs_GetManagerVersion(pipes_struct *p)
{
- DFS_Q_DFS_EXIST q_u;
- DFS_R_DFS_EXIST r_u;
+ NETDFS_Q_DFS_GETMANAGERVERSION q_u;
+ NETDFS_R_DFS_GETMANAGERVERSION r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_GetManagerVersion("", &q_u, data, 0))
+ return False;
+
+ _dfs_GetManagerVersion(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_GetManagerVersion("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_Add
+ *****************************************************************/
- if(!dfs_io_q_dfs_exist("", &q_u, data, 0))
+static BOOL api_dfs_Add(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ADD q_u;
+ NETDFS_R_DFS_ADD r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_Add("", &q_u, data, 0))
return False;
- r_u.status = _dfs_exist(p, &q_u, &r_u);
+ r_u.status = _dfs_Add(p, &q_u, &r_u);
- if (!dfs_io_r_dfs_exist("", &r_u, rdata, 0))
+ if (!netdfs_io_r_dfs_Add("", &r_u, rdata, 0))
return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_Remove
+ *****************************************************************/
+static BOOL api_dfs_Remove(pipes_struct *p)
+{
+ NETDFS_Q_DFS_REMOVE q_u;
+ NETDFS_R_DFS_REMOVE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_Remove("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_Remove(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_Remove("", &r_u, rdata, 0))
+ return False;
+
return True;
}
+/******************************************************************
+ api_dfs_SetInfo
+ *****************************************************************/
-/*****************************************************************
- api_dfs_add
+static BOOL api_dfs_SetInfo(pipes_struct *p)
+{
+ NETDFS_Q_DFS_SETINFO q_u;
+ NETDFS_R_DFS_SETINFO r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_SetInfo("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_SetInfo(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_SetInfo("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_GetInfo
*****************************************************************/
-static BOOL api_dfs_add(pipes_struct *p)
+static BOOL api_dfs_GetInfo(pipes_struct *p)
{
- DFS_Q_DFS_ADD q_u;
- DFS_R_DFS_ADD r_u;
+ NETDFS_Q_DFS_GETINFO q_u;
+ NETDFS_R_DFS_GETINFO r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_GetInfo("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_GetInfo(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_GetInfo("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_Enum
+ *****************************************************************/
+static BOOL api_dfs_Enum(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ENUM q_u;
+ NETDFS_R_DFS_ENUM r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!dfs_io_q_dfs_add("", &q_u, data, 0))
+ if (!netdfs_io_q_dfs_Enum("", &q_u, data, 0))
return False;
- r_u.status = _dfs_add(p, &q_u, &r_u);
+ r_u.status = _dfs_Enum(p, &q_u, &r_u);
- if (!dfs_io_r_dfs_add("", &r_u, rdata, 0))
+ if (!netdfs_io_r_dfs_Enum("", &r_u, rdata, 0))
return False;
return True;
}
+/******************************************************************
+ api_dfs_Rename
+ *****************************************************************/
-/*****************************************************************
- api_dfs_remove
+static BOOL api_dfs_Rename(pipes_struct *p)
+{
+ NETDFS_Q_DFS_RENAME q_u;
+ NETDFS_R_DFS_RENAME r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_Rename("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_Rename(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_Rename("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_Move
*****************************************************************/
-static BOOL api_dfs_remove(pipes_struct *p)
+static BOOL api_dfs_Move(pipes_struct *p)
{
- DFS_Q_DFS_REMOVE q_u;
- DFS_R_DFS_REMOVE r_u;
+ NETDFS_Q_DFS_MOVE q_u;
+ NETDFS_R_DFS_MOVE r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!dfs_io_q_dfs_remove("", &q_u, data, 0))
+ if (!netdfs_io_q_dfs_Move("", &q_u, data, 0))
return False;
- r_u.status = _dfs_remove(p, &q_u, &r_u);
+ r_u.status = _dfs_Move(p, &q_u, &r_u);
- if (!dfs_io_r_dfs_remove("", &r_u, rdata, 0))
+ if (!netdfs_io_r_dfs_Move("", &r_u, rdata, 0))
return False;
return True;
}
+/******************************************************************
+ api_dfs_ManagerGetConfigInfo
+ *****************************************************************/
-/*******************************************************************
- api_dfs_get_info
- *******************************************************************/
+static BOOL api_dfs_ManagerGetConfigInfo(pipes_struct *p)
+{
+ NETDFS_Q_DFS_MANAGERGETCONFIGINFO q_u;
+ NETDFS_R_DFS_MANAGERGETCONFIGINFO r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_ManagerGetConfigInfo("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_ManagerGetConfigInfo(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_ManagerGetConfigInfo("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_ManagerSendSiteInfo
+ *****************************************************************/
-static BOOL api_dfs_get_info(pipes_struct *p)
+static BOOL api_dfs_ManagerSendSiteInfo(pipes_struct *p)
{
- DFS_Q_DFS_GET_INFO q_u;
- DFS_R_DFS_GET_INFO r_u;
+ NETDFS_Q_DFS_MANAGERSENDSITEINFO q_u;
+ NETDFS_R_DFS_MANAGERSENDSITEINFO r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_ManagerSendSiteInfo("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_ManagerSendSiteInfo(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_ManagerSendSiteInfo("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_AddFtRoot
+ *****************************************************************/
+static BOOL api_dfs_AddFtRoot(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ADDFTROOT q_u;
+ NETDFS_R_DFS_ADDFTROOT r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!dfs_io_q_dfs_get_info("", &q_u, data, 0))
+ if (!netdfs_io_q_dfs_AddFtRoot("", &q_u, data, 0))
return False;
- r_u.status = _dfs_get_info(p, &q_u, &r_u);
+ r_u.status = _dfs_AddFtRoot(p, &q_u, &r_u);
- if(!dfs_io_r_dfs_get_info("", &r_u, rdata, 0))
+ if (!netdfs_io_r_dfs_AddFtRoot("", &r_u, rdata, 0))
return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_RemoveFtRoot
+ *****************************************************************/
+static BOOL api_dfs_RemoveFtRoot(pipes_struct *p)
+{
+ NETDFS_Q_DFS_REMOVEFTROOT q_u;
+ NETDFS_R_DFS_REMOVEFTROOT r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_RemoveFtRoot("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_RemoveFtRoot(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_RemoveFtRoot("", &r_u, rdata, 0))
+ return False;
+
return True;
}
+/******************************************************************
+ api_dfs_AddStdRoot
+ *****************************************************************/
-/*******************************************************************
- api_dfs_enum
- *******************************************************************/
+static BOOL api_dfs_AddStdRoot(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ADDSTDROOT q_u;
+ NETDFS_R_DFS_ADDSTDROOT r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_AddStdRoot("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_AddStdRoot(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_AddStdRoot("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_RemoveStdRoot
+ *****************************************************************/
-static BOOL api_dfs_enum(pipes_struct *p)
+static BOOL api_dfs_RemoveStdRoot(pipes_struct *p)
{
- DFS_Q_DFS_ENUM q_u;
- DFS_R_DFS_ENUM r_u;
+ NETDFS_Q_DFS_REMOVESTDROOT q_u;
+ NETDFS_R_DFS_REMOVESTDROOT r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_RemoveStdRoot("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_RemoveStdRoot(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_RemoveStdRoot("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_ManagerInitialize
+ *****************************************************************/
+static BOOL api_dfs_ManagerInitialize(pipes_struct *p)
+{
+ NETDFS_Q_DFS_MANAGERINITIALIZE q_u;
+ NETDFS_R_DFS_MANAGERINITIALIZE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_ManagerInitialize("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_ManagerInitialize(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_ManagerInitialize("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_AddStdRootForced
+ *****************************************************************/
- if(!dfs_io_q_dfs_enum("", &q_u, data, 0))
+static BOOL api_dfs_AddStdRootForced(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ADDSTDROOTFORCED q_u;
+ NETDFS_R_DFS_ADDSTDROOTFORCED r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_AddStdRootForced("", &q_u, data, 0))
return False;
- r_u.status = _dfs_enum(p, &q_u, &r_u);
+ r_u.status = _dfs_AddStdRootForced(p, &q_u, &r_u);
- if(!dfs_io_r_dfs_enum("", &r_u, rdata, 0))
+ if (!netdfs_io_r_dfs_AddStdRootForced("", &r_u, rdata, 0))
return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_GetDcAddress
+ *****************************************************************/
+static BOOL api_dfs_GetDcAddress(pipes_struct *p)
+{
+ NETDFS_Q_DFS_GETDCADDRESS q_u;
+ NETDFS_R_DFS_GETDCADDRESS r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_GetDcAddress("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_GetDcAddress(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_GetDcAddress("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_SetDcAddress
+ *****************************************************************/
+
+static BOOL api_dfs_SetDcAddress(pipes_struct *p)
+{
+ NETDFS_Q_DFS_SETDCADDRESS q_u;
+ NETDFS_R_DFS_SETDCADDRESS r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_SetDcAddress("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_SetDcAddress(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_SetDcAddress("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_FlushFtTable
+ *****************************************************************/
+
+static BOOL api_dfs_FlushFtTable(pipes_struct *p)
+{
+ NETDFS_Q_DFS_FLUSHFTTABLE q_u;
+ NETDFS_R_DFS_FLUSHFTTABLE r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_FlushFtTable("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_FlushFtTable(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_FlushFtTable("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_Add2
+ *****************************************************************/
+
+static BOOL api_dfs_Add2(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ADD2 q_u;
+ NETDFS_R_DFS_ADD2 r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_Add2("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_Add2(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_Add2("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_Remove2
+ *****************************************************************/
+
+static BOOL api_dfs_Remove2(pipes_struct *p)
+{
+ NETDFS_Q_DFS_REMOVE2 q_u;
+ NETDFS_R_DFS_REMOVE2 r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_Remove2("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_Remove2(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_Remove2("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_EnumEx
+ *****************************************************************/
+
+static BOOL api_dfs_EnumEx(pipes_struct *p)
+{
+ NETDFS_Q_DFS_ENUMEX q_u;
+ NETDFS_R_DFS_ENUMEX r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_EnumEx("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_EnumEx(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_EnumEx("", &r_u, rdata, 0))
+ return False;
+
+ return True;
+}
+/******************************************************************
+ api_dfs_SetInfo2
+ *****************************************************************/
+
+static BOOL api_dfs_SetInfo2(pipes_struct *p)
+{
+ NETDFS_Q_DFS_SETINFO2 q_u;
+ NETDFS_R_DFS_SETINFO2 r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if (!netdfs_io_q_dfs_SetInfo2("", &q_u, data, 0))
+ return False;
+
+ r_u.status = _dfs_SetInfo2(p, &q_u, &r_u);
+
+ if (!netdfs_io_r_dfs_SetInfo2("", &r_u, rdata, 0))
+ return False;
+
return True;
}
-/*******************************************************************
-\pipe\netdfs commands
-********************************************************************/
-static struct api_struct api_netdfs_cmds[] =
+/* Tables */
+static struct api_struct api_netdfs_cmds[] =
{
- {"DFS_EXIST", DFS_EXIST, api_dfs_exist },
- {"DFS_ADD", DFS_ADD, api_dfs_add },
- {"DFS_REMOVE", DFS_REMOVE, api_dfs_remove },
- {"DFS_GET_INFO", DFS_GET_INFO, api_dfs_get_info },
- {"DFS_ENUM", DFS_ENUM, api_dfs_enum }
+ {"DFS_GETMANAGERVERSION", DFS_GETMANAGERVERSION, api_dfs_GetManagerVersion},
+ {"DFS_ADD", DFS_ADD, api_dfs_Add},
+ {"DFS_REMOVE", DFS_REMOVE, api_dfs_Remove},
+ {"DFS_SETINFO", DFS_SETINFO, api_dfs_SetInfo},
+ {"DFS_GETINFO", DFS_GETINFO, api_dfs_GetInfo},
+ {"DFS_ENUM", DFS_ENUM, api_dfs_Enum},
+ {"DFS_RENAME", DFS_RENAME, api_dfs_Rename},
+ {"DFS_MOVE", DFS_MOVE, api_dfs_Move},
+ {"DFS_MANAGERGETCONFIGINFO", DFS_MANAGERGETCONFIGINFO, api_dfs_ManagerGetConfigInfo},
+ {"DFS_MANAGERSENDSITEINFO", DFS_MANAGERSENDSITEINFO, api_dfs_ManagerSendSiteInfo},
+ {"DFS_ADDFTROOT", DFS_ADDFTROOT, api_dfs_AddFtRoot},
+ {"DFS_REMOVEFTROOT", DFS_REMOVEFTROOT, api_dfs_RemoveFtRoot},
+ {"DFS_ADDSTDROOT", DFS_ADDSTDROOT, api_dfs_AddStdRoot},
+ {"DFS_REMOVESTDROOT", DFS_REMOVESTDROOT, api_dfs_RemoveStdRoot},
+ {"DFS_MANAGERINITIALIZE", DFS_MANAGERINITIALIZE, api_dfs_ManagerInitialize},
+ {"DFS_ADDSTDROOTFORCED", DFS_ADDSTDROOTFORCED, api_dfs_AddStdRootForced},
+ {"DFS_GETDCADDRESS", DFS_GETDCADDRESS, api_dfs_GetDcAddress},
+ {"DFS_SETDCADDRESS", DFS_SETDCADDRESS, api_dfs_SetDcAddress},
+ {"DFS_FLUSHFTTABLE", DFS_FLUSHFTTABLE, api_dfs_FlushFtTable},
+ {"DFS_ADD2", DFS_ADD2, api_dfs_Add2},
+ {"DFS_REMOVE2", DFS_REMOVE2, api_dfs_Remove2},
+ {"DFS_ENUMEX", DFS_ENUMEX, api_dfs_EnumEx},
+ {"DFS_SETINFO2", DFS_SETINFO2, api_dfs_SetInfo2},
};
-void netdfs_get_pipe_fns( struct api_struct **fns, int *n_fns )
+void netdfs_get_pipe_fns(struct api_struct **fns, int *n_fns)
{
*fns = api_netdfs_cmds;
*n_fns = sizeof(api_netdfs_cmds) / sizeof(struct api_struct);
}
-NTSTATUS rpc_dfs_init(void)
+NTSTATUS rpc_netdfs_init(void)
{
- return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "netdfs", "netdfs", api_netdfs_cmds,
- sizeof(api_netdfs_cmds) / sizeof(struct api_struct));
+ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "netdfs", "netdfs", api_netdfs_cmds, sizeof(api_netdfs_cmds) / sizeof(struct api_struct));
}
diff --git a/source/rpc_server/srv_dfs_nt.c b/source/rpc_server/srv_dfs_nt.c
index f61348ee05d..f04d8c37c3d 100644
--- a/source/rpc_server/srv_dfs_nt.c
+++ b/source/rpc_server/srv_dfs_nt.c
@@ -1,10 +1,9 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines for Dfs
- * Copyright (C) Andrew Tridgell 1992-1997,
- * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Shirish Kalele 2000.
- * Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Shirish Kalele 2000.
+ * Copyright (C) Jeremy Allison 2001.
+ * 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
@@ -24,7 +23,6 @@
/* This is the implementation of the dfs pipe. */
#include "includes.h"
-#include "nterr.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_MSDFS
@@ -32,7 +30,7 @@
/* This function does not return a WERROR or NTSTATUS code but rather 1 if
dfs exists, or 0 otherwise. */
-uint32 _dfs_exist(pipes_struct *p, DFS_Q_DFS_EXIST *q_u, DFS_R_DFS_EXIST *r_u)
+uint32 _dfs_GetManagerVersion(pipes_struct *p, NETDFS_Q_DFS_GETMANAGERVERSION *q_u, NETDFS_R_DFS_GETMANAGERVERSION *r_u)
{
if(lp_host_msdfs())
return 1;
@@ -40,7 +38,7 @@ uint32 _dfs_exist(pipes_struct *p, DFS_Q_DFS_EXIST *q_u, DFS_R_DFS_EXIST *r_u)
return 0;
}
-WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
+WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
{
struct current_user user;
struct junction_map jn;
@@ -52,14 +50,14 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
get_current_user(&user,p);
- if (user.uid != 0) {
+ if (user.ut.uid != 0) {
DEBUG(10,("_dfs_add: uid != 0. Access denied.\n"));
return WERR_ACCESS_DENIED;
}
- unistr2_to_ascii(dfspath, &q_u->DfsEntryPath, sizeof(dfspath)-1);
- unistr2_to_ascii(servername, &q_u->ServerName, sizeof(servername)-1);
- unistr2_to_ascii(sharename, &q_u->ShareName, sizeof(sharename)-1);
+ unistr2_to_ascii(dfspath, &q_u->path, sizeof(dfspath)-1);
+ unistr2_to_ascii(servername, &q_u->server, sizeof(servername)-1);
+ unistr2_to_ascii(sharename, &q_u->share, sizeof(sharename)-1);
DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",
dfspath, servername, sharename));
@@ -103,8 +101,8 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
return WERR_OK;
}
-WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
- DFS_R_DFS_REMOVE *r_u)
+WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u,
+ NETDFS_R_DFS_REMOVE *r_u)
{
struct current_user user;
struct junction_map jn;
@@ -115,21 +113,21 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
get_current_user(&user,p);
- if (user.uid != 0) {
+ if (user.ut.uid != 0) {
DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n"));
return WERR_ACCESS_DENIED;
}
- unistr2_to_ascii(dfspath, &q_u->DfsEntryPath, sizeof(dfspath)-1);
- if(q_u->ptr_ServerName) {
- unistr2_to_ascii(servername, &q_u->ServerName, sizeof(servername)-1);
+ unistr2_to_ascii(dfspath, &q_u->path, sizeof(dfspath)-1);
+ if(q_u->ptr0_server) {
+ unistr2_to_ascii(servername, &q_u->server, sizeof(servername)-1);
}
- if(q_u->ptr_ShareName) {
- unistr2_to_ascii(sharename, &q_u->ShareName, sizeof(sharename)-1);
+ if(q_u->ptr0_share) {
+ unistr2_to_ascii(sharename, &q_u->share, sizeof(sharename)-1);
}
- if(q_u->ptr_ServerName && q_u->ptr_ShareName) {
+ if(q_u->ptr0_server && q_u->ptr0_share) {
pstrcpy(altpath, servername);
pstrcat(altpath, "\\");
pstrcat(altpath, sharename);
@@ -144,7 +142,7 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
}
/* if no server-share pair given, remove the msdfs link completely */
- if(!q_u->ptr_ServerName && !q_u->ptr_ShareName) {
+ if(!q_u->ptr0_server && !q_u->ptr0_share) {
if(!remove_msdfs_link(&jn)) {
vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_DFS_NO_SUCH_VOL;
@@ -189,167 +187,164 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
return WERR_OK;
}
-static BOOL init_reply_dfs_info_1(struct junction_map* j, DFS_INFO_1* dfs1, int num_j)
+static BOOL init_reply_dfs_info_1(struct junction_map* j, NETDFS_DFS_INFO1* dfs1)
{
- int i=0;
- for(i=0;i<num_j;i++) {
- pstring str;
- dfs1[i].ptr_entrypath = 1;
- slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
- j[i].service_name, j[i].volume_name);
- DEBUG(5,("init_reply_dfs_info_1: %d) initing entrypath: %s\n",i,str));
- init_unistr2(&dfs1[i].entrypath,str,UNI_STR_TERMINATE);
- }
+ pstring str;
+ dfs1->ptr0_path = 1;
+ slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
+ j->service_name, j->volume_name);
+ DEBUG(5,("init_reply_dfs_info_1: initing entrypath: %s\n",str));
+ init_unistr2(&dfs1->path,str,UNI_STR_TERMINATE);
return True;
}
-static BOOL init_reply_dfs_info_2(struct junction_map* j, DFS_INFO_2* dfs2, int num_j)
+static BOOL init_reply_dfs_info_2(struct junction_map* j, NETDFS_DFS_INFO2* dfs2)
{
- int i=0;
- for(i=0;i<num_j;i++) {
- pstring str;
- dfs2[i].ptr_entrypath = 1;
- slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
- j[i].service_name, j[i].volume_name);
- init_unistr2(&dfs2[i].entrypath, str, UNI_STR_TERMINATE);
- dfs2[i].ptr_comment = 0;
- dfs2[i].state = 1; /* set up state of dfs junction as OK */
- dfs2[i].num_storages = j[i].referral_count;
- }
+ pstring str;
+ dfs2->ptr0_path = 1;
+ slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
+ j->service_name, j->volume_name);
+ init_unistr2(&dfs2->path, str, UNI_STR_TERMINATE);
+ dfs2->ptr0_comment = 0;
+ dfs2->state = 1; /* set up state of dfs junction as OK */
+ dfs2->num_stores = j->referral_count;
return True;
}
-static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_INFO_3* dfs3, int num_j)
+static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, NETDFS_DFS_INFO3* dfs3)
{
- int i=0,ii=0;
- for(i=0;i<num_j;i++) {
- pstring str;
- dfs3[i].ptr_entrypath = 1;
- if (j[i].volume_name[0] == '\0')
- slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s",
- global_myname(), j[i].service_name);
- else
- slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
- j[i].service_name, j[i].volume_name);
-
- init_unistr2(&dfs3[i].entrypath, str, UNI_STR_TERMINATE);
- dfs3[i].ptr_comment = 1;
- init_unistr2(&dfs3[i].comment, "", UNI_STR_TERMINATE);
- dfs3[i].state = 1;
- dfs3[i].num_storages = dfs3[i].num_storage_infos = j[i].referral_count;
- dfs3[i].ptr_storages = 1;
-
- /* also enumerate the storages */
- dfs3[i].storages = TALLOC_ARRAY(ctx, DFS_STORAGE_INFO, j[i].referral_count);
- if (!dfs3[i].storages)
- return False;
-
- memset(dfs3[i].storages, '\0', j[i].referral_count * sizeof(DFS_STORAGE_INFO));
-
- for(ii=0;ii<j[i].referral_count;ii++) {
- char* p;
- pstring path;
- DFS_STORAGE_INFO* stor = &(dfs3[i].storages[ii]);
- struct referral* ref = &(j[i].referral_list[ii]);
-
- pstrcpy(path, ref->alternate_path);
- trim_char(path,'\\','\0');
- p = strrchr_m(path,'\\');
- if(p==NULL) {
- DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path));
- continue;
- }
- *p = '\0';
- DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1));
- stor->state = 2; /* set all storages as ONLINE */
- init_unistr2(&stor->servername, path, UNI_STR_TERMINATE);
- init_unistr2(&stor->sharename, p+1, UNI_STR_TERMINATE);
- stor->ptr_servername = stor->ptr_sharename = 1;
+ int ii;
+ pstring str;
+ dfs3->ptr0_path = 1;
+ if (j->volume_name[0] == '\0')
+ slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s",
+ global_myname(), j->service_name);
+ else
+ slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
+ j->service_name, j->volume_name);
+
+ init_unistr2(&dfs3->path, str, UNI_STR_TERMINATE);
+ dfs3->ptr0_comment = 1;
+ init_unistr2(&dfs3->comment, "", UNI_STR_TERMINATE);
+ dfs3->state = 1;
+ dfs3->num_stores = dfs3->size_stores = j->referral_count;
+ dfs3->ptr0_stores = 1;
+
+ /* also enumerate the stores */
+ dfs3->stores = TALLOC_ARRAY(ctx, NETDFS_DFS_STORAGEINFO, j->referral_count);
+ if (!dfs3->stores)
+ return False;
+
+ memset(dfs3->stores, '\0', j->referral_count * sizeof(NETDFS_DFS_STORAGEINFO));
+
+ for(ii=0;ii<j->referral_count;ii++) {
+ char* p;
+ pstring path;
+ NETDFS_DFS_STORAGEINFO* stor = &(dfs3->stores[ii]);
+ struct referral* ref = &(j->referral_list[ii]);
+
+ pstrcpy(path, ref->alternate_path);
+ trim_char(path,'\\','\0');
+ p = strrchr_m(path,'\\');
+ if(p==NULL) {
+ DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path));
+ continue;
}
+ *p = '\0';
+ DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1));
+ stor->state = 2; /* set all stores as ONLINE */
+ init_unistr2(&stor->server, path, UNI_STR_TERMINATE);
+ init_unistr2(&stor->share, p+1, UNI_STR_TERMINATE);
+ stor->ptr0_server = stor->ptr0_share = 1;
}
return True;
}
-static WERROR init_reply_dfs_ctr(TALLOC_CTX *ctx, uint32 level,
- DFS_INFO_CTR* ctr, struct junction_map* jn,
- int num_jn)
+WERROR _dfs_Enum(pipes_struct *p, NETDFS_Q_DFS_ENUM *q_u, NETDFS_R_DFS_ENUM *r_u)
{
- /* do the levels */
- switch(level) {
+ uint32 level = q_u->level;
+ struct junction_map jn[MAX_MSDFS_JUNCTIONS];
+ int num_jn = 0;
+ int i;
+
+ num_jn = enum_msdfs_links(p->mem_ctx, jn, ARRAY_SIZE(jn));
+ vfs_ChDir(p->conn,p->conn->connectpath);
+
+ DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn, level));
+
+ r_u->ptr0_info = q_u->ptr0_info;
+ r_u->ptr0_total = q_u->ptr0_total;
+ r_u->total = num_jn;
+
+ r_u->info = q_u->info;
+
+ /* Create the return array */
+ switch (level) {
case 1:
- {
- DFS_INFO_1* dfs1;
- dfs1 = TALLOC_ARRAY(ctx, DFS_INFO_1, num_jn);
- if (!dfs1)
+ if ((r_u->info.e.u.info1.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO1, num_jn)) == NULL) {
return WERR_NOMEM;
- init_reply_dfs_info_1(jn, dfs1, num_jn);
- ctr->dfs.info1 = dfs1;
- break;
}
+ r_u->info.e.u.info1.count = num_jn;
+ r_u->info.e.u.info1.ptr0_s = 1;
+ r_u->info.e.u.info1.size_s = num_jn;
+ break;
case 2:
- {
- DFS_INFO_2* dfs2;
- dfs2 = TALLOC_ARRAY(ctx, DFS_INFO_2, num_jn);
- if (!dfs2)
+ if ((r_u->info.e.u.info2.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO2, num_jn)) == NULL) {
return WERR_NOMEM;
- init_reply_dfs_info_2(jn, dfs2, num_jn);
- ctr->dfs.info2 = dfs2;
- break;
}
+ r_u->info.e.u.info2.count = num_jn;
+ r_u->info.e.u.info2.ptr0_s = 1;
+ r_u->info.e.u.info2.size_s = num_jn;
+ break;
case 3:
- {
- DFS_INFO_3* dfs3;
- dfs3 = TALLOC_ARRAY(ctx, DFS_INFO_3, num_jn);
- if (!dfs3)
+ if ((r_u->info.e.u.info3.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO3, num_jn)) == NULL) {
return WERR_NOMEM;
- init_reply_dfs_info_3(ctx, jn, dfs3, num_jn);
- ctr->dfs.info3 = dfs3;
+ }
+ r_u->info.e.u.info3.count = num_jn;
+ r_u->info.e.u.info3.ptr0_s = 1;
+ r_u->info.e.u.info3.size_s = num_jn;
break;
+ case 4:
+ if ((r_u->info.e.u.info4.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO4, num_jn)) == NULL) {
+ return WERR_NOMEM;
}
+ r_u->info.e.u.info4.count = num_jn;
+ r_u->info.e.u.info4.ptr0_s = 1;
+ r_u->info.e.u.info4.size_s = num_jn;
+ break;
default:
return WERR_INVALID_PARAM;
}
- return WERR_OK;
-}
-
-WERROR _dfs_enum(pipes_struct *p, DFS_Q_DFS_ENUM *q_u, DFS_R_DFS_ENUM *r_u)
-{
- uint32 level = q_u->level;
- struct junction_map jn[MAX_MSDFS_JUNCTIONS];
- int num_jn = 0;
-
- num_jn = enum_msdfs_links(p->mem_ctx, jn, ARRAY_SIZE(jn));
- vfs_ChDir(p->conn,p->conn->connectpath);
-
- DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn, level));
- r_u->ptr_buffer = level;
- r_u->level = r_u->level2 = level;
- r_u->ptr_num_entries = r_u->ptr_num_entries2 = 1;
- r_u->num_entries = r_u->num_entries2 = num_jn;
- r_u->reshnd.ptr_hnd = 1;
- r_u->reshnd.handle = num_jn;
-
- r_u->ctr = TALLOC_P(p->mem_ctx, DFS_INFO_CTR);
- if (!r_u->ctr)
- return WERR_NOMEM;
- ZERO_STRUCTP(r_u->ctr);
- r_u->ctr->switch_value = level;
- r_u->ctr->num_entries = num_jn;
- r_u->ctr->ptr_dfs_ctr = 1;
+ for (i = 0; i < num_jn; i++) {
+ switch (level) {
+ case 1:
+ init_reply_dfs_info_1(&jn[i], &r_u->info.e.u.info1.s[i]);
+ break;
+ case 2:
+ init_reply_dfs_info_2(&jn[i], &r_u->info.e.u.info2.s[i]);
+ break;
+ case 3:
+ init_reply_dfs_info_3(p->mem_ctx, &jn[i], &r_u->info.e.u.info3.s[i]);
+ break;
+ default:
+ return WERR_INVALID_PARAM;
+ }
+ }
- r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, r_u->ctr, jn, num_jn);
+ r_u->status = WERR_OK;
return r_u->status;
}
-WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
- DFS_R_DFS_GET_INFO *r_u)
+WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u,
+ NETDFS_R_DFS_GETINFO *r_u)
{
- UNISTR2* uni_path = &q_u->uni_path;
+ UNISTR2* uni_path = &q_u->path;
uint32 level = q_u->level;
int consumedcnt = sizeof(pstring);
pstring path;
+ BOOL ret;
struct junction_map jn;
unistr2_to_ascii(path, uni_path, sizeof(path)-1);
@@ -363,9 +358,130 @@ WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
}
vfs_ChDir(p->conn,p->conn->connectpath);
- r_u->level = level;
- r_u->ptr_ctr = 1;
- r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, &r_u->ctr, &jn, 1);
+ r_u->info.switch_value = level;
+ r_u->info.ptr0 = 1;
+ r_u->status = WERR_OK;
+
+ switch (level) {
+ case 1: ret = init_reply_dfs_info_1(&jn, &r_u->info.u.info1); break;
+ case 2: ret = init_reply_dfs_info_2(&jn, &r_u->info.u.info2); break;
+ case 3: ret = init_reply_dfs_info_3(p->mem_ctx, &jn, &r_u->info.u.info3); break;
+ default:
+ ret = False;
+ break;
+ }
+
+ if (!ret)
+ r_u->status = WERR_INVALID_PARAM;
return r_u->status;
}
+
+WERROR _dfs_SetInfo(pipes_struct *p, NETDFS_Q_DFS_SETINFO *q_u, NETDFS_R_DFS_SETINFO *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Rename(pipes_struct *p, NETDFS_Q_DFS_RENAME *q_u, NETDFS_R_DFS_RENAME *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Move(pipes_struct *p, NETDFS_Q_DFS_MOVE *q_u, NETDFS_R_DFS_MOVE *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_ManagerGetConfigInfo(pipes_struct *p, NETDFS_Q_DFS_MANAGERGETCONFIGINFO *q_u, NETDFS_R_DFS_MANAGERGETCONFIGINFO *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_ManagerSendSiteInfo(pipes_struct *p, NETDFS_Q_DFS_MANAGERSENDSITEINFO *q_u, NETDFS_R_DFS_MANAGERSENDSITEINFO *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_AddFtRoot(pipes_struct *p, NETDFS_Q_DFS_ADDFTROOT *q_u, NETDFS_R_DFS_ADDFTROOT *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_RemoveFtRoot(pipes_struct *p, NETDFS_Q_DFS_REMOVEFTROOT *q_u, NETDFS_R_DFS_REMOVEFTROOT *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_AddStdRoot(pipes_struct *p, NETDFS_Q_DFS_ADDSTDROOT *q_u, NETDFS_R_DFS_ADDSTDROOT *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_RemoveStdRoot(pipes_struct *p, NETDFS_Q_DFS_REMOVESTDROOT *q_u, NETDFS_R_DFS_REMOVESTDROOT *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_ManagerInitialize(pipes_struct *p, NETDFS_Q_DFS_MANAGERINITIALIZE *q_u, NETDFS_R_DFS_MANAGERINITIALIZE *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_AddStdRootForced(pipes_struct *p, NETDFS_Q_DFS_ADDSTDROOTFORCED *q_u, NETDFS_R_DFS_ADDSTDROOTFORCED *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_GetDcAddress(pipes_struct *p, NETDFS_Q_DFS_GETDCADDRESS *q_u, NETDFS_R_DFS_GETDCADDRESS *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_SetDcAddress(pipes_struct *p, NETDFS_Q_DFS_SETDCADDRESS *q_u, NETDFS_R_DFS_SETDCADDRESS *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_FlushFtTable(pipes_struct *p, NETDFS_Q_DFS_FLUSHFTTABLE *q_u, NETDFS_R_DFS_FLUSHFTTABLE *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Add2(pipes_struct *p, NETDFS_Q_DFS_ADD2 *q_u, NETDFS_R_DFS_ADD2 *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Remove2(pipes_struct *p, NETDFS_Q_DFS_REMOVE2 *q_u, NETDFS_R_DFS_REMOVE2 *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_EnumEx(pipes_struct *p, NETDFS_Q_DFS_ENUMEX *q_u, NETDFS_R_DFS_ENUMEX *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_SetInfo2(pipes_struct *p, NETDFS_Q_DFS_SETINFO2 *q_u, NETDFS_R_DFS_SETINFO2 *r_u)
+{
+ /* FIXME: Implement your code here */
+ return WERR_NOT_SUPPORTED;
+}
+
diff --git a/source/rpc_server/srv_eventlog_lib.c b/source/rpc_server/srv_eventlog_lib.c
index ec5edf2f347..acae1c94e9a 100644
--- a/source/rpc_server/srv_eventlog_lib.c
+++ b/source/rpc_server/srv_eventlog_lib.c
@@ -163,7 +163,7 @@ BOOL make_way_for_eventlogs( TDB_CONTEXT * the_tdb, int32 needed,
if ( mem_ctx == NULL )
return False; /* can't allocate memory indicates bigger problems */
/* lock */
- tdb_lock_bystring( the_tdb, EVT_NEXT_RECORD, 1 );
+ tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
/* read */
end_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
start_record = tdb_fetch_int32( the_tdb, EVT_OLDEST_ENTRY );
@@ -489,7 +489,7 @@ int write_eventlog_tdb( TDB_CONTEXT * the_tdb, Eventlog_entry * ee )
/* need to read the record number and insert it into the entry here */
/* lock */
- tdb_lock_bystring( the_tdb, EVT_NEXT_RECORD, 1 );
+ tdb_lock_bystring_with_timeout( the_tdb, EVT_NEXT_RECORD, 1 );
/* read */
next_record = tdb_fetch_int32( the_tdb, EVT_NEXT_RECORD );
@@ -707,16 +707,13 @@ BOOL parse_logentry( char *line, Eventlog_entry * entry, BOOL * eor )
memset( temp, 0, sizeof( temp ) );
strncpy( temp, stop, temp_len );
rpcstr_push( ( void * ) ( entry->data_record.strings +
- entry->data_record.strings_len ),
+ ( entry->data_record.strings_len / 2 ) ),
temp,
sizeof( entry->data_record.strings ) -
- entry->data_record.strings_len, STR_TERMINATE );
- entry->data_record.strings_len += temp_len + 1;
+ ( entry->data_record.strings_len / 2 ), STR_TERMINATE );
+ entry->data_record.strings_len += ( temp_len * 2 ) + 2;
entry->record.num_strings++;
} else if ( 0 == strncmp( start, "DAT", stop - start ) ) {
- /* Now that we're done processing the STR data, adjust the length to account for
- unicode, then proceed with the DAT data. */
- entry->data_record.strings_len *= 2;
/* skip past initial ":" */
stop++;
/* now skip any other leading whitespace */
diff --git a/source/rpc_server/srv_eventlog_nt.c b/source/rpc_server/srv_eventlog_nt.c
index a8b9c66717e..284ee37348e 100644
--- a/source/rpc_server/srv_eventlog_nt.c
+++ b/source/rpc_server/srv_eventlog_nt.c
@@ -146,7 +146,7 @@ static BOOL get_num_records_hook( EVENTLOG_INFO * info )
/* lock the tdb since we have to get 2 records */
- tdb_lock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
+ tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
diff --git a/source/rpc_server/srv_lsa.c b/source/rpc_server/srv_lsa.c
index fc84dbe923b..286266f30de 100644
--- a/source/rpc_server/srv_lsa.c
+++ b/source/rpc_server/srv_lsa.c
@@ -916,6 +916,159 @@ static BOOL api_lsa_delete_object(pipes_struct *p)
return True;
}
+/***************************************************************************
+ api_lsa_lookup_sids2
+ ***************************************************************************/
+
+static BOOL api_lsa_lookup_sids2(pipes_struct *p)
+{
+ LSA_Q_LOOKUP_SIDS2 q_u;
+ LSA_R_LOOKUP_SIDS2 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 info class and policy handle */
+ if(!lsa_io_q_lookup_sids2("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_lookup_sids2: failed to unmarshall LSA_Q_LOOKUP_SIDS2.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_lookup_sids2(p, &q_u, &r_u);
+
+ if(!lsa_io_r_lookup_sids2("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_lookup_sids2: Failed to marshall LSA_R_LOOKUP_SIDS2.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ api_lsa_lookup_sids3
+ ***************************************************************************/
+
+static BOOL api_lsa_lookup_sids3(pipes_struct *p)
+{
+ LSA_Q_LOOKUP_SIDS3 q_u;
+ LSA_R_LOOKUP_SIDS3 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 info class and policy handle */
+ if(!lsa_io_q_lookup_sids3("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_lookup_sids3: failed to unmarshall LSA_Q_LOOKUP_SIDS3.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_lookup_sids3(p, &q_u, &r_u);
+
+ if(!lsa_io_r_lookup_sids3("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_lookup_sids3: Failed to marshall LSA_R_LOOKUP_SIDS3.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ api_lsa_lookup_names2
+ ***************************************************************************/
+
+static BOOL api_lsa_lookup_names2(pipes_struct *p)
+{
+ LSA_Q_LOOKUP_NAMES2 q_u;
+ LSA_R_LOOKUP_NAMES2 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 info class and policy handle */
+ if(!lsa_io_q_lookup_names2("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_lookup_names2: failed to unmarshall LSA_Q_LOOKUP_NAMES2.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_lookup_names2(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_lookup_names2("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_lookup_names2: Failed to marshall LSA_R_LOOKUP_NAMES2.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ api_lsa_lookup_names3
+ ***************************************************************************/
+
+static BOOL api_lsa_lookup_names3(pipes_struct *p)
+{
+ LSA_Q_LOOKUP_NAMES3 q_u;
+ LSA_R_LOOKUP_NAMES3 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 info class and policy handle */
+ if(!lsa_io_q_lookup_names3("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_lookup_names3: failed to unmarshall LSA_Q_LOOKUP_NAMES3.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_lookup_names3(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_lookup_names3("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_lookup_names3: Failed to marshall LSA_R_LOOKUP_NAMES3.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/***************************************************************************
+ api_lsa_lookup_names4
+ ***************************************************************************/
+
+static BOOL api_lsa_lookup_names4(pipes_struct *p)
+{
+ LSA_Q_LOOKUP_NAMES4 q_u;
+ LSA_R_LOOKUP_NAMES4 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 info class and policy handle */
+ if(!lsa_io_q_lookup_names4("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_lookup_names4: failed to unmarshall LSA_Q_LOOKUP_NAMES4.\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_lookup_names4(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_lookup_names4("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_lookup_names4: Failed to marshall LSA_R_LOOKUP_NAMES4.\n"));
+ return False;
+ }
+
+ return True;
+}
+
#if 0 /* AD DC work in ongoing in Samba 4 */
/***************************************************************************
@@ -984,7 +1137,12 @@ static struct api_struct api_lsa_cmds[] =
{ "LSA_CREATETRUSTDOM" , LSA_CREATETRUSTDOM , api_lsa_create_trust_dom },
{ "LSA_CREATSECRET" , LSA_CREATESECRET , api_lsa_create_secret },
{ "LSA_SETSECRET" , LSA_SETSECRET , api_lsa_set_secret },
- { "LSA_DELETEOBJECT" , LSA_DELETEOBJECT , api_lsa_delete_object }
+ { "LSA_DELETEOBJECT" , LSA_DELETEOBJECT , api_lsa_delete_object },
+ { "LSA_LOOKUPSIDS2" , LSA_LOOKUPSIDS2 , api_lsa_lookup_sids2 },
+ { "LSA_LOOKUPNAMES2" , LSA_LOOKUPNAMES2 , api_lsa_lookup_names2 },
+ { "LSA_LOOKUPNAMES3" , LSA_LOOKUPNAMES3 , api_lsa_lookup_names3 },
+ { "LSA_LOOKUPSIDS3" , LSA_LOOKUPSIDS3 , api_lsa_lookup_sids3 },
+ { "LSA_LOOKUPNAMES4" , LSA_LOOKUPNAMES4 , api_lsa_lookup_names4 }
#if 0 /* AD DC work in ongoing in Samba 4 */
/* be careful of the adding of new RPC's. See commentrs below about
ADS DC capabilities */
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index b56ae109141..d5222bbcb98 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -4,11 +4,12 @@
* 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) Jeremy Allison 2001, 2006.
* Copyright (C) Rafal Szczesniak 2002,
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002,
* Copyright (C) Simo Sorce 2003.
* Copyright (C) Gerald (Jerry) Carter 2005.
+ * 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
@@ -61,7 +62,7 @@ static void free_lsa_info(void *ptr)
Init dom_query
***************************************************************************/
-static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_sid)
+static void init_dom_query_3(DOM_QUERY_3 *d_q, const char *dom_name, DOM_SID *dom_sid)
{
d_q->buffer_dom_name = (dom_name != NULL) ? 1 : 0; /* domain buffer pointer */
d_q->buffer_dom_sid = (dom_sid != NULL) ? 1 : 0; /* domain sid pointer */
@@ -93,18 +94,25 @@ static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_si
}
/***************************************************************************
+Init dom_query
+ ***************************************************************************/
+
+static void init_dom_query_5(DOM_QUERY_5 *d_q, const char *dom_name, DOM_SID *dom_sid)
+{
+ init_dom_query_3(d_q, dom_name, dom_sid);
+}
+
+/***************************************************************************
init_dom_ref - adds a domain if it's not already in, returns the index.
***************************************************************************/
-static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
+static int init_dom_ref(DOM_R_REF *ref, const char *dom_name, DOM_SID *dom_sid)
{
int num = 0;
if (dom_name != NULL) {
for (num = 0; num < ref->num_ref_doms_1; num++) {
- fstring domname;
- rpcstr_pull(domname, ref->ref_dom[num].uni_dom_name.buffer, sizeof(domname), -1, 0);
- if (strequal(domname, dom_name))
+ if (sid_equal(dom_sid, &ref->ref_dom[num].ref_dom.sid))
return num;
}
} else {
@@ -121,7 +129,7 @@ static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
ref->max_entries = MAX_REF_DOMAINS;
ref->num_ref_doms_2 = num+1;
- ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0;
+ ref->hdr_ref_dom[num].ptr_dom_sid = 1; /* dom sid cannot be NULL. */
init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, UNI_FLAGS_NONE);
init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, &ref->ref_dom[num].uni_dom_name);
@@ -132,70 +140,162 @@ static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
}
/***************************************************************************
- init_lsa_rid2s
+ lookup_lsa_rids. Must be called as root for lookup_name to work.
***************************************************************************/
-static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
- int num_entries, UNISTR2 *name,
- uint32 *mapped_count, BOOL endian)
+static NTSTATUS lookup_lsa_rids(TALLOC_CTX *mem_ctx,
+ DOM_R_REF *ref,
+ DOM_RID *prid,
+ uint32 num_entries,
+ const UNISTR2 *name,
+ int flags,
+ uint32 *pmapped_count)
{
- int i;
- int total = 0;
- *mapped_count = 0;
+ uint32 mapped_count, i;
SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
- become_root(); /* lookup_name can require root privs */
+ mapped_count = 0;
+ *pmapped_count = 0;
for (i = 0; i < num_entries; i++) {
- BOOL status = False;
DOM_SID sid;
- uint32 rid = 0xffffffff;
- int dom_idx = -1;
- pstring full_name;
- fstring dom_name, user;
- enum SID_NAME_USE name_type = SID_NAME_UNKNOWN;
+ uint32 rid;
+ int dom_idx;
+ char *full_name;
+ const char *domain;
+ enum SID_NAME_USE type = SID_NAME_UNKNOWN;
/* Split name into domain and user component */
- unistr2_to_ascii(full_name, &name[i], sizeof(full_name));
- split_domain_name(full_name, dom_name, user);
+ full_name = rpcstr_pull_unistr2_talloc(mem_ctx, &name[i]);
+ if (full_name == NULL) {
+ DEBUG(0, ("pull_ucs2_talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- /* Lookup name */
+ DEBUG(5, ("lookup_lsa_rids: looking up name %s\n", full_name));
+
+ /* We can ignore the result of lookup_name, it will not touch
+ "type" if it's not successful */
+
+ lookup_name(mem_ctx, full_name, flags, &domain, NULL,
+ &sid, &type);
+
+ switch (type) {
+ case SID_NAME_USER:
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_DOMAIN:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ DEBUG(5, ("init_lsa_rids: %s found\n", full_name));
+ /* Leave these unchanged */
+ break;
+ default:
+ /* Don't hand out anything but the list above */
+ DEBUG(5, ("init_lsa_rids: %s not found\n", full_name));
+ type = SID_NAME_UNKNOWN;
+ break;
+ }
- DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name));
+ rid = 0;
+ dom_idx = -1;
- status = lookup_name(dom_name, user, &sid, &name_type);
+ if (type != SID_NAME_UNKNOWN) {
+ sid_split_rid(&sid, &rid);
+ dom_idx = init_dom_ref(ref, domain, &sid);
+ mapped_count++;
+ }
+
+ init_dom_rid(&prid[i], rid, type, dom_idx);
+ }
- if((name_type == SID_NAME_UNKNOWN) && (lp_server_role() == ROLE_DOMAIN_MEMBER) && (strncmp(dom_name, full_name, strlen(dom_name)) != 0)) {
- DEBUG(5, ("init_lsa_rid2s: domain name not provided and local account not found, using member domain\n"));
- fstrcpy(dom_name, lp_workgroup());
- status = lookup_name(dom_name, user, &sid, &name_type);
+ *pmapped_count = mapped_count;
+ return NT_STATUS_OK;
+}
+
+/***************************************************************************
+ lookup_lsa_sids. Must be called as root for lookup_name to work.
+ ***************************************************************************/
+
+static NTSTATUS lookup_lsa_sids(TALLOC_CTX *mem_ctx,
+ DOM_R_REF *ref,
+ LSA_TRANSLATED_SID3 *trans_sids,
+ uint32 num_entries,
+ const UNISTR2 *name,
+ int flags,
+ uint32 *pmapped_count)
+{
+ uint32 mapped_count, i;
+
+ SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
+
+ mapped_count = 0;
+ *pmapped_count = 0;
+
+ for (i = 0; i < num_entries; i++) {
+ DOM_SID sid;
+ uint32 rid;
+ int dom_idx;
+ char *full_name;
+ const char *domain;
+ enum SID_NAME_USE type = SID_NAME_UNKNOWN;
+
+ /* Split name into domain and user component */
+
+ full_name = rpcstr_pull_unistr2_talloc(mem_ctx, &name[i]);
+ if (full_name == NULL) {
+ DEBUG(0, ("pull_ucs2_talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- if (name_type == SID_NAME_WKN_GRP) {
- /* BUILTIN aliases are still aliases :-) */
- name_type = SID_NAME_ALIAS;
+ DEBUG(5, ("init_lsa_sids: looking up name %s\n", full_name));
+
+ /* We can ignore the result of lookup_name, it will not touch
+ "type" if it's not successful */
+
+ lookup_name(mem_ctx, full_name, flags, &domain, NULL,
+ &sid, &type);
+
+ switch (type) {
+ case SID_NAME_USER:
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_DOMAIN:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ DEBUG(5, ("init_lsa_sids: %s found\n", full_name));
+ /* Leave these unchanged */
+ break;
+ default:
+ /* Don't hand out anything but the list above */
+ DEBUG(5, ("init_lsa_sids: %s not found\n", full_name));
+ type = SID_NAME_UNKNOWN;
+ break;
}
- DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" :
- "not found"));
+ rid = 0;
+ dom_idx = -1;
- if (status && name_type != SID_NAME_UNKNOWN) {
- sid_split_rid(&sid, &rid);
- dom_idx = init_dom_ref(ref, dom_name, &sid);
- (*mapped_count)++;
- } else {
- dom_idx = -1;
- rid = 0;
- name_type = SID_NAME_UNKNOWN;
+ if (type != SID_NAME_UNKNOWN) {
+ DOM_SID domain_sid;
+ sid_copy(&domain_sid, &sid);
+ sid_split_rid(&domain_sid, &rid);
+ dom_idx = init_dom_ref(ref, domain, &domain_sid);
+ mapped_count++;
}
- init_dom_rid2(&rid2[total], rid, name_type, dom_idx);
- total++;
+ /* Initialize the LSA_TRANSLATED_SID3 return. */
+ trans_sids[i].sid_type = type;
+ trans_sids[i].sid2 = TALLOC_P(mem_ctx, DOM_SID2);
+ if (trans_sids[i].sid2 == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ init_dom_sid2(trans_sids[i].sid2, &sid);
+ trans_sids[i].sid_idx = dom_idx;
}
- unbecome_root();
+ *pmapped_count = mapped_count;
+ return NT_STATUS_OK;
}
/***************************************************************************
@@ -204,7 +304,7 @@ static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
DOM_R_REF *ref, uint32 num_entries,
- DOM_RID2 *rid2, uint32 mapped_count)
+ DOM_RID *rid, uint32 mapped_count)
{
r_l->ptr_dom_ref = 1;
r_l->dom_ref = ref;
@@ -212,102 +312,139 @@ static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
r_l->num_entries = num_entries;
r_l->ptr_entries = 1;
r_l->num_entries2 = num_entries;
- r_l->dom_rid = rid2;
+ r_l->dom_rid = rid;
r_l->mapped_count = mapped_count;
}
/***************************************************************************
- Init lsa_trans_names.
+ init_reply_lookup_names2
***************************************************************************/
-static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn,
- int num_entries, DOM_SID2 *sid,
- uint32 *mapped_count)
+static void init_reply_lookup_names2(LSA_R_LOOKUP_NAMES2 *r_l,
+ DOM_R_REF *ref, uint32 num_entries,
+ DOM_RID2 *rid, uint32 mapped_count)
{
- int i;
- int total = 0;
- *mapped_count = 0;
-
- /* Allocate memory for list of names */
-
- if (num_entries > 0) {
- if (!(trn->name = TALLOC_ARRAY(ctx, LSA_TRANS_NAME, num_entries))) {
- DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
- return;
- }
+ r_l->ptr_dom_ref = 1;
+ r_l->dom_ref = ref;
- if (!(trn->uni_name = TALLOC_ARRAY(ctx, UNISTR2, num_entries))) {
- DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
- return;
- }
- }
+ r_l->num_entries = num_entries;
+ r_l->ptr_entries = 1;
+ r_l->num_entries2 = num_entries;
+ r_l->dom_rid = rid;
- become_root(); /* Need root to get to passdb to for local sids */
+ r_l->mapped_count = mapped_count;
+}
- for (i = 0; i < num_entries; i++) {
- BOOL status = False;
- DOM_SID find_sid = sid[i].sid;
- uint32 rid = 0xffffffff;
- int dom_idx = -1;
- fstring name, dom_name;
- enum SID_NAME_USE sid_name_use = (enum SID_NAME_USE)0;
+/***************************************************************************
+ init_reply_lookup_names3
+ ***************************************************************************/
- sid_to_string(name, &find_sid);
- DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", name));
+static void init_reply_lookup_names3(LSA_R_LOOKUP_NAMES3 *r_l,
+ DOM_R_REF *ref, uint32 num_entries,
+ LSA_TRANSLATED_SID3 *trans_sids, uint32 mapped_count)
+{
+ r_l->ptr_dom_ref = 1;
+ r_l->dom_ref = ref;
- /* Lookup sid from winbindd */
+ r_l->num_entries = num_entries;
+ r_l->ptr_entries = 1;
+ r_l->num_entries2 = num_entries;
+ r_l->trans_sids = trans_sids;
- status = lookup_sid(&find_sid, dom_name, name, &sid_name_use);
+ r_l->mapped_count = mapped_count;
+}
- DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" :
- "not found"));
+/***************************************************************************
+ init_reply_lookup_names4
+ ***************************************************************************/
- if (!status) {
- sid_name_use = SID_NAME_UNKNOWN;
- memset(dom_name, '\0', sizeof(dom_name));
- sid_to_string(name, &find_sid);
- dom_idx = -1;
+static void init_reply_lookup_names4(LSA_R_LOOKUP_NAMES4 *r_l,
+ DOM_R_REF *ref, uint32 num_entries,
+ LSA_TRANSLATED_SID3 *trans_sids, uint32 mapped_count)
+{
+ r_l->ptr_dom_ref = 1;
+ r_l->dom_ref = ref;
- DEBUG(10,("init_lsa_trans_names: added unknown user '%s' to "
- "referenced list.\n", name ));
- } else {
- (*mapped_count)++;
- /* Store domain sid in ref array */
- if (find_sid.num_auths == 5) {
- sid_split_rid(&find_sid, &rid);
- }
- dom_idx = init_dom_ref(ref, dom_name, &find_sid);
+ r_l->num_entries = num_entries;
+ r_l->ptr_entries = 1;
+ r_l->num_entries2 = num_entries;
+ r_l->trans_sids = trans_sids;
- DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' (%d) to referenced list.\n",
- sid_type_lookup(sid_name_use), dom_name, name, sid_name_use ));
+ r_l->mapped_count = mapped_count;
+}
- }
+/***************************************************************************
+ Init_reply_lookup_sids.
+ ***************************************************************************/
- init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
- sid_name_use, name, dom_idx);
- total++;
- }
+static void init_reply_lookup_sids2(LSA_R_LOOKUP_SIDS2 *r_l,
+ DOM_R_REF *ref,
+ LSA_TRANS_NAME_ENUM2 *names,
+ uint32 mapped_count)
+{
+ r_l->ptr_dom_ref = ref ? 1 : 0;
+ r_l->dom_ref = ref;
+ r_l->names = names;
+ r_l->mapped_count = mapped_count;
+}
- unbecome_root();
+/***************************************************************************
+ Init_reply_lookup_sids.
+ ***************************************************************************/
- trn->num_entries = total;
- trn->ptr_trans_names = 1;
- trn->num_entries2 = total;
+static void init_reply_lookup_sids3(LSA_R_LOOKUP_SIDS3 *r_l,
+ DOM_R_REF *ref,
+ LSA_TRANS_NAME_ENUM2 *names,
+ uint32 mapped_count)
+{
+ r_l->ptr_dom_ref = ref ? 1 : 0;
+ r_l->dom_ref = ref;
+ r_l->names = names;
+ r_l->mapped_count = mapped_count;
}
/***************************************************************************
Init_reply_lookup_sids.
***************************************************************************/
-static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
- DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
- uint32 mapped_count)
+static NTSTATUS init_reply_lookup_sids(TALLOC_CTX *mem_ctx,
+ LSA_R_LOOKUP_SIDS *r_l,
+ DOM_R_REF *ref,
+ LSA_TRANS_NAME_ENUM2 *names,
+ uint32 mapped_count)
{
- r_l->ptr_dom_ref = 1;
+ LSA_TRANS_NAME_ENUM *oldnames = TALLOC_ZERO_P(mem_ctx, LSA_TRANS_NAME_ENUM);
+
+ if (!oldnames) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ oldnames->num_entries = names->num_entries;
+ oldnames->ptr_trans_names = names->ptr_trans_names;
+ oldnames->num_entries2 = names->num_entries2;
+ oldnames->uni_name = names->uni_name;
+
+ if (names->num_entries) {
+ int i;
+
+ oldnames->name = TALLOC_ARRAY(oldnames, LSA_TRANS_NAME, names->num_entries);
+
+ if (!oldnames->name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i = 0; i < names->num_entries; i++) {
+ oldnames->name[i].sid_name_use = names->name[i].sid_name_use;
+ oldnames->name[i].hdr_name = names->name[i].hdr_name;
+ oldnames->name[i].domain_idx = names->name[i].domain_idx;
+ }
+ }
+
+ r_l->ptr_dom_ref = ref ? 1 : 0;
r_l->dom_ref = ref;
- r_l->names = names;
+ r_l->names = oldnames;
r_l->mapped_count = mapped_count;
+ return NT_STATUS_OK;
}
static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *sd_size)
@@ -485,10 +622,12 @@ NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *
ufff, done :) mimir
***************************************************************************/
-NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
+NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u,
+ LSA_R_ENUM_TRUST_DOM *r_u)
{
struct lsa_info *info;
- uint32 enum_context = q_u->enum_context;
+ uint32 next_idx;
+ struct trustdom_info **domains;
/*
* preferred length is set to 5 as a "our" preferred length
@@ -496,10 +635,11 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
* update (20.08.2002): it's not preferred length, but preferred size!
* it needs further investigation how to optimally choose this value
*/
- uint32 max_num_domains = q_u->preferred_len < 5 ? q_u->preferred_len : 10;
- TRUSTDOM **trust_doms;
+ uint32 max_num_domains =
+ q_u->preferred_len < 5 ? q_u->preferred_len : 10;
uint32 num_domains;
NTSTATUS nt_status;
+ uint32 num_thistime;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
return NT_STATUS_INVALID_HANDLE;
@@ -508,19 +648,34 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- nt_status = secrets_get_trusted_domains(p->mem_ctx, (int *)&enum_context, max_num_domains, (int *)&num_domains, &trust_doms);
+ nt_status = secrets_trusted_domains(p->mem_ctx, &num_domains,
+ &domains);
- if (!NT_STATUS_IS_OK(nt_status) &&
- !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES) &&
- !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
+ if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
- } else {
- r_u->status = nt_status;
}
+ if (q_u->enum_context < num_domains) {
+ num_thistime = MIN(num_domains, max_num_domains);
+
+ r_u->status = STATUS_MORE_ENTRIES;
+
+ if (q_u->enum_context + num_thistime > num_domains) {
+ num_thistime = num_domains - q_u->enum_context;
+ r_u->status = NT_STATUS_OK;
+ }
+
+ next_idx = q_u->enum_context + num_thistime;
+ } else {
+ num_thistime = 0;
+ next_idx = 0xffffffff;
+ r_u->status = NT_STATUS_NO_MORE_ENTRIES;
+ }
+
/* set up the lsa_enum_trust_dom response */
- init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, num_domains, trust_doms);
+ init_r_enum_trust_dom(p->mem_ctx, r_u, next_idx,
+ num_thistime, domains+q_u->enum_context);
return r_u->status;
}
@@ -532,7 +687,7 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INFO *r_u)
{
struct lsa_info *handle;
- LSA_INFO_UNION *info = &r_u->dom;
+ LSA_INFO_CTR *ctr = &r_u->ctr;
DOM_SID domain_sid;
const char *name;
DOM_SID *sid = NULL;
@@ -545,19 +700,31 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
switch (q_u->info_class) {
case 0x02:
{
- unsigned int i;
+
+ uint32 policy_def = LSA_AUDIT_POLICY_ALL;
+
/* check if the user have enough rights */
- if (!(handle->access & POLICY_VIEW_AUDIT_INFORMATION))
+ if (!(handle->access & POLICY_VIEW_AUDIT_INFORMATION)) {
+ DEBUG(10,("_lsa_query_info: insufficient access rights\n"));
return NT_STATUS_ACCESS_DENIED;
+ }
/* fake info: We audit everything. ;) */
- info->id2.auditing_enabled = 1;
- info->id2.count1 = 7;
- info->id2.count2 = 7;
- if ((info->id2.auditsettings = TALLOC_ARRAY(p->mem_ctx,uint32, 7)) == NULL)
+ ctr->info.id2.ptr = 1;
+ ctr->info.id2.auditing_enabled = True;
+ ctr->info.id2.count1 = ctr->info.id2.count2 = LSA_AUDIT_NUM_CATEGORIES;
+
+ if ((ctr->info.id2.auditsettings = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, LSA_AUDIT_NUM_CATEGORIES)) == NULL)
return NT_STATUS_NO_MEMORY;
- for (i = 0; i < 7; i++)
- info->id2.auditsettings[i] = 3;
+
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_ACCOUNT_MANAGEMENT] = policy_def;
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_FILE_AND_OBJECT_ACCESS] = policy_def;
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_LOGON] = policy_def;
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_PROCCESS_TRACKING] = policy_def;
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_SECURITY_POLICY_CHANGES] = policy_def;
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_SYSTEM] = policy_def;
+ ctr->info.id2.auditsettings[LSA_AUDIT_CATEGORY_USE_OF_USER_RIGHTS] = policy_def;
+
break;
}
case 0x03:
@@ -587,7 +754,7 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
default:
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
- init_dom_query(&r_u->dom.id3, name, sid);
+ init_dom_query_3(&r_u->ctr.info.id3, name, sid);
break;
case 0x05:
/* check if the user have enough rights */
@@ -597,7 +764,7 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
/* Request PolicyAccountDomainInformation. */
name = get_global_sam_name();
sid = get_global_sam_sid();
- init_dom_query(&r_u->dom.id5, name, sid);
+ init_dom_query_5(&r_u->ctr.info.id5, name, sid);
break;
case 0x06:
/* check if the user have enough rights */
@@ -610,14 +777,14 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
* only a BDC is a backup controller
* of the domain, it controls.
*/
- info->id6.server_role = 2;
+ ctr->info.id6.server_role = 2;
break;
default:
/*
* any other role is a primary
* of the domain, it controls.
*/
- info->id6.server_role = 3;
+ ctr->info.id6.server_role = 3;
break;
}
break;
@@ -628,34 +795,280 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
}
if (NT_STATUS_IS_OK(r_u->status)) {
- r_u->undoc_buffer = 0x22000000; /* bizarre */
- r_u->info_class = q_u->info_class;
+ r_u->dom_ptr = 0x22000000; /* bizarre */
+ ctr->info_class = q_u->info_class;
}
return r_u->status;
}
/***************************************************************************
+ _lsa_lookup_sids_internal
+ ***************************************************************************/
+
+static NTSTATUS _lsa_lookup_sids_internal(pipes_struct *p,
+ uint16 level, /* input */
+ int num_sids, /* input */
+ const DOM_SID2 *sid, /* input */
+ DOM_R_REF **pp_ref, /* output */
+ LSA_TRANS_NAME_ENUM2 **pp_names, /* output */
+ uint32 *pp_mapped_count)
+{
+ NTSTATUS status;
+ int i;
+ const DOM_SID **sids = NULL;
+ LSA_TRANS_NAME_ENUM2 *names = NULL;
+ DOM_R_REF *ref = NULL;
+ uint32 mapped_count = 0;
+ struct lsa_dom_info *dom_infos = NULL;
+ struct lsa_name_info *name_infos = NULL;
+
+ *pp_mapped_count = 0;
+ *pp_ref = NULL;
+ *pp_names = NULL;
+
+ names = TALLOC_ZERO_P(p->mem_ctx, LSA_TRANS_NAME_ENUM2);
+ sids = TALLOC_ARRAY(p->mem_ctx, const DOM_SID *, num_sids);
+ ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
+
+ if (sids == NULL || names == NULL || ref == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num_sids; i++) {
+ sids[i] = &sid[i].sid;
+ }
+
+ status = lookup_sids(p->mem_ctx, num_sids, sids, level,
+ &dom_infos, &name_infos);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (num_sids > 0) {
+ names->name = TALLOC_ARRAY(names, LSA_TRANS_NAME2, num_sids);
+ names->uni_name = TALLOC_ARRAY(names, UNISTR2, num_sids);
+ if ((names->name == NULL) || (names->uni_name == NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ for (i=0; i<MAX_REF_DOMAINS; i++) {
+
+ if (!dom_infos[i].valid) {
+ break;
+ }
+
+ if (init_dom_ref(ref, dom_infos[i].name,
+ &dom_infos[i].sid) != i) {
+ DEBUG(0, ("Domain %s mentioned twice??\n",
+ dom_infos[i].name));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ }
+
+ for (i=0; i<num_sids; i++) {
+ struct lsa_name_info *name = &name_infos[i];
+
+ if (name->type == SID_NAME_UNKNOWN) {
+ name->dom_idx = -1;
+ name->name = talloc_asprintf(p->mem_ctx, "%8.8x",
+ name->rid);
+ if (name->name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ mapped_count += 1;
+ }
+ init_lsa_trans_name2(&names->name[i], &names->uni_name[i],
+ name->type, name->name, name->dom_idx);
+ }
+
+ names->num_entries = num_sids;
+ names->ptr_trans_names = 1;
+ names->num_entries2 = num_sids;
+
+ status = NT_STATUS_NONE_MAPPED;
+ if (mapped_count > 0) {
+ status = (mapped_count < num_sids) ?
+ STATUS_SOME_UNMAPPED : NT_STATUS_OK;
+ }
+
+ DEBUG(10, ("num_sids %d, mapped_count %d, status %s\n",
+ num_sids, mapped_count, nt_errstr(status)));
+
+ *pp_mapped_count = mapped_count;
+ *pp_ref = ref;
+ *pp_names = names;
+
+ return status;
+}
+
+/***************************************************************************
_lsa_lookup_sids
***************************************************************************/
-NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_SIDS *r_u)
+NTSTATUS _lsa_lookup_sids(pipes_struct *p,
+ LSA_Q_LOOKUP_SIDS *q_u,
+ LSA_R_LOOKUP_SIDS *r_u)
+{
+ struct lsa_info *handle;
+ int num_sids = q_u->sids.num_entries;
+ uint32 mapped_count = 0;
+ DOM_R_REF *ref = NULL;
+ LSA_TRANS_NAME_ENUM2 *names = NULL;
+ NTSTATUS status;
+
+ if ((q_u->level < 1) || (q_u->level > 6)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* check if the user has enough rights */
+ if (!(handle->access & POLICY_LOOKUP_NAMES)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (num_sids > MAX_LOOKUP_SIDS) {
+ DEBUG(5,("_lsa_lookup_sids: limit of %d exceeded, requested %d\n",
+ MAX_LOOKUP_SIDS, num_sids));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ r_u->status = _lsa_lookup_sids_internal(p,
+ q_u->level,
+ num_sids,
+ q_u->sids.sid,
+ &ref,
+ &names,
+ &mapped_count);
+
+ /* Convert from LSA_TRANS_NAME_ENUM2 to LSA_TRANS_NAME_ENUM */
+
+ status = init_reply_lookup_sids(p->mem_ctx, r_u, ref, names, mapped_count);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return r_u->status;
+}
+
+/***************************************************************************
+ _lsa_lookup_sids2
+ ***************************************************************************/
+
+NTSTATUS _lsa_lookup_sids2(pipes_struct *p,
+ LSA_Q_LOOKUP_SIDS2 *q_u,
+ LSA_R_LOOKUP_SIDS2 *r_u)
{
struct lsa_info *handle;
- DOM_SID2 *sid = q_u->sids.sid;
- int num_entries = q_u->sids.num_entries;
+ int num_sids = q_u->sids.num_entries;
+ uint32 mapped_count = 0;
DOM_R_REF *ref = NULL;
- LSA_TRANS_NAME_ENUM *names = NULL;
+ LSA_TRANS_NAME_ENUM2 *names = NULL;
+
+ if ((q_u->level < 1) || (q_u->level > 6)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* check if the user have enough rights */
+ if (!(handle->access & POLICY_LOOKUP_NAMES)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (num_sids > MAX_LOOKUP_SIDS) {
+ DEBUG(5,("_lsa_lookup_sids2: limit of %d exceeded, requested %d\n",
+ MAX_LOOKUP_SIDS, num_sids));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ r_u->status = _lsa_lookup_sids_internal(p,
+ q_u->level,
+ num_sids,
+ q_u->sids.sid,
+ &ref,
+ &names,
+ &mapped_count);
+
+ init_reply_lookup_sids2(r_u, ref, names, mapped_count);
+ return r_u->status;
+}
+
+/***************************************************************************
+ _lsa_lookup_sida3
+ ***************************************************************************/
+
+NTSTATUS _lsa_lookup_sids3(pipes_struct *p,
+ LSA_Q_LOOKUP_SIDS3 *q_u,
+ LSA_R_LOOKUP_SIDS3 *r_u)
+{
+ int num_sids = q_u->sids.num_entries;
+ uint32 mapped_count = 0;
+ DOM_R_REF *ref = NULL;
+ LSA_TRANS_NAME_ENUM2 *names = NULL;
+
+ if ((q_u->level < 1) || (q_u->level > 6)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* No policy handle on this call. Restrict to crypto connections. */
+ if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
+ DEBUG(0,("_lsa_lookup_sids3: client %s not using schannel for netlogon\n",
+ get_remote_machine_name() ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (num_sids > MAX_LOOKUP_SIDS) {
+ DEBUG(5,("_lsa_lookup_sids3: limit of %d exceeded, requested %d\n",
+ MAX_LOOKUP_SIDS, num_sids));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ r_u->status = _lsa_lookup_sids_internal(p,
+ q_u->level,
+ num_sids,
+ q_u->sids.sid,
+ &ref,
+ &names,
+ &mapped_count);
+
+ init_reply_lookup_sids3(r_u, ref, names, mapped_count);
+ return r_u->status;
+}
+
+/***************************************************************************
+lsa_reply_lookup_names
+ ***************************************************************************/
+
+NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP_NAMES *r_u)
+{
+ struct lsa_info *handle;
+ UNISTR2 *names = q_u->uni_name;
+ uint32 num_entries = q_u->num_entries;
+ DOM_R_REF *ref;
+ DOM_RID *rids;
uint32 mapped_count = 0;
+ int flags = 0;
if (num_entries > MAX_LOOKUP_SIDS) {
- num_entries = 0;
- DEBUG(5,("_lsa_lookup_sids: limit of %d exceeded, truncating SID lookup list to %d\n", MAX_LOOKUP_SIDS, num_entries));
- r_u->status = NT_STATUS_NONE_MAPPED;
+ num_entries = MAX_LOOKUP_SIDS;
+ DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
+ }
+
+ /* Probably the lookup_level is some sort of bitmask. */
+ if (q_u->lookup_level == 1) {
+ flags = LOOKUP_NAME_ALL;
}
ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
- names = TALLOC_ZERO_P(p->mem_ctx, LSA_TRANS_NAME_ENUM);
+ rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID, num_entries);
if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
r_u->status = NT_STATUS_INVALID_HANDLE;
@@ -667,44 +1080,58 @@ NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_
r_u->status = NT_STATUS_ACCESS_DENIED;
goto done;
}
- if (!ref || !names)
+
+ if (!ref || !rids)
return NT_STATUS_NO_MEMORY;
+ /* set up the LSA Lookup RIDs response */
+ become_root(); /* lookup_name can require root privs */
+ r_u->status = lookup_lsa_rids(p->mem_ctx, ref, rids, num_entries,
+ names, flags, &mapped_count);
+ unbecome_root();
+
done:
- /* set up the LSA Lookup SIDs response */
- init_lsa_trans_names(p->mem_ctx, ref, names, num_entries, sid, &mapped_count);
- if (NT_STATUS_IS_OK(r_u->status)) {
+ if (NT_STATUS_IS_OK(r_u->status) && (num_entries != 0) ) {
if (mapped_count == 0)
r_u->status = NT_STATUS_NONE_MAPPED;
else if (mapped_count != num_entries)
r_u->status = STATUS_SOME_UNMAPPED;
}
- init_reply_lookup_sids(r_u, ref, names, mapped_count);
+ init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
return r_u->status;
}
/***************************************************************************
-lsa_reply_lookup_names
+lsa_reply_lookup_names2
***************************************************************************/
-NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP_NAMES *r_u)
+NTSTATUS _lsa_lookup_names2(pipes_struct *p, LSA_Q_LOOKUP_NAMES2 *q_u, LSA_R_LOOKUP_NAMES2 *r_u)
{
struct lsa_info *handle;
UNISTR2 *names = q_u->uni_name;
- int num_entries = q_u->num_entries;
+ uint32 num_entries = q_u->num_entries;
DOM_R_REF *ref;
- DOM_RID2 *rids;
+ DOM_RID *rids;
+ DOM_RID2 *rids2;
+ int i;
uint32 mapped_count = 0;
+ int flags = 0;
if (num_entries > MAX_LOOKUP_SIDS) {
num_entries = MAX_LOOKUP_SIDS;
- DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
+ DEBUG(5,("_lsa_lookup_names2: truncating name lookup list to %d\n", num_entries));
}
+ /* Probably the lookup_level is some sort of bitmask. */
+ if (q_u->lookup_level == 1) {
+ flags = LOOKUP_NAME_ALL;
+ }
+
ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
- rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID2, num_entries);
+ rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID, num_entries);
+ rids2 = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID2, num_entries);
if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
r_u->status = NT_STATUS_INVALID_HANDLE;
@@ -717,21 +1144,152 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP
goto done;
}
- if (!ref || !rids)
+ if (!ref || !rids || !rids2) {
return NT_STATUS_NO_MEMORY;
+ }
+
+ /* set up the LSA Lookup RIDs response */
+ become_root(); /* lookup_name can require root privs */
+ r_u->status = lookup_lsa_rids(p->mem_ctx, ref, rids, num_entries,
+ names, flags, &mapped_count);
+ unbecome_root();
done:
- /* set up the LSA Lookup RIDs response */
- init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian);
if (NT_STATUS_IS_OK(r_u->status)) {
- if (mapped_count == 0)
+ if (mapped_count == 0) {
r_u->status = NT_STATUS_NONE_MAPPED;
- else if (mapped_count != num_entries)
+ } else if (mapped_count != num_entries) {
r_u->status = STATUS_SOME_UNMAPPED;
+ }
}
- init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
+ /* Convert the rids array to rids2. */
+ for (i = 0; i < num_entries; i++) {
+ rids2[i].type = rids[i].type;
+ rids2[i].rid = rids[i].rid;
+ rids2[i].rid_idx = rids[i].rid_idx;
+ rids2[i].unknown = 0;
+ }
+
+ init_reply_lookup_names2(r_u, ref, num_entries, rids2, mapped_count);
+ return r_u->status;
+}
+
+/***************************************************************************
+lsa_reply_lookup_names3.
+ ***************************************************************************/
+
+NTSTATUS _lsa_lookup_names3(pipes_struct *p, LSA_Q_LOOKUP_NAMES3 *q_u, LSA_R_LOOKUP_NAMES3 *r_u)
+{
+ struct lsa_info *handle;
+ UNISTR2 *names = q_u->uni_name;
+ uint32 num_entries = q_u->num_entries;
+ DOM_R_REF *ref = NULL;
+ LSA_TRANSLATED_SID3 *trans_sids = NULL;
+ uint32 mapped_count = 0;
+ int flags = 0;
+
+ if (num_entries > MAX_LOOKUP_SIDS) {
+ num_entries = MAX_LOOKUP_SIDS;
+ DEBUG(5,("_lsa_lookup_names3: truncating name lookup list to %d\n", num_entries));
+ }
+
+ /* Probably the lookup_level is some sort of bitmask. */
+ if (q_u->lookup_level == 1) {
+ flags = LOOKUP_NAME_ALL;
+ }
+
+ ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
+ trans_sids = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_TRANSLATED_SID3, num_entries);
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
+ r_u->status = NT_STATUS_INVALID_HANDLE;
+ goto done;
+ }
+
+ /* check if the user have enough rights */
+ if (!(handle->access & POLICY_LOOKUP_NAMES)) {
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
+ if (!ref || !trans_sids) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* set up the LSA Lookup SIDs response */
+ become_root(); /* lookup_name can require root privs */
+ r_u->status = lookup_lsa_sids(p->mem_ctx, ref, trans_sids, num_entries,
+ names, flags, &mapped_count);
+ unbecome_root();
+
+done:
+
+ if (NT_STATUS_IS_OK(r_u->status)) {
+ if (mapped_count == 0) {
+ r_u->status = NT_STATUS_NONE_MAPPED;
+ } else if (mapped_count != num_entries) {
+ r_u->status = STATUS_SOME_UNMAPPED;
+ }
+ }
+
+ init_reply_lookup_names3(r_u, ref, num_entries, trans_sids, mapped_count);
+ return r_u->status;
+}
+
+/***************************************************************************
+lsa_reply_lookup_names4.
+ ***************************************************************************/
+
+NTSTATUS _lsa_lookup_names4(pipes_struct *p, LSA_Q_LOOKUP_NAMES4 *q_u, LSA_R_LOOKUP_NAMES4 *r_u)
+{
+ UNISTR2 *names = q_u->uni_name;
+ uint32 num_entries = q_u->num_entries;
+ DOM_R_REF *ref = NULL;
+ LSA_TRANSLATED_SID3 *trans_sids = NULL;
+ uint32 mapped_count = 0;
+ int flags = 0;
+
+ if (num_entries > MAX_LOOKUP_SIDS) {
+ num_entries = MAX_LOOKUP_SIDS;
+ DEBUG(5,("_lsa_lookup_names4: truncating name lookup list to %d\n", num_entries));
+ }
+
+ /* Probably the lookup_level is some sort of bitmask. */
+ if (q_u->lookup_level == 1) {
+ flags = LOOKUP_NAME_ALL;
+ }
+
+ /* No policy handle on this call. Restrict to crypto connections. */
+ if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
+ DEBUG(0,("_lsa_lookup_names4: client %s not using schannel for netlogon\n",
+ get_remote_machine_name() ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
+ trans_sids = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_TRANSLATED_SID3, num_entries);
+
+ if (!ref || !trans_sids) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* set up the LSA Lookup SIDs response */
+ become_root(); /* lookup_name can require root privs */
+ r_u->status = lookup_lsa_sids(p->mem_ctx, ref, trans_sids, num_entries,
+ names, flags, &mapped_count);
+ unbecome_root();
+
+ if (NT_STATUS_IS_OK(r_u->status)) {
+ if (mapped_count == 0) {
+ r_u->status = NT_STATUS_NONE_MAPPED;
+ } else if (mapped_count != num_entries) {
+ r_u->status = STATUS_SOME_UNMAPPED;
+ }
+ }
+
+ init_reply_lookup_names4(r_u, ref, num_entries, trans_sids, mapped_count);
return r_u->status;
}
@@ -741,8 +1299,9 @@ done:
NTSTATUS _lsa_close(pipes_struct *p, LSA_Q_CLOSE *q_u, LSA_R_CLOSE *r_u)
{
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->pol, NULL)) {
return NT_STATUS_INVALID_HANDLE;
+ }
close_policy_hnd(p, &q_u->pol);
return NT_STATUS_OK;
@@ -1109,15 +1668,13 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS
NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
{
struct lsa_info *info=NULL;
- fstring name, dom_name;
- enum SID_NAME_USE type;
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!lookup_sid(&info->sid, dom_name, name, &type))
+ if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL))
return NT_STATUS_ACCESS_DENIED;
/*
@@ -1157,10 +1714,7 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA
if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
- if(!pdb_update_group_mapping_entry(&map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- return r_u->status;
+ return pdb_update_group_mapping_entry(&map);
}
/***************************************************************************
@@ -1182,7 +1736,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u
account_pol.tdb was already opened as root, this is all we have */
get_current_user( &user, p );
- if ( user.uid != sec_initial_uid()
+ if ( user.ut.uid != sec_initial_uid()
&& !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
{
return NT_STATUS_ACCESS_DENIED;
@@ -1223,7 +1777,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP
account_pol.tdb was already opened as root, this is all we have */
get_current_user( &user, p );
- if ( user.uid != sec_initial_uid()
+ if ( user.ut.uid != sec_initial_uid()
&& !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
{
return NT_STATUS_ACCESS_DENIED;
@@ -1385,7 +1939,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R
account_pol.tdb was already opened as root, this is all we have */
get_current_user( &user, p );
- if ( user.uid != sec_initial_uid()
+ if ( user.ut.uid != sec_initial_uid()
&& !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
{
return NT_STATUS_ACCESS_DENIED;
@@ -1443,7 +1997,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u,
account_pol.tdb was already opened as root, this is all we have */
get_current_user( &user, p );
- if ( user.uid != sec_initial_uid()
+ if ( user.ut.uid != sec_initial_uid()
&& !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
{
return NT_STATUS_ACCESS_DENIED;
@@ -1557,4 +2111,3 @@ NTSTATUS _lsa_lookup_priv_value(pipes_struct *p, LSA_Q_LOOKUP_PRIV_VALUE *q_u, L
return NT_STATUS_OK;
}
-
diff --git a/source/rpc_server/srv_netlog.c b/source/rpc_server/srv_netlog.c
index a45a7eebf6a..78ffb2e9f1a 100644
--- a/source/rpc_server/srv_netlog.c
+++ b/source/rpc_server/srv_netlog.c
@@ -197,10 +197,10 @@ static BOOL api_net_sam_logon(pipes_struct *p)
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!net_io_q_sam_logon("", &q_u, data, 0)) {
- DEBUG(0, ("api_net_sam_logon: Failed to unmarshall NET_Q_SAM_LOGON.\n"));
- return False;
- }
+ if(!net_io_q_sam_logon("", &q_u, data, 0)) {
+ DEBUG(0, ("api_net_sam_logon: Failed to unmarshall NET_Q_SAM_LOGON.\n"));
+ return False;
+ }
r_u.status = _net_sam_logon(p, &q_u, &r_u);
@@ -210,7 +210,7 @@ static BOOL api_net_sam_logon(pipes_struct *p)
return False;
}
- return True;
+ return True;
}
/*************************************************************************
@@ -307,6 +307,37 @@ static BOOL api_net_logon_ctrl(pipes_struct *p)
}
/*************************************************************************
+ api_net_sam_logon_ex:
+ *************************************************************************/
+
+static BOOL api_net_sam_logon_ex(pipes_struct *p)
+{
+ NET_Q_SAM_LOGON_EX q_u;
+ NET_R_SAM_LOGON_EX r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!net_io_q_sam_logon_ex("", &q_u, data, 0)) {
+ DEBUG(0, ("api_net_sam_logon_ex: Failed to unmarshall NET_Q_SAM_LOGON_EX.\n"));
+ return False;
+ }
+
+ r_u.status = _net_sam_logon_ex(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!net_io_r_sam_logon_ex("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_net_sam_logon_ex: Failed to marshall NET_R_SAM_LOGON_EX.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+/*************************************************************************
api_ds_enum_dom_trusts:
*************************************************************************/
@@ -356,6 +387,7 @@ static struct api_struct api_net_cmds [] =
{ "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 },
{ "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
{ "NET_LOGON_CTRL" , NET_LOGON_CTRL , api_net_logon_ctrl },
+ { "NET_SAMLOGON_EX" , NET_SAMLOGON_EX , api_net_sam_logon_ex },
#if 0 /* JERRY */
{ "DS_ENUM_DOM_TRUSTS", DS_ENUM_DOM_TRUSTS, api_ds_enum_dom_trusts }
#endif /* JERRY */
diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c
index 643921f5963..1a7ab4ef533 100644
--- a/source/rpc_server/srv_netlog_nt.c
+++ b/source/rpc_server/srv_netlog_nt.c
@@ -204,9 +204,9 @@ static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
gets a machine password entry. checks access rights of the host.
******************************************************************/
-static BOOL get_md4pw(char *md4pw, char *mach_acct)
+static NTSTATUS get_md4pw(char *md4pw, char *mach_acct, uint16 sec_chan_type)
{
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
const uint8 *pass;
BOOL ret;
uint32 acct_ctrl;
@@ -229,35 +229,79 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
}
#endif /* 0 */
- if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
- return False;
+ if ( !(sampass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
/* JRA. This is ok as it is only used for generating the challenge. */
become_root();
- ret=pdb_getsampwnam(sampass, mach_acct);
+ ret = pdb_getsampwnam(sampass, mach_acct);
unbecome_root();
- if (ret==False) {
+ if (ret == False) {
DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
- pdb_free_sam(&sampass);
- return False;
+ TALLOC_FREE(sampass);
+ return NT_STATUS_ACCESS_DENIED;
}
acct_ctrl = pdb_get_acct_ctrl(sampass);
- if (!(acct_ctrl & ACB_DISABLED) &&
- ((acct_ctrl & ACB_DOMTRUST) ||
- (acct_ctrl & ACB_WSTRUST) ||
- (acct_ctrl & ACB_SVRTRUST)) &&
- ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
- memcpy(md4pw, pass, 16);
- dump_data(5, md4pw, 16);
- pdb_free_sam(&sampass);
- return True;
+ if (acct_ctrl & ACB_DISABLED) {
+ DEBUG(0,("get_md4pw: Workstation %s: account is disabled\n", mach_acct));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_ACCOUNT_DISABLED;
+ }
+
+ if (!(acct_ctrl & ACB_SVRTRUST) &&
+ !(acct_ctrl & ACB_WSTRUST) &&
+ !(acct_ctrl & ACB_DOMTRUST))
+ {
+ DEBUG(0,("get_md4pw: Workstation %s: account is not a trust account\n", mach_acct));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+ }
+
+ switch (sec_chan_type) {
+ case SEC_CHAN_BDC:
+ if (!(acct_ctrl & ACB_SVRTRUST)) {
+ DEBUG(0,("get_md4pw: Workstation %s: BDC secure channel requested "
+ "but not a server trust account\n", mach_acct));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+ }
+ break;
+ case SEC_CHAN_WKSTA:
+ if (!(acct_ctrl & ACB_WSTRUST)) {
+ DEBUG(0,("get_md4pw: Workstation %s: WORKSTATION secure channel requested "
+ "but not a workstation trust account\n", mach_acct));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+ }
+ break;
+ case SEC_CHAN_DOMAIN:
+ if (!(acct_ctrl & ACB_DOMTRUST)) {
+ DEBUG(0,("get_md4pw: Workstation %s: DOMAIN secure channel requested "
+ "but not a interdomain trust account\n", mach_acct));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
+ }
+ break;
+ default:
+ break;
}
+
+ if ((pass = pdb_get_nt_passwd(sampass)) == NULL) {
+ DEBUG(0,("get_md4pw: Workstation %s: account does not have a password\n", mach_acct));
+ TALLOC_FREE(sampass);
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ memcpy(md4pw, pass, 16);
+ dump_data(5, md4pw, 16);
+
+ TALLOC_FREE(sampass);
+
+ return NT_STATUS_OK;
- DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
- pdb_free_sam(&sampass);
- return False;
}
@@ -312,6 +356,7 @@ static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS statu
NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
{
+ NTSTATUS status;
fstring mach_acct;
fstring remote_machine;
DOM_CHAL srv_chal_out;
@@ -325,19 +370,22 @@ NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
- if (!get_md4pw((char *)p->dc->mach_pw, mach_acct)) {
+ status = get_md4pw((char *)p->dc->mach_pw, mach_acct, q_u->clnt_id.sec_chan);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("_net_auth: creds_server_check failed. Failed to "
- "get pasword for machine account %s "
- "from client %s\n",
- mach_acct, remote_machine ));
+ "get password for machine account %s "
+ "from client %s: %s\n",
+ mach_acct, remote_machine, nt_errstr(status) ));
+ /* always return NT_STATUS_ACCESS_DENIED */
return NT_STATUS_ACCESS_DENIED;
}
/* From the client / server challenges and md4 password, generate sess key */
- creds_server_init(p->dc,
+ creds_server_init(0, /* No neg flags. */
+ p->dc,
&p->dc->clnt_chal, /* Stored client chal. */
&p->dc->srv_chal, /* Stored server chal. */
- (const char *)p->dc->mach_pw,
+ p->dc->mach_pw,
&srv_chal_out);
/* Check client credentials are valid. */
@@ -377,6 +425,7 @@ static void init_net_r_auth_2(NET_R_AUTH_2 *r_a,
NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
{
+ NTSTATUS status;
NEG_FLAGS srv_flgs;
fstring mach_acct;
fstring remote_machine;
@@ -384,6 +433,8 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
+
+ /* We use this as the key to store the creds. */
rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
@@ -403,18 +454,21 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
return NT_STATUS_ACCESS_DENIED;
}
- if (!get_md4pw((char *)p->dc->mach_pw, mach_acct)) {
+ status = get_md4pw((char *)p->dc->mach_pw, mach_acct, q_u->clnt_id.sec_chan);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("_net_auth2: failed to get machine password for "
- "account %s\n",
- mach_acct ));
+ "account %s: %s\n",
+ mach_acct, nt_errstr(status) ));
+ /* always return NT_STATUS_ACCESS_DENIED */
return NT_STATUS_ACCESS_DENIED;
}
/* From the client / server challenges and md4 password, generate sess key */
- creds_server_init(p->dc,
+ creds_server_init(q_u->clnt_flgs.neg_flags,
+ p->dc,
&p->dc->clnt_chal, /* Stored client chal. */
&p->dc->srv_chal, /* Stored server chal. */
- (const char *)p->dc->mach_pw,
+ p->dc->mach_pw,
&srv_chal_out);
/* Check client credentials are valid. */
@@ -442,7 +496,9 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
/* Store off the state so we can continue after client disconnect. */
become_root();
- secrets_store_schannel_session_info(p->mem_ctx, p->dc);
+ secrets_store_schannel_session_info(p->mem_ctx,
+ remote_machine,
+ p->dc);
unbecome_root();
return r_u->status;
@@ -455,8 +511,8 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
{
NTSTATUS status = NT_STATUS_ACCESS_DENIED;
- fstring workstation;
- SAM_ACCOUNT *sampass=NULL;
+ fstring remote_machine;
+ struct samu *sampass=NULL;
BOOL ret = False;
unsigned char pwd[16];
int i;
@@ -464,32 +520,61 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
DOM_CRED cred_out;
const uchar *old_pw;
+ DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
+
+ /* We need the remote machine name for the creds lookup. */
+ rpcstr_pull(remote_machine,q_u->clnt_id.login.uni_comp_name.buffer,
+ sizeof(remote_machine),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
+
+ if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
+ /* 'server schannel = yes' should enforce use of
+ schannel, the client did offer it in auth2, but
+ obviously did not use it. */
+ DEBUG(0,("_net_srv_pwset: client %s not using schannel for netlogon\n",
+ remote_machine ));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!p->dc) {
+ /* Restore the saved state of the netlogon creds. */
+ become_root();
+ ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
+ remote_machine,
+ &p->dc);
+ unbecome_root();
+ if (!ret) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ }
+
if (!p->dc || !p->dc->authenticated) {
return NT_STATUS_INVALID_HANDLE;
}
+ DEBUG(3,("_net_srv_pwset: Server Password Set by remote machine:[%s] on account [%s]\n",
+ remote_machine, p->dc->mach_acct));
+
/* Step the creds chain forward. */
if (!creds_server_step(p->dc, &q_u->clnt_id.cred, &cred_out)) {
DEBUG(2,("_net_srv_pwset: creds_server_step failed. Rejecting auth "
"request from client %s machine account %s\n",
- p->dc->remote_machine, p->dc->mach_acct ));
- return NT_STATUS_ACCESS_DENIED;
+ remote_machine, p->dc->mach_acct ));
+ return NT_STATUS_INVALID_PARAMETER;
}
- DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
-
- rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer,
- sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
-
- DEBUG(3,("_net_srv_pwset: Server Password Set by Wksta:[%s] on account [%s]\n",
- workstation, p->dc->mach_acct));
-
- pdb_init_sam(&sampass);
-
+ /* We must store the creds state after an update. */
become_root();
- ret=pdb_getsampwnam(sampass, p->dc->mach_acct);
+ secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
+ remote_machine,
+ p->dc);
+ if ( (sampass = samu_new( NULL )) != NULL ) {
+ ret = pdb_getsampwnam(sampass, p->dc->mach_acct);
+ }
unbecome_root();
+ if ( !sampass )
+ return NT_STATUS_NO_MEMORY;
+
/* Ensure the account exists and is a machine account. */
acct_ctrl = pdb_get_acct_ctrl(sampass);
@@ -498,12 +583,12 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
&& (acct_ctrl & ACB_WSTRUST ||
acct_ctrl & ACB_SVRTRUST ||
acct_ctrl & ACB_DOMTRUST))) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_NO_SUCH_USER;
}
if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_ACCOUNT_DISABLED;
}
@@ -526,33 +611,30 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
/* LM password should be NULL for machines */
if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_NO_MEMORY;
}
if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_NO_MEMORY;
}
if (!pdb_set_pass_changed_now(sampass)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
/* Not quite sure what this one qualifies as, but this will do */
return NT_STATUS_UNSUCCESSFUL;
}
become_root();
- ret = pdb_update_sam_account (sampass);
+ r_u->status = pdb_update_sam_account (sampass);
unbecome_root();
}
- if (ret) {
- status = NT_STATUS_OK;
- }
/* set up the LSA Server Password Set response */
init_net_r_srv_pwset(r_u, &cred_out, status);
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return r_u->status;
}
@@ -562,9 +644,39 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
{
+ fstring remote_machine;
+
+ if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
+ /* 'server schannel = yes' should enforce use of
+ schannel, the client did offer it in auth2, but
+ obviously did not use it. */
+ DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n",
+ get_remote_machine_name() ));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+
if (!get_valid_user_struct(p->vuid))
return NT_STATUS_NO_SUCH_USER;
+ /* Get the remote machine name for the creds store. */
+ rpcstr_pull(remote_machine,q_u->sam_id.client.login.uni_comp_name.buffer,
+ sizeof(remote_machine),q_u->sam_id.client.login.uni_comp_name.uni_str_len*2,0);
+
+ if (!p->dc) {
+ /* Restore the saved state of the netlogon creds. */
+ BOOL ret;
+
+ become_root();
+ ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
+ remote_machine,
+ &p->dc);
+ unbecome_root();
+ if (!ret) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ }
+
if (!p->dc || !p->dc->authenticated) {
return NT_STATUS_INVALID_HANDLE;
}
@@ -575,41 +687,48 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF
if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
DEBUG(2,("_net_sam_logoff: creds_server_step failed. Rejecting auth "
"request from client %s machine account %s\n",
- p->dc->remote_machine, p->dc->mach_acct ));
- return NT_STATUS_ACCESS_DENIED;
+ remote_machine, p->dc->mach_acct ));
+ return NT_STATUS_INVALID_PARAMETER;
}
+ /* We must store the creds state after an update. */
+ become_root();
+ secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
+ remote_machine,
+ p->dc);
+ unbecome_root();
+
r_u->status = NT_STATUS_OK;
return r_u->status;
}
-
/*******************************************************************
gets a domain user's groups from their already-calculated NT_USER_TOKEN
********************************************************************/
-static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
- const NT_USER_TOKEN *nt_token,
+
+static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ size_t num_sids,
+ const DOM_SID *sids,
int *numgroups, DOM_GID **pgids)
{
- DOM_GID *gids;
int i;
- gids = TALLOC_ARRAY(mem_ctx, DOM_GID, nt_token->num_sids);
-
- if (!gids) {
- return NT_STATUS_NO_MEMORY;
- }
-
*numgroups=0;
+ *pgids = NULL;
- for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) {
- if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) {
- sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid));
- gids[*numgroups].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED);
- (*numgroups)++;
+ for (i=0; i<num_sids; i++) {
+ DOM_GID gid;
+ if (!sid_peek_check_rid(domain_sid, &sids[i], &gid.g_rid)) {
+ continue;
+ }
+ gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
+ SE_GROUP_ENABLED);
+ ADD_TO_ARRAY(mem_ctx, DOM_GID, gid, pgids, numgroups);
+ if (*pgids == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
}
- *pgids = gids;
return NT_STATUS_OK;
}
@@ -617,7 +736,10 @@ static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domai
_net_sam_logon
*************************************************************************/
-NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
+static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
+ NET_Q_SAM_LOGON *q_u,
+ NET_R_SAM_LOGON *r_u,
+ BOOL process_creds)
{
NTSTATUS status = NT_STATUS_OK;
NET_USER_INFO_3 *usr_info = NULL;
@@ -628,48 +750,83 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
fstring nt_username, nt_domain, nt_workstation;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
- SAM_ACCOUNT *sampw;
+ struct samu *sampw;
struct auth_context *auth_context = NULL;
-
+
+ if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
+ /* 'server schannel = yes' should enforce use of
+ schannel, the client did offer it in auth2, but
+ obviously did not use it. */
+ DEBUG(0,("_net_sam_logon_internal: client %s not using schannel for netlogon\n",
+ get_remote_machine_name() ));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
usr_info = TALLOC_P(p->mem_ctx, NET_USER_INFO_3);
- if (!usr_info)
+ if (!usr_info) {
return NT_STATUS_NO_MEMORY;
+ }
ZERO_STRUCTP(usr_info);
/* store the user information, if there is any. */
r_u->user = usr_info;
- r_u->switch_value = 0; /* indicates no info */
r_u->auth_resp = 1; /* authoritative response */
- r_u->switch_value = 3; /* indicates type of validation user info */
+ if (q_u->validation_level != 2 && q_u->validation_level != 3) {
+ DEBUG(0,("_net_sam_logon: bad validation_level value %d.\n", (int)q_u->validation_level ));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ /* We handle the return of USER_INFO_2 instead of 3 in the parse return. Sucks, I know... */
+ r_u->switch_value = q_u->validation_level; /* indicates type of validation user info */
r_u->buffer_creds = 1; /* Ensure we always return server creds. */
if (!get_valid_user_struct(p->vuid))
return NT_STATUS_NO_SUCH_USER;
- if (!p->dc || !p->dc->authenticated) {
- return NT_STATUS_INVALID_HANDLE;
- }
+ if (process_creds) {
+ fstring remote_machine;
- if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
- /* 'server schannel = yes' should enforce use of
- schannel, the client did offer it in auth2, but
- obviously did not use it. */
- DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n",
- p->dc->remote_machine ));
- return NT_STATUS_ACCESS_DENIED;
- }
+ /* Get the remote machine name for the creds store. */
+ /* Note this is the remote machine this request is coming from (member server),
+ not neccessarily the workstation name the user is logging onto.
+ */
+ rpcstr_pull(remote_machine,q_u->sam_id.client.login.uni_comp_name.buffer,
+ sizeof(remote_machine),q_u->sam_id.client.login.uni_comp_name.uni_str_len*2,0);
- /* checks and updates credentials. creates reply credentials */
- if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
- DEBUG(2,("_net_sam_logon: creds_server_step failed. Rejecting auth "
- "request from client %s machine account %s\n",
- p->dc->remote_machine, p->dc->mach_acct ));
- return NT_STATUS_ACCESS_DENIED;
+ if (!p->dc) {
+ /* Restore the saved state of the netlogon creds. */
+ BOOL ret;
+
+ become_root();
+ ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
+ remote_machine,
+ &p->dc);
+ unbecome_root();
+ if (!ret) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ }
+
+ if (!p->dc || !p->dc->authenticated) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* checks and updates credentials. creates reply credentials */
+ if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
+ DEBUG(2,("_net_sam_logon: creds_server_step failed. Rejecting auth "
+ "request from client %s machine account %s\n",
+ remote_machine, p->dc->mach_acct ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* We must store the creds state after an update. */
+ become_root();
+ secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
+ remote_machine,
+ p->dc);
+ unbecome_root();
}
- /* find the username */
-
switch (q_u->sam_id.logon_level) {
case INTERACTIVE_LOGON_TYPE:
uni_samlogon_user = &ctr->auth.id1.uni_user_name;
@@ -695,9 +852,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
- DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username,
- nt_workstation, nt_domain));
-
+ DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, nt_workstation, nt_domain));
fstrcpy(current_user_info.smb_name, nt_username);
sub_set_smb_name(nt_username);
@@ -734,10 +889,10 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
break;
}
case INTERACTIVE_LOGON_TYPE:
- /* 'Interactive' autheticaion, supplies the password in its
- MD4 form, encrypted with the session key. We will
- convert this to chellange/responce for the auth
- subsystem to chew on */
+ /* 'Interactive' authentication, supplies the password in its
+ MD4 form, encrypted with the session key. We will convert
+ this to challenge/response for the auth subsystem to chew
+ on */
{
const uint8 *chal;
@@ -787,14 +942,15 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
&& !is_trusted_domain(nt_domain) )
r_u->auth_resp = 0; /* We are not authoritative */
- free_server_info(&server_info);
+ TALLOC_FREE(server_info);
return status;
}
if (server_info->guest) {
/* We don't like guest domain logons... */
- DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
- free_server_info(&server_info);
+ DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST "
+ "denied.\n"));
+ TALLOC_FREE(server_info);
return NT_STATUS_LOGON_FAILURE;
}
@@ -813,13 +969,14 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
pstring my_name;
fstring user_sid_string;
fstring group_sid_string;
- uchar user_session_key[16];
- uchar lm_session_key[16];
- uchar netlogon_sess_key[16];
+ unsigned char user_session_key[16];
+ unsigned char lm_session_key[16];
+ unsigned char pipe_session_key[16];
sampw = server_info->sam_account;
- /* set up pointer indicating user/password failed to be found */
+ /* set up pointer indicating user/password failed to be
+ * found */
usr_info->ptr_user_info = 0;
user_sid = pdb_get_user_sid(sampw);
@@ -829,8 +986,12 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
sid_split_rid(&domain_sid, &user_rid);
if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
- DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n",
- pdb_get_domain(sampw), pdb_get_username(sampw),
+ DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid "
+ "%s\n but group sid %s.\n"
+ "The conflicting domain portions are not "
+ "supported for NETLOGON calls\n",
+ pdb_get_domain(sampw),
+ pdb_get_username(sampw),
sid_to_string(user_sid_string, user_sid),
sid_to_string(group_sid_string, group_sid)));
return NT_STATUS_UNSUCCESSFUL;
@@ -842,29 +1003,52 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
} else {
pstrcpy(my_name, global_myname());
}
-
- if (!NT_STATUS_IS_OK(status
- = nt_token_to_group_list(p->mem_ctx,
- &domain_sid,
- server_info->ptok,
- &num_gids,
- &gids))) {
+
+ status = nt_token_to_group_list(p->mem_ctx, &domain_sid,
+ server_info->num_sids,
+ server_info->sids,
+ &num_gids, &gids);
+
+ if (!NT_STATUS_IS_OK(status)) {
return status;
}
- ZERO_STRUCT(netlogon_sess_key);
- memcpy(netlogon_sess_key, p->dc->sess_key, 8);
if (server_info->user_session_key.length) {
- memcpy(user_session_key, server_info->user_session_key.data,
- MIN(sizeof(user_session_key), server_info->user_session_key.length));
- SamOEMhash(user_session_key, netlogon_sess_key, 16);
+ memcpy(user_session_key,
+ server_info->user_session_key.data,
+ MIN(sizeof(user_session_key),
+ server_info->user_session_key.length));
+ if (process_creds) {
+ /* Get the pipe session key from the creds. */
+ memcpy(pipe_session_key, p->dc->sess_key, 16);
+ } else {
+ /* Get the pipe session key from the schannel. */
+ if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL || p->auth.a_u.schannel_auth == NULL) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ memcpy(pipe_session_key, p->auth.a_u.schannel_auth->sess_key, 16);
+ }
+ SamOEMhash(user_session_key, pipe_session_key, 16);
+ memset(pipe_session_key, '\0', 16);
}
if (server_info->lm_session_key.length) {
- memcpy(lm_session_key, server_info->lm_session_key.data,
- MIN(sizeof(lm_session_key), server_info->lm_session_key.length));
- SamOEMhash(lm_session_key, netlogon_sess_key, 16);
+ memcpy(lm_session_key,
+ server_info->lm_session_key.data,
+ MIN(sizeof(lm_session_key),
+ server_info->lm_session_key.length));
+ if (process_creds) {
+ /* Get the pipe session key from the creds. */
+ memcpy(pipe_session_key, p->dc->sess_key, 16);
+ } else {
+ /* Get the pipe session key from the schannel. */
+ if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL || p->auth.a_u.schannel_auth == NULL) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+ memcpy(pipe_session_key, p->auth.a_u.schannel_auth->sess_key, 16);
+ }
+ SamOEMhash(lm_session_key, pipe_session_key, 16);
+ memset(pipe_session_key, '\0', 16);
}
- ZERO_STRUCT(netlogon_sess_key);
init_net_user_info3(p->mem_ctx, usr_info,
user_rid,
@@ -881,28 +1065,75 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
pdb_get_pass_last_set_time(sampw),
pdb_get_pass_can_change_time(sampw),
pdb_get_pass_must_change_time(sampw),
-
0, /* logon_count */
0, /* bad_pw_count */
num_gids, /* uint32 num_groups */
gids , /* DOM_GID *gids */
- 0x20 , /* uint32 user_flgs (?) */
+ LOGON_EXTRA_SIDS, /* uint32 user_flgs (?) */
+ pdb_get_acct_ctrl(sampw),
server_info->user_session_key.length ? user_session_key : NULL,
server_info->lm_session_key.length ? lm_session_key : NULL,
my_name , /* char *logon_srv */
pdb_get_domain(sampw),
- &domain_sid, /* DOM_SID *dom_sid */
- /* Should be users domain sid, not servers - for trusted domains */
-
- NULL); /* char *other_sids */
+ &domain_sid); /* DOM_SID *dom_sid */
ZERO_STRUCT(user_session_key);
ZERO_STRUCT(lm_session_key);
}
- free_server_info(&server_info);
+ TALLOC_FREE(server_info);
return status;
}
/*************************************************************************
+ _net_sam_logon
+ *************************************************************************/
+
+NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
+{
+ return _net_sam_logon_internal(p, q_u, r_u, True);
+}
+
+/*************************************************************************
+ _net_sam_logon_ex - no credential chaining. Map into net sam logon.
+ *************************************************************************/
+
+NTSTATUS _net_sam_logon_ex(pipes_struct *p, NET_Q_SAM_LOGON_EX *q_u, NET_R_SAM_LOGON_EX *r_u)
+{
+ NET_Q_SAM_LOGON q;
+ NET_R_SAM_LOGON r;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Only allow this if the pipe is protected. */
+ if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
+ DEBUG(0,("_net_sam_logon_ex: client %s not using schannel for netlogon\n",
+ get_remote_machine_name() ));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Map a NET_Q_SAM_LOGON_EX to NET_Q_SAM_LOGON. */
+ q.validation_level = q_u->validation_level;
+
+ /* Map a DOM_SAM_INFO_EX into a DOM_SAM_INFO with no creds. */
+ q.sam_id.client.login = q_u->sam_id.client;
+ q.sam_id.logon_level = q_u->sam_id.logon_level;
+ q.sam_id.ctr = q_u->sam_id.ctr;
+
+ r_u->status = _net_sam_logon_internal(p, &q, &r, False);
+
+ if (!NT_STATUS_IS_OK(r_u->status)) {
+ return r_u->status;
+ }
+
+ /* Map the NET_R_SAM_LOGON to NET_R_SAM_LOGON_EX. */
+ r_u->switch_value = r.switch_value;
+ r_u->user = r.user;
+ r_u->auth_resp = r.auth_resp;
+ r_u->flags = 0; /* FIXME ! */
+ return r_u->status;
+}
+
+/*************************************************************************
_ds_enum_dom_trusts
*************************************************************************/
#if 0 /* JERRY -- not correct */
diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c
index ecf79d0c1f3..72298520e3e 100644
--- a/source/rpc_server/srv_pipe.c
+++ b/source/rpc_server/srv_pipe.c
@@ -71,7 +71,7 @@ static BOOL create_next_pdu_ntlmssp(pipes_struct *p)
*/
if(p->fault_state) {
- setup_fault_pdu(p, NT_STATUS(0x1c010002));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
return True;
}
@@ -284,7 +284,7 @@ static BOOL create_next_pdu_schannel(pipes_struct *p)
*/
if(p->fault_state) {
- setup_fault_pdu(p, NT_STATUS(0x1c010002));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
return True;
}
@@ -460,7 +460,7 @@ static BOOL create_next_pdu_noauth(pipes_struct *p)
*/
if(p->fault_state) {
- setup_fault_pdu(p, NT_STATUS(0x1c010002));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
return True;
}
@@ -606,7 +606,7 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
NTSTATUS status;
AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state;
- DEBUG(5,("pipe_ntlmssp_verify_final: checking user details\n"));
+ DEBUG(5,("pipe_ntlmssp_verify_final: pipe %s checking user details\n", p->name));
ZERO_STRUCT(reply);
@@ -616,9 +616,9 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
memset(p->wks, '\0', sizeof(p->wks));
/* Set up for non-authenticated user. */
- delete_nt_token(&p->pipe_user.nt_user_token);
- p->pipe_user.ngroups = 0;
- SAFE_FREE( p->pipe_user.groups);
+ TALLOC_FREE(p->pipe_user.nt_user_token);
+ p->pipe_user.ut.ngroups = 0;
+ SAFE_FREE( p->pipe_user.ut.groups);
status = auth_ntlmssp_update(a, *p_resp_blob, &reply);
@@ -629,6 +629,27 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
return False;
}
+ /* Finally - if the pipe negotiated integrity (sign) or privacy (seal)
+ ensure the underlying NTLMSSP flags are also set. If not we should
+ refuse the bind. */
+
+ if (p->auth.auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+ if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet integrity requested "
+ "but client declined signing.\n",
+ p->name ));
+ return False;
+ }
+ }
+ if (p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+ if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+ DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet privacy requested "
+ "but client declined sealing.\n",
+ p->name ));
+ return False;
+ }
+ }
+
fstrcpy(p->user_name, a->ntlmssp_state->user);
fstrcpy(p->pipe_user_name, a->server_info->unix_name);
fstrcpy(p->domain, a->ntlmssp_state->domain);
@@ -641,8 +662,8 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
* Store the UNIX credential data (uid/gid pair) in the pipe structure.
*/
- p->pipe_user.uid = a->server_info->uid;
- p->pipe_user.gid = a->server_info->gid;
+ p->pipe_user.ut.uid = a->server_info->uid;
+ p->pipe_user.ut.gid = a->server_info->gid;
/*
* Copy the session key from the ntlmssp state.
@@ -654,16 +675,18 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
return False;
}
- p->pipe_user.ngroups = a->server_info->n_groups;
- if (p->pipe_user.ngroups) {
- if (!(p->pipe_user.groups = memdup(a->server_info->groups, sizeof(gid_t) * p->pipe_user.ngroups))) {
+ p->pipe_user.ut.ngroups = a->server_info->n_groups;
+ if (p->pipe_user.ut.ngroups) {
+ if (!(p->pipe_user.ut.groups = memdup(a->server_info->groups,
+ sizeof(gid_t) * p->pipe_user.ut.ngroups))) {
DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n"));
return False;
}
}
if (a->server_info->ptok) {
- p->pipe_user.nt_user_token = dup_nt_token(a->server_info->ptok);
+ p->pipe_user.nt_user_token =
+ dup_nt_token(NULL, a->server_info->ptok);
} else {
DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
p->pipe_user.nt_user_token = NULL;
@@ -1030,7 +1053,7 @@ NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *s
rpc_lookup will still be valid afterwards. It could then succeed if
called again later */
rpc_lookup_size++;
- rpc_entry = SMB_REALLOC_ARRAY(rpc_lookup, struct rpc_table, rpc_lookup_size);
+ rpc_entry = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(rpc_lookup, struct rpc_table, rpc_lookup_size);
if (NULL == rpc_entry) {
rpc_lookup_size--;
DEBUG(0, ("rpc_pipe_register_commands: memory allocation failed\n"));
@@ -1044,6 +1067,9 @@ NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *s
rpc_entry->pipe.clnt = SMB_STRDUP(clnt);
rpc_entry->pipe.srv = SMB_STRDUP(srv);
rpc_entry->cmds = SMB_REALLOC_ARRAY(rpc_entry->cmds, struct api_struct, rpc_entry->n_cmds + size);
+ if (!rpc_entry->cmds) {
+ return NT_STATUS_NO_MEMORY;
+ }
memcpy(rpc_entry->cmds + rpc_entry->n_cmds, cmds, size * sizeof(struct api_struct));
rpc_entry->n_cmds += size;
@@ -1282,7 +1308,7 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
RPC_AUTH_SCHANNEL_NEG neg;
RPC_AUTH_VERIFIER auth_verifier;
BOOL ret;
- struct dcinfo stored_dcinfo;
+ struct dcinfo *pdcinfo;
uint32 flags;
if (!smb_io_rpc_auth_schannel_neg("", &neg, rpc_in_p, 0)) {
@@ -1290,10 +1316,14 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
return False;
}
- ZERO_STRUCT(stored_dcinfo);
+ /*
+ * The neg.myname key here must match the remote computer name
+ * given in the DOM_CLNT_SRV.uni_comp_name used on all netlogon pipe
+ * operations that use credentials.
+ */
become_root();
- ret = secrets_restore_schannel_session_info(p->mem_ctx, neg.myname, &stored_dcinfo);
+ ret = secrets_restore_schannel_session_info(p->mem_ctx, neg.myname, &pdcinfo);
unbecome_root();
if (!ret) {
@@ -1303,29 +1333,24 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
p->auth.a_u.schannel_auth = TALLOC_P(p->pipe_state_mem_ctx, struct schannel_auth_struct);
if (!p->auth.a_u.schannel_auth) {
+ TALLOC_FREE(pdcinfo);
return False;
}
memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key));
- memcpy(p->auth.a_u.schannel_auth->sess_key, stored_dcinfo.sess_key, sizeof(stored_dcinfo.sess_key));
+ memcpy(p->auth.a_u.schannel_auth->sess_key, pdcinfo->sess_key,
+ sizeof(pdcinfo->sess_key));
+
+ TALLOC_FREE(pdcinfo);
p->auth.a_u.schannel_auth->seq_num = 0;
/*
* JRA. Should we also copy the schannel session key into the pipe session key p->session_key
- * here ? We do that for NTLMSPP, but the session key is already set up from the vuser
+ * here ? We do that for NTLMSSP, but the session key is already set up from the vuser
* struct of the person who opened the pipe. I need to test this further. JRA.
*/
- /* The client opens a second RPC NETLOGON pipe without
- doing a auth2. The credentials for the schannel are
- re-used from the auth2 the client did before. */
- p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo);
- if (!p->dc) {
- return False;
- }
- *p->dc = stored_dcinfo;
-
init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) {
DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n"));
@@ -2246,7 +2271,7 @@ BOOL api_rpcTNP(pipes_struct *p, const char *rpc_name,
* and not put the pipe into fault state. JRA.
*/
DEBUG(4, ("unknown\n"));
- setup_fault_pdu(p, NT_STATUS(0x1c010002));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
return True;
}
@@ -2264,7 +2289,7 @@ BOOL api_rpcTNP(pipes_struct *p, const char *rpc_name,
if (p->bad_handle_fault_state) {
DEBUG(4,("api_rpcTNP: bad handle fault return.\n"));
p->bad_handle_fault_state = False;
- setup_fault_pdu(p, NT_STATUS(0x1C00001A));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_CONTEXT_MISMATCH));
return True;
}
diff --git a/source/rpc_server/srv_pipe_hnd.c b/source/rpc_server/srv_pipe_hnd.c
index 5fb84115cc3..9cc8b72546f 100644
--- a/source/rpc_server/srv_pipe_hnd.c
+++ b/source/rpc_server/srv_pipe_hnd.c
@@ -330,6 +330,8 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
talloc_destroy(p->mem_ctx);
talloc_destroy(p->pipe_state_mem_ctx);
+ close_policy_by_pipe(p);
+ SAFE_FREE(p);
return NULL;
}
@@ -343,13 +345,14 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
ZERO_STRUCT(p->pipe_user);
- p->pipe_user.uid = (uid_t)-1;
- p->pipe_user.gid = (gid_t)-1;
+ p->pipe_user.ut.uid = (uid_t)-1;
+ p->pipe_user.ut.gid = (gid_t)-1;
/* Store the session key and NT_TOKEN */
if (vuser) {
p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);
- p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token);
+ p->pipe_user.nt_user_token = dup_nt_token(
+ NULL, vuser->nt_user_token);
}
/*
@@ -696,7 +699,7 @@ static void process_complete_pdu(pipes_struct *p)
DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
p->name ));
set_incoming_fault(p);
- setup_fault_pdu(p, NT_STATUS(0x1c010002));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
return;
}
@@ -823,7 +826,7 @@ static void process_complete_pdu(pipes_struct *p)
if (!reply) {
DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on pipe %s\n", p->pipe_srv_name));
set_incoming_fault(p);
- setup_fault_pdu(p, NT_STATUS(0x1c010002));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
prs_mem_free(&rpc_in);
} else {
/*
@@ -1222,9 +1225,9 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn)
/* Free the handles database. */
close_policy_by_pipe(p);
- delete_nt_token(&p->pipe_user.nt_user_token);
+ TALLOC_FREE(p->pipe_user.nt_user_token);
data_blob_free(&p->session_key);
- SAFE_FREE(p->pipe_user.groups);
+ SAFE_FREE(p->pipe_user.ut.groups);
DLIST_REMOVE(InternalPipes, p);
diff --git a/source/rpc_server/srv_reg_nt.c b/source/rpc_server/srv_reg_nt.c
index 33711d0fac9..5ac6738b991 100644
--- a/source/rpc_server/srv_reg_nt.c
+++ b/source/rpc_server/srv_reg_nt.c
@@ -835,8 +835,10 @@ static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
/* get the rootkey from the regf file and then load the tree
via recursive calls */
- if ( !(rootkey = regfio_rootkey( regfile )) )
+ if ( !(rootkey = regfio_rootkey( regfile )) ) {
+ regfio_close( regfile );
return WERR_REG_FILE_INVALID;
+ }
result = reg_load_tree( regfile, krecord->name, rootkey );
diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c
index cbfad5688e1..8e4955a81c2 100644
--- a/source/rpc_server/srv_samr.c
+++ b/source/rpc_server/srv_samr.c
@@ -679,6 +679,68 @@ static BOOL api_samr_connect4(pipes_struct *p)
return True;
}
+/*******************************************************************
+ api_samr_chgpasswd_user3
+ ********************************************************************/
+
+static BOOL api_samr_chgpasswd_user3(pipes_struct *p)
+{
+ SAMR_Q_CHGPASSWD_USER3 q_u;
+ SAMR_R_CHGPASSWD_USER3 r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ /* change password request */
+ if (!samr_io_q_chgpasswd_user3("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_chgpasswd_user3: Failed to unmarshall SAMR_Q_CHGPASSWD_USER3.\n"));
+ return False;
+ }
+
+ r_u.status = _samr_chgpasswd_user3(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!samr_io_r_chgpasswd_user3("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_chgpasswd_user3: Failed to marshall SAMR_R_CHGPASSWD_USER3.\n" ));
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
+ api_samr_connect5
+ ********************************************************************/
+
+static BOOL api_samr_connect5(pipes_struct *p)
+{
+ SAMR_Q_CONNECT5 q_u;
+ SAMR_R_CONNECT5 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 samr open policy */
+ if(!samr_io_q_connect5("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_connect5: unable to unmarshall SAMR_Q_CONNECT5.\n"));
+ return False;
+ }
+
+ r_u.status = _samr_connect5(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!samr_io_r_connect5("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_connect5: unable to marshall SAMR_R_CONNECT5.\n"));
+ return False;
+ }
+
+ return True;
+}
+
/**********************************************************************
api_samr_lookup_domain
**********************************************************************/
@@ -787,7 +849,7 @@ static BOOL api_samr_set_userinfo(pipes_struct *p)
/* Fix for W2K SP2 */
/* what is that status-code ? - gd */
if (q_u.switch_value == 0x1a) {
- setup_fault_pdu(p, NT_STATUS(0x1c000006));
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_INVALID_TAG));
return True;
}
return False;
@@ -1492,7 +1554,9 @@ static struct api_struct api_samr_cmds [] =
{"SAMR_GET_USRDOM_PWINFO" , SAMR_GET_USRDOM_PWINFO, api_samr_get_usrdom_pwinfo},
{"SAMR_QUERY_DOMAIN_INFO2", SAMR_QUERY_DOMAIN_INFO2, api_samr_query_domain_info2},
{"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info },
- {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 }
+ {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 },
+ {"SAMR_CHGPASSWD_USER3" , SAMR_CHGPASSWD_USER3 , api_samr_chgpasswd_user3 },
+ {"SAMR_CONNECT5" , SAMR_CONNECT5 , api_samr_connect5 }
};
void samr_get_pipe_fns( struct api_struct **fns, int *n_fns )
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index 4e6ebeaf64f..c4b3d3512c0 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -140,7 +140,7 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd
if ( sid ) {
init_sec_access( &mask, sid_access );
init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-}
+ }
/* create the security descriptor */
@@ -470,7 +470,7 @@ static void force_flush_samr_cache(DISP_INFO *disp_info)
Ensure password info is never given out. Paranioa... JRA.
********************************************************************/
-static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
+static void samr_clear_sam_passwd(struct samu *sam_pass)
{
if (!sam_pass)
@@ -482,7 +482,7 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
pdb_set_nt_passwd(sam_pass, NULL, PDB_DEFAULT);
}
-static uint32 count_sam_users(struct disp_info *info, uint16 acct_flags)
+static uint32 count_sam_users(struct disp_info *info, uint32 acct_flags)
{
struct samr_displayentry *entry;
@@ -1377,9 +1377,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];
- uint32 local_rid;
enum SID_NAME_USE type[MAX_SAM_ENTRIES];
- enum SID_NAME_USE local_type;
int i;
int num_rids = q_u->num_names2;
DOM_SID pol_sid;
@@ -1411,42 +1409,30 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
for (i = 0; i < num_rids; i++) {
fstring name;
- DOM_SID sid;
int ret;
r_u->status = NT_STATUS_NONE_MAPPED;
+ type[i] = SID_NAME_UNKNOWN;
rid [i] = 0xffffffff;
- type[i] = SID_NAME_UNKNOWN;
ret = rpcstr_pull(name, q_u->uni_name[i].buffer, sizeof(name), q_u->uni_name[i].uni_str_len*2, 0);
- /*
- * we are only looking for a name
- * the SID we get back can be outside
- * the scope of the pol_sid
- *
- * in clear: it prevents to reply to domain\group: yes
- * when only builtin\group exists.
- *
- * a cleaner code is to add the sid of the domain we're looking in
- * to the local_lookup_name function.
- */
-
- if ((ret > 0) && local_lookup_name(name, &sid, &local_type)) {
- sid_split_rid(&sid, &local_rid);
-
- if (sid_equal(&sid, &pol_sid)) {
- rid[i]=local_rid;
-
- /* Windows does not return WKN_GRP here, even
- * on lookups in builtin */
- type[i] = (local_type == SID_NAME_WKN_GRP) ?
- SID_NAME_ALIAS : local_type;
-
- r_u->status = NT_STATUS_OK;
+ if (ret <= 0) {
+ continue;
+ }
+
+ if (sid_check_is_builtin(&pol_sid)) {
+ if (lookup_builtin_name(name, &rid[i])) {
+ type[i] = SID_NAME_ALIAS;
}
- }
+ } else {
+ lookup_global_sam_name(name, 0, &rid[i], &type[i]);
+ }
+
+ if (type[i] != SID_NAME_UNKNOWN) {
+ r_u->status = NT_STATUS_OK;
+ }
}
init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
@@ -1487,7 +1473,7 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_
*/
r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
- q_u->nt_newpass.pass, q_u->nt_oldhash.hash);
+ q_u->nt_newpass.pass, q_u->nt_oldhash.hash, NULL);
init_samr_r_chgpasswd_user(r_u, r_u->status);
@@ -1497,6 +1483,98 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_
}
/*******************************************************************
+ _samr_chgpasswd_user3
+ ********************************************************************/
+
+NTSTATUS _samr_chgpasswd_user3(pipes_struct *p, SAMR_Q_CHGPASSWD_USER3 *q_u, SAMR_R_CHGPASSWD_USER3 *r_u)
+{
+ fstring user_name;
+ fstring wks;
+ uint32 reject_reason;
+ SAM_UNK_INFO_1 *info = NULL;
+ SAMR_CHANGE_REJECT *reject = NULL;
+
+ DEBUG(5,("_samr_chgpasswd_user3: %d\n", __LINE__));
+
+ rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0);
+ rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0);
+
+ DEBUG(5,("_samr_chgpasswd_user3: user: %s wks: %s\n", user_name, wks));
+
+ /*
+ * Pass the user through the NT -> unix user mapping
+ * function.
+ */
+
+ (void)map_username(user_name);
+
+ /*
+ * UNIX username case mangling not required, pass_oem_change
+ * is case insensitive.
+ */
+
+ r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
+ q_u->nt_newpass.pass, q_u->nt_oldhash.hash, &reject_reason);
+
+ if (NT_STATUS_EQUAL(r_u->status, NT_STATUS_PASSWORD_RESTRICTION) ||
+ NT_STATUS_EQUAL(r_u->status, NT_STATUS_ACCOUNT_RESTRICTION)) {
+
+ uint32 min_pass_len,pass_hist,password_properties;
+ time_t u_expire, u_min_age;
+ NTTIME nt_expire, nt_min_age;
+ uint32 account_policy_temp;
+
+ if ((info = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_INFO_1)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ((reject = TALLOC_ZERO_P(p->mem_ctx, SAMR_CHANGE_REJECT)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCTP(info);
+ ZERO_STRUCTP(reject);
+
+ become_root();
+
+ /* AS ROOT !!! */
+
+ pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp);
+ min_pass_len = account_policy_temp;
+
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp);
+ pass_hist = account_policy_temp;
+
+ pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
+ password_properties = account_policy_temp;
+
+ pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
+ u_expire = account_policy_temp;
+
+ pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp);
+ u_min_age = account_policy_temp;
+
+ /* !AS ROOT */
+
+ unbecome_root();
+
+ unix_to_nt_time_abs(&nt_expire, u_expire);
+ unix_to_nt_time_abs(&nt_min_age, u_min_age);
+
+ init_unk_info1(info, (uint16)min_pass_len, (uint16)pass_hist,
+ password_properties, nt_expire, nt_min_age);
+
+ reject->reject_reason = reject_reason;
+ }
+
+ init_samr_r_chgpasswd_user3(r_u, r_u->status, reject, info);
+
+ DEBUG(5,("_samr_chgpasswd_user3: %d\n", __LINE__));
+
+ return r_u->status;
+}
+
+/*******************************************************************
makes a SAMR_R_LOOKUP_RIDS structure.
********************************************************************/
@@ -1572,6 +1650,10 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
names, attrs);
unbecome_root();
+ if ( NT_STATUS_EQUAL(r_u->status, NT_STATUS_NONE_MAPPED) && (num_rids == 0) ) {
+ r_u->status = NT_STATUS_OK;
+ }
+
if(!make_samr_lookup_rids(p->mem_ctx, num_rids, names,
&hdr_name, &uni_name))
return NT_STATUS_NO_MEMORY;
@@ -1589,7 +1671,7 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USER *r_u)
{
- SAM_ACCOUNT *sampass=NULL;
+ struct samu *sampass=NULL;
DOM_SID sid;
POLICY_HND domain_pol = q_u->domain_pol;
POLICY_HND *user_pol = &r_u->user_pol;
@@ -1615,10 +1697,9 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
if ( !NT_STATUS_IS_OK(nt_status) )
return nt_status;
- nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass);
-
- if (!NT_STATUS_IS_OK(nt_status))
- return nt_status;
+ if ( !(sampass = samu_new( p->mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
/* append the user's RID to it */
@@ -1649,7 +1730,7 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
return NT_STATUS_NO_SUCH_USER;
}
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
/* associate the user's SID and access bits with the new handle. */
if ((info = get_samr_info_by_sid(&sid)) == NULL)
@@ -1669,21 +1750,18 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_SID *user_sid)
{
- SAM_ACCOUNT *smbpass=NULL;
+ struct samu *smbpass=NULL;
BOOL ret;
- NTSTATUS nt_status;
- nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
+ if ( !(smbpass = samu_new( mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
}
-
+
become_root();
ret = pdb_getsampwsid(smbpass, user_sid);
unbecome_root();
- if (ret==False) {
+ if ( !ret ) {
DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
return NT_STATUS_NO_SUCH_USER;
}
@@ -1693,7 +1771,7 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_S
ZERO_STRUCTP(id7);
init_sam_user_info7(id7, pdb_get_username(smbpass) );
- pdb_free_sam(&smbpass);
+ TALLOC_FREE(smbpass);
return NT_STATUS_OK;
}
@@ -1703,14 +1781,11 @@ static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_S
*************************************************************************/
static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_SID *user_sid)
{
- SAM_ACCOUNT *smbpass=NULL;
+ struct samu *smbpass=NULL;
BOOL ret;
- NTSTATUS nt_status;
- nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
+ if ( !(smbpass = samu_new( mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
}
become_root();
@@ -1727,7 +1802,7 @@ static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_
ZERO_STRUCTP(id9);
init_sam_user_info9(id9, pdb_get_group_rid(smbpass) );
- pdb_free_sam(&smbpass);
+ TALLOC_FREE(smbpass);
return NT_STATUS_OK;
}
@@ -1738,14 +1813,11 @@ static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx, SAM_USER_INFO_9 * id9, DOM_
static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, SAM_USER_INFO_16 *id16, DOM_SID *user_sid)
{
- SAM_ACCOUNT *smbpass=NULL;
+ struct samu *smbpass=NULL;
BOOL ret;
- NTSTATUS nt_status;
- nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
+ if ( !(smbpass = samu_new( mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
}
become_root();
@@ -1762,7 +1834,7 @@ static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, SAM_USER_INFO_16 *id16, DO
ZERO_STRUCTP(id16);
init_sam_user_info16(id16, pdb_get_acct_ctrl(smbpass) );
- pdb_free_sam(&smbpass);
+ TALLOC_FREE(smbpass);
return NT_STATUS_OK;
}
@@ -1775,9 +1847,8 @@ static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx, SAM_USER_INFO_16 *id16, DO
static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_INFO_18 * id18, DOM_SID *user_sid)
{
- SAM_ACCOUNT *smbpass=NULL;
+ struct samu *smbpass=NULL;
BOOL ret;
- NTSTATUS nt_status;
if (p->auth.auth_type != PIPE_AUTH_TYPE_NTLMSSP || p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
return NT_STATUS_ACCESS_DENIED;
@@ -1791,31 +1862,29 @@ static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_
* Do *NOT* do become_root()/unbecome_root() here ! JRA.
*/
- nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
+ if ( !(smbpass = samu_new( mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
}
ret = pdb_getsampwsid(smbpass, user_sid);
if (ret == False) {
DEBUG(4, ("User %s not found\n", sid_string_static(user_sid)));
- pdb_free_sam(&smbpass);
+ TALLOC_FREE(smbpass);
return (geteuid() == (uid_t)0) ? NT_STATUS_NO_SUCH_USER : NT_STATUS_ACCESS_DENIED;
}
DEBUG(3,("User:[%s] 0x%x\n", pdb_get_username(smbpass), pdb_get_acct_ctrl(smbpass) ));
if ( pdb_get_acct_ctrl(smbpass) & ACB_DISABLED) {
- pdb_free_sam(&smbpass);
+ TALLOC_FREE(smbpass);
return NT_STATUS_ACCOUNT_DISABLED;
}
ZERO_STRUCTP(id18);
init_sam_user_info18(id18, pdb_get_lanman_passwd(smbpass), pdb_get_nt_passwd(smbpass));
- pdb_free_sam(&smbpass);
+ TALLOC_FREE(smbpass);
return NT_STATUS_OK;
}
@@ -1826,10 +1895,12 @@ static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_
static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DOM_SID *user_sid)
{
- SAM_ACCOUNT *sampass=NULL;
+ struct samu *sampass=NULL;
BOOL ret;
- pdb_init_sam_talloc(mem_ctx, &sampass);
+ if ( !(sampass = samu_new( mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
become_root();
ret = pdb_getsampwsid(sampass, user_sid);
@@ -1847,7 +1918,7 @@ static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DO
ZERO_STRUCTP(id20);
init_sam_user_info20A(id20, sampass);
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_OK;
}
@@ -1859,13 +1930,12 @@ static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DO
static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
DOM_SID *user_sid, DOM_SID *domain_sid)
{
- SAM_ACCOUNT *sampass=NULL;
+ struct samu *sampass=NULL;
BOOL ret;
NTSTATUS nt_status;
- nt_status = pdb_init_sam_talloc(mem_ctx, &sampass);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
+ if ( !(sampass = samu_new( mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
}
become_root();
@@ -1884,7 +1954,7 @@ static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
ZERO_STRUCTP(id21);
nt_status = init_sam_user_info21A(id21, sampass, domain_sid);
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_OK;
}
@@ -1952,28 +2022,6 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
return r_u->status;
break;
-#if 0
-/* whoops - got this wrong. i think. or don't understand what's happening. */
- case 17:
- {
- NTTIME expire;
- info = (void *)&id11;
-
- expire.low = 0xffffffff;
- expire.high = 0x7fffffff;
-
- ctr->info.id = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_17));
- ZERO_STRUCTP(ctr->info.id17);
- init_sam_user_info17(ctr->info.id17, &expire,
- "BROOKFIELDS$", /* name */
- 0x03ef, /* user rid */
- 0x201, /* group rid */
- 0x0080); /* acb info */
-
- break;
- }
-#endif
-
case 18:
ctr->info.id18 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_18);
if (ctr->info.id18 == NULL)
@@ -2017,11 +2065,12 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u)
{
- SAM_ACCOUNT *sam_pass=NULL;
- struct passwd *passwd;
+ struct samu *sam_pass=NULL;
DOM_SID sid;
DOM_SID *sids;
+ DOM_GID dom_gid;
DOM_GID *gids = NULL;
+ uint32 primary_group_rid;
size_t num_groups = 0;
gid_t *unix_gids;
size_t i, num_gids;
@@ -2056,58 +2105,74 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
if (!sid_check_is_in_our_domain(&sid))
return NT_STATUS_OBJECT_TYPE_MISMATCH;
- pdb_init_sam(&sam_pass);
-
+ if ( !(sam_pass = samu_new( p->mem_ctx )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
become_root();
ret = pdb_getsampwsid(sam_pass, &sid);
unbecome_root();
- if (ret == False) {
- pdb_free_sam(&sam_pass);
- return NT_STATUS_NO_SUCH_USER;
- }
-
- passwd = getpwnam_alloc(pdb_get_username(sam_pass));
- if (passwd == NULL) {
- pdb_free_sam(&sam_pass);
+ if (!ret) {
+ DEBUG(10, ("pdb_getsampwsid failed for %s\n",
+ sid_string_static(&sid)));
return NT_STATUS_NO_SUCH_USER;
}
sids = NULL;
become_root();
- result = pdb_enum_group_memberships(pdb_get_username(sam_pass),
- passwd->pw_gid,
+ result = pdb_enum_group_memberships(p->mem_ctx, sam_pass,
&sids, &unix_gids, &num_groups);
unbecome_root();
- pdb_free_sam(&sam_pass);
- passwd_free(&passwd);
-
- if (!NT_STATUS_IS_OK(result))
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
+ sid_string_static(&sid)));
return result;
-
- SAFE_FREE(unix_gids);
+ }
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)) {
+ 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)));
+ TALLOC_FREE(sam_pass);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ 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++) {
- uint32 rid;
if (!sid_peek_check_rid(get_global_sam_sid(),
- &(sids[i]), &rid))
+ &(sids[i]), &dom_gid.g_rid)) {
+ DEBUG(10, ("Found sid %s not in our domain\n",
+ sid_string_static(&sids[i])));
continue;
+ }
+
+ if (dom_gid.g_rid == primary_group_rid) {
+ /* We added the primary group directly from the
+ * sam_account. The other SIDs are unique from
+ * enum_group_memberships */
+ continue;
+ }
- gids = TALLOC_REALLOC_ARRAY(p->mem_ctx, gids, DOM_GID, num_gids+1);
- gids[num_gids].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED);
- gids[num_gids].g_rid = rid;
- num_gids += 1;
+ ADD_TO_ARRAY(p->mem_ctx, DOM_GID, dom_gid, &gids, &num_gids);
}
- SAFE_FREE(sids);
/* construct the response. lkclXXXX: gids are not copied! */
- init_samr_r_query_usergroups(r_u, num_groups, gids, r_u->status);
+ init_samr_r_query_usergroups(r_u, num_gids, gids, r_u->status);
DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
@@ -2122,7 +2187,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
{
struct samr_info *info = NULL;
SAM_UNK_CTR *ctr;
- uint32 min_pass_len,pass_hist,flag;
+ uint32 min_pass_len,pass_hist,password_properties;
time_t u_expire, u_min_age;
NTTIME nt_expire, nt_min_age;
@@ -2168,7 +2233,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
pass_hist = account_policy_temp;
pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
- flag = account_policy_temp;
+ password_properties = account_policy_temp;
pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
u_expire = account_policy_temp;
@@ -2184,7 +2249,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
unix_to_nt_time_abs(&nt_min_age, u_min_age);
init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist,
- flag, nt_expire, nt_min_age);
+ password_properties, nt_expire, nt_min_age);
break;
case 0x02:
@@ -2221,7 +2286,11 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
/* AS ROOT !!! */
- pdb_get_account_policy(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout);
+ {
+ uint32 ul;
+ pdb_get_account_policy(AP_TIME_TO_LOGOUT, &ul);
+ u_logout = (time_t)ul;
+ }
/* !AS ROOT */
@@ -2299,30 +2368,63 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
return r_u->status;
}
+/* W2k3 seems to use the same check for all 3 objects that can be created via
+ * SAMR, if you try to create for example "Dialup" as an alias it says
+ * "NT_STATUS_USER_EXISTS". This is racy, but we can't really lock the user
+ * database. */
+
+static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name)
+{
+ enum SID_NAME_USE type;
+ BOOL result;
+
+ DEBUG(10, ("Checking whether [%s] can be created\n", new_name));
+
+ become_root();
+ /* Lookup in our local databases (only LOOKUP_NAME_ISOLATED set)
+ * whether the name already exists */
+ result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_ISOLATED,
+ NULL, NULL, NULL, &type);
+ unbecome_root();
+
+ if (!result) {
+ DEBUG(10, ("%s does not exist, can create it\n", new_name));
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(5, ("trying to create %s, exists as %s\n",
+ new_name, sid_type_lookup(type)));
+
+ if (type == SID_NAME_DOM_GRP) {
+ return NT_STATUS_GROUP_EXISTS;
+ }
+ if (type == SID_NAME_ALIAS) {
+ return NT_STATUS_ALIAS_EXISTS;
+ }
+
+ /* Yes, the default is NT_STATUS_USER_EXISTS */
+ return NT_STATUS_USER_EXISTS;
+}
+
/*******************************************************************
_samr_create_user
Create an account, can be either a normal user or a machine.
This funcion will need to be updated for bdc/domain trusts.
********************************************************************/
-NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREATE_USER *r_u)
+NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
+ SAMR_R_CREATE_USER *r_u)
{
- SAM_ACCOUNT *sam_pass=NULL;
- fstring account;
+ char *account;
DOM_SID sid;
- pstring add_script;
POLICY_HND dom_pol = q_u->domain_pol;
- UNISTR2 user_account = q_u->uni_name;
uint16 acb_info = q_u->acb_info;
POLICY_HND *user_pol = &r_u->user_pol;
struct samr_info *info = NULL;
- BOOL ret;
NTSTATUS nt_status;
- struct passwd *pw;
uint32 acc_granted;
SEC_DESC *psd;
size_t sd_size;
- uint32 new_rid = 0;
/* check this, when giving away 'add computer to domain' privs */
uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS;
BOOL can_add_account = False;
@@ -2330,72 +2432,61 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
DISP_INFO *disp_info = NULL;
/* Get the domain SID stored in the domain policy */
- if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted, &disp_info))
+ if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted,
+ &disp_info))
return NT_STATUS_INVALID_HANDLE;
- if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_USER, "_samr_create_user"))) {
+ nt_status = access_check_samr_function(acc_granted,
+ SA_RIGHT_DOMAIN_CREATE_USER,
+ "_samr_create_user");
+ if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
- if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST || acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) {
+ if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST ||
+ acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) {
/* Match Win2k, and return NT_STATUS_INVALID_PARAMETER if
this parameter is not an account type */
return NT_STATUS_INVALID_PARAMETER;
}
- rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0);
- strlower_m(account);
-
- pdb_init_sam(&sam_pass);
-
- become_root();
- ret = pdb_getsampwnam(sam_pass, account);
- unbecome_root();
- if (ret == True) {
- /* this account exists: say so */
- pdb_free_sam(&sam_pass);
- return NT_STATUS_USER_EXISTS;
+ account = rpcstr_pull_unistr2_talloc(p->mem_ctx, &q_u->uni_name);
+ if (account == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- pdb_free_sam(&sam_pass);
-
- /*********************************************************************
- * HEADS UP! If we have to create a new user account, we have to get
- * a new RID from somewhere. This used to be done by the passdb
- * backend. It has been moved into idmap now. Since idmap is now
- * wrapped up behind winbind, this means you have to run winbindd if you
- * want new accounts to get a new RID when "enable rid algorithm = no".
- * Tough. We now have a uniform way of allocating RIDs regardless
- * of what ever passdb backend people may use.
- * --jerry (2003-07-10)
- *********************************************************************/
-
- pw = Get_Pwnam(account);
+ nt_status = can_create(p->mem_ctx, account);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
/* determine which user right we need to check based on the acb_info */
if ( acb_info & ACB_WSTRUST )
{
- pstrcpy(add_script, lp_addmachine_script());
se_priv_copy( &se_rights, &se_machine_account );
- can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
+ can_add_account = user_has_privileges(
+ p->pipe_user.nt_user_token, &se_rights );
}
/* usrmgr.exe (and net rpc trustdom grant) creates a normal user
account for domain trusts and changes the ACB flags later */
- else if ( acb_info & ACB_NORMAL && (account[strlen(account)-1] != '$') )
+ else if ( acb_info & ACB_NORMAL &&
+ (account[strlen(account)-1] != '$') )
{
- pstrcpy(add_script, lp_adduser_script());
se_priv_copy( &se_rights, &se_add_users );
- can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
+ can_add_account = user_has_privileges(
+ p->pipe_user.nt_user_token, &se_rights );
}
- else /* implicit assumption of a BDC or domain trust account here (we already check the flags earlier) */
+ else /* implicit assumption of a BDC or domain trust account here
+ * (we already check the flags earlier) */
{
- pstrcpy(add_script, lp_addmachine_script());
if ( lp_enable_privileges() ) {
/* only Domain Admins can add a BDC or domain trust */
se_priv_copy( &se_rights, &se_priv_none );
- can_add_account = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
- }
+ can_add_account = nt_token_check_domain_rid(
+ p->pipe_user.nt_user_token,
+ DOMAIN_GROUP_RID_ADMINS );
+ }
}
DEBUG(5, ("_samr_create_user: %s can add this account : %s\n",
@@ -2406,35 +2497,9 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
if ( can_add_account )
become_root();
- if ( !pw ) {
- if (*add_script) {
- int add_ret;
-
- all_string_sub(add_script, "%u", account, sizeof(add_script));
- add_ret = smbrun(add_script,NULL);
- DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
- }
- }
+ nt_status = pdb_create_user(p->mem_ctx, account, acb_info,
+ &r_u->user_rid);
- /* implicit call to getpwnam() next. we have a valid SID coming out of this call */
-
- flush_pwnam_cache();
- nt_status = pdb_init_sam_new(&sam_pass, account, new_rid);
-
- /* this code is order such that we have no unnecessary retuns
- out of the admin block of code */
-
- if ( NT_STATUS_IS_OK(nt_status) ) {
- pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
-
- if ( !(ret = pdb_add_sam_account(sam_pass)) ) {
- pdb_free_sam(&sam_pass);
- DEBUG(0, ("could not add user/computer %s to passdb. Check permissions?\n",
- account));
- nt_status = NT_STATUS_ACCESS_DENIED;
- }
- }
-
if ( can_add_account )
unbecome_root();
@@ -2446,10 +2511,11 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
return nt_status;
/* Get the user's SID */
+
+ sid_compose(&sid, get_global_sam_sid(), r_u->user_rid);
- sid_copy(&sid, pdb_get_user_sid(sam_pass));
-
- make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping,
+ &sid, SAMR_USR_RIGHTS_WRITE_PW);
se_map_generic(&des_access, &usr_generic_mapping);
nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
@@ -2462,7 +2528,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
/* associate the user's SID with the new handle. */
if ((info = get_samr_info_by_sid(&sid)) == NULL) {
- pdb_free_sam(&sam_pass);
return NT_STATUS_NO_MEMORY;
}
@@ -2472,19 +2537,14 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
/* get a (unique) handle. open a policy on it. */
if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) {
- pdb_free_sam(&sam_pass);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
/* After a "set" ensure we have no cached display info. */
force_flush_samr_cache(info->disp_info);
- r_u->user_rid=pdb_get_user_rid(sam_pass);
-
r_u->access_granted = acc_granted;
- pdb_free_sam(&sam_pass);
-
return NT_STATUS_OK;
}
@@ -2517,6 +2577,11 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO
was observed from a win98 client trying to enumerate users (when configured
user level access control on shares) --jerry */
+ if (des_access == MAXIMUM_ALLOWED_ACCESS) {
+ /* Map to max possible knowing we're filtered below. */
+ des_access = GENERIC_ALL_ACCESS;
+ }
+
se_map_generic( &des_access, &sam_generic_mapping );
info->acc_granted = des_access & (SA_RIGHT_SAM_ENUM_DOMAINS|SA_RIGHT_SAM_OPEN_DOMAIN);
@@ -2631,6 +2696,60 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *
return r_u->status;
}
+/*******************************************************************
+ samr_connect5
+ ********************************************************************/
+
+NTSTATUS _samr_connect5(pipes_struct *p, SAMR_Q_CONNECT5 *q_u, SAMR_R_CONNECT5 *r_u)
+{
+ struct samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access = q_u->access_mask;
+ NTSTATUS nt_status;
+ POLICY_HND pol;
+ size_t sd_size;
+
+
+ DEBUG(5,("_samr_connect5: %d\n", __LINE__));
+
+ ZERO_STRUCTP(r_u);
+
+ /* Access check */
+
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to samr_connect5\n"));
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ return r_u->status;
+ }
+
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0);
+ se_map_generic(&des_access, &sam_generic_mapping);
+
+ nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ NULL, 0, des_access, &acc_granted, "_samr_connect5");
+
+ if ( !NT_STATUS_IS_OK(nt_status) )
+ return nt_status;
+
+ /* associate the user's SID and access granted with the new handle. */
+ if ((info = get_samr_info_by_sid(NULL)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ info->acc_granted = acc_granted;
+ info->status = q_u->access_mask;
+
+ /* get a (unique) handle. open a policy on it. */
+ if (!create_policy_hnd(p, &pol, free_samr_info, (void *)info))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ DEBUG(5,("_samr_connect: %d\n", __LINE__));
+
+ init_samr_r_connect5(r_u, &pol, NT_STATUS_OK);
+
+ return r_u->status;
+}
+
/**********************************************************************
api_samr_lookup_domain
**********************************************************************/
@@ -2662,9 +2781,9 @@ NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_
if (strequal(domain_name, builtin_domain_name())) {
sid_copy(&sid, &global_sid_Builtin);
} else {
- if (!secrets_fetch_domain_sid(domain_name, &sid)) {
- r_u->status = NT_STATUS_NO_SUCH_DOMAIN;
- }
+ if (!secrets_fetch_domain_sid(domain_name, &sid)) {
+ r_u->status = NT_STATUS_NO_SUCH_DOMAIN;
+ }
}
DEBUG(2,("Returning domain sid for domain %s -> %s\n", domain_name, sid_string_static(&sid)));
@@ -2778,7 +2897,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
/* append the alias' RID to it */
if (!sid_append_rid(&sid, alias_rid))
- return NT_STATUS_NO_SUCH_USER;
+ return NT_STATUS_NO_SUCH_ALIAS;
/*check if access can be granted as requested by client. */
@@ -2795,10 +2914,27 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
if ( !NT_STATUS_IS_OK(status) )
return status;
- /*
- * we should check if the rid really exist !!!
- * JFM.
- */
+ {
+ /* Check we actually have the requested alias */
+ enum SID_NAME_USE type;
+ BOOL result;
+ gid_t gid;
+
+ become_root();
+ result = lookup_sid(NULL, &sid, NULL, NULL, &type);
+ unbecome_root();
+
+ if (!result || (type != SID_NAME_ALIAS)) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ /* make sure there is a mapping */
+
+ if ( !sid_to_gid( &sid, &gid ) ) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ }
/* associate the alias SID with the new handle. */
if ((info = get_samr_info_by_sid(&sid)) == NULL)
@@ -2816,22 +2952,21 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
/*******************************************************************
set_user_info_7
********************************************************************/
-static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
+static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx,
+ const SAM_USER_INFO_7 *id7, struct samu *pwd)
{
fstring new_name;
- SAM_ACCOUNT *check_acct = NULL;
NTSTATUS rc;
- BOOL check_rc;
if (id7 == NULL) {
DEBUG(5, ("set_user_info_7: NULL id7\n"));
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return NT_STATUS_ACCESS_DENIED;
}
if(!rpcstr_pull(new_name, id7->uni_name.buffer, sizeof(new_name), id7->uni_name.uni_str_len*2, 0)) {
DEBUG(5, ("set_user_info_7: failed to get new username\n"));
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return NT_STATUS_ACCESS_DENIED;
}
@@ -2844,18 +2979,14 @@ static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
simply that the rename fails with a slightly different status
code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */
- pdb_init_sam(&check_acct);
- check_rc = pdb_getsampwnam(check_acct, new_name);
- pdb_free_sam(&check_acct);
-
- if (check_rc == True) {
- /* this account exists: say so */
- return NT_STATUS_USER_EXISTS;
+ rc = can_create(mem_ctx, new_name);
+ if (!NT_STATUS_IS_OK(rc)) {
+ return rc;
}
rc = pdb_rename_sam_account(pwd, new_name);
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return rc;
}
@@ -2863,26 +2994,26 @@ static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
set_user_info_16
********************************************************************/
-static BOOL set_user_info_16(const SAM_USER_INFO_16 *id16, SAM_ACCOUNT *pwd)
+static BOOL set_user_info_16(const SAM_USER_INFO_16 *id16, struct samu *pwd)
{
if (id16 == NULL) {
DEBUG(5, ("set_user_info_16: NULL id16\n"));
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
/* FIX ME: check if the value is really changed --metze */
if (!pdb_set_acct_ctrl(pwd, id16->acb_info, PDB_CHANGED)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
- if(!pdb_update_sam_account(pwd)) {
- pdb_free_sam(&pwd);
+ if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
return False;
}
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return True;
}
@@ -2891,78 +3022,42 @@ static BOOL set_user_info_16(const SAM_USER_INFO_16 *id16, SAM_ACCOUNT *pwd)
set_user_info_18
********************************************************************/
-static BOOL set_user_info_18(SAM_USER_INFO_18 *id18, SAM_ACCOUNT *pwd)
+static BOOL set_user_info_18(SAM_USER_INFO_18 *id18, struct samu *pwd)
{
if (id18 == NULL) {
DEBUG(2, ("set_user_info_18: id18 is NULL\n"));
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
if (!pdb_set_lanman_passwd (pwd, id18->lm_pwd, PDB_CHANGED)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
if (!pdb_set_nt_passwd (pwd, id18->nt_pwd, PDB_CHANGED)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
if (!pdb_set_pass_changed_now (pwd)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
- if(!pdb_update_sam_account(pwd)) {
- pdb_free_sam(&pwd);
+ if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
return False;
}
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return True;
}
/*******************************************************************
- The GROUPSID field in the SAM_ACCOUNT changed. Try to tell unix.
- ********************************************************************/
-static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass)
-{
- struct group *grp;
- gid_t gid;
-
- if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sampass),
- &gid))) {
- DEBUG(2,("Could not get gid for primary group of "
- "user %s\n", pdb_get_username(sampass)));
- return False;
- }
-
- grp = getgrgid(gid);
-
- if (grp == NULL) {
- DEBUG(2,("Could not find primary group %lu for "
- "user %s\n", (unsigned long)gid,
- pdb_get_username(sampass)));
- return False;
- }
-
- if (smb_set_primary_group(grp->gr_name,
- pdb_get_username(sampass)) != 0) {
- DEBUG(2,("Could not set primary group for user %s to "
- "%s\n",
- pdb_get_username(sampass), grp->gr_name));
- return False;
- }
-
- return True;
-}
-
-
-/*******************************************************************
set_user_info_20
********************************************************************/
-static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd)
+static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, struct samu *pwd)
{
if (id20 == NULL) {
DEBUG(5, ("set_user_info_20: NULL id20\n"));
@@ -2972,12 +3067,12 @@ static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd)
copy_id20_to_sam_passwd(pwd, id20);
/* write the change out */
- if(!pdb_update_sam_account(pwd)) {
- pdb_free_sam(&pwd);
+ if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
return False;
}
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return True;
}
@@ -2985,14 +3080,50 @@ static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd)
set_user_info_21
********************************************************************/
-static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd)
+static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
+ struct samu *pwd)
{
-
+ fstring new_name;
+ NTSTATUS status;
+
if (id21 == NULL) {
DEBUG(5, ("set_user_info_21: NULL id21\n"));
- return False;
+ return NT_STATUS_INVALID_PARAMETER;
}
-
+
+ /* 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)))) {
+
+ /* check to see if the new username already exists. Note: we can't
+ reliably lock all backends, so there is potentially the
+ possibility that a user can be created in between this check and
+ the rename. The rename should fail, but may not get the
+ exact same failure status code. I think this is small enough
+ of a window for this type of operation and the results are
+ simply that the rename fails with a slightly different status
+ code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */
+
+ status = can_create(mem_ctx, new_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = pdb_rename_sam_account(pwd, new_name);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("set_user_info_21: failed to rename account: %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(pwd);
+ return status;
+ }
+
+ /* set the new username so that later
+ functions can work on the new account */
+ pdb_set_username(pwd, new_name, PDB_SET);
+ }
+
copy_id21_to_sam_passwd(pwd, id21);
/*
@@ -3002,33 +3133,43 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd)
* id21. I don't know if they need to be set. --jerry
*/
- if (IS_SAM_CHANGED(pwd, PDB_GROUPSID))
- set_unix_primary_group(pwd);
+ if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) {
+ status = pdb_set_unix_primary_group(mem_ctx, pwd);
+ if ( !NT_STATUS_IS_OK(status) ) {
+ return status;
+ }
+ }
+
+ /* 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(!pdb_update_sam_account(pwd)) {
- pdb_free_sam(&pwd);
- return False;
+ if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
+ return status;
}
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
- return True;
+ return NT_STATUS_OK;
}
/*******************************************************************
set_user_info_23
********************************************************************/
-static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
+static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23,
+ struct samu *pwd)
{
pstring plaintext_buf;
uint32 len;
uint16 acct_ctrl;
+ NTSTATUS status;
if (id23 == NULL) {
DEBUG(5, ("set_user_info_23: NULL id23\n"));
- return False;
+ return NT_STATUS_INVALID_PARAMETER;
}
DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n",
@@ -3037,13 +3178,13 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
acct_ctrl = pdb_get_acct_ctrl(pwd);
if (!decode_pw_buffer(id23->pass, plaintext_buf, 256, &len, STR_UNICODE)) {
- pdb_free_sam(&pwd);
- return False;
+ TALLOC_FREE(pwd);
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) {
- pdb_free_sam(&pwd);
- return False;
+ TALLOC_FREE(pwd);
+ return NT_STATUS_ACCESS_DENIED;
}
copy_id23_to_sam_passwd(pwd, id23);
@@ -3062,36 +3203,40 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
}
if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
- pdb_free_sam(&pwd);
- return False;
+ TALLOC_FREE(pwd);
+ return NT_STATUS_ACCESS_DENIED;
}
}
}
ZERO_STRUCT(plaintext_buf);
- if (IS_SAM_CHANGED(pwd, PDB_GROUPSID))
- set_unix_primary_group(pwd);
+ if (IS_SAM_CHANGED(pwd, PDB_GROUPSID) &&
+ (!NT_STATUS_IS_OK(status = pdb_set_unix_primary_group(mem_ctx,
+ pwd)))) {
+ TALLOC_FREE(pwd);
+ return status;
+ }
- if(!pdb_update_sam_account(pwd)) {
- pdb_free_sam(&pwd);
- return False;
+ if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
+ return status;
}
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
- return True;
+ return NT_STATUS_OK;
}
/*******************************************************************
set_user_info_pw
********************************************************************/
-static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd)
+static BOOL set_user_info_pw(uint8 *pass, struct samu *pwd)
{
uint32 len;
pstring plaintext_buf;
- uint16 acct_ctrl;
+ uint32 acct_ctrl;
DEBUG(5, ("Attempting administrator password change for user %s\n",
pdb_get_username(pwd)));
@@ -3101,12 +3246,12 @@ static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd)
ZERO_STRUCT(plaintext_buf);
if (!decode_pw_buffer(pass, plaintext_buf, 256, &len, STR_UNICODE)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
@@ -3124,7 +3269,7 @@ static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd)
}
if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return False;
}
}
@@ -3135,12 +3280,12 @@ static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd)
DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n"));
/* update the SAMBA password */
- if(!pdb_update_sam_account(pwd)) {
- pdb_free_sam(&pwd);
+ if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
+ TALLOC_FREE(pwd);
return False;
}
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return True;
}
@@ -3151,7 +3296,7 @@ static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd)
NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_USERINFO *r_u)
{
- SAM_ACCOUNT *pwd = NULL;
+ struct samu *pwd = NULL;
DOM_SID sid;
POLICY_HND *pol = &q_u->pol;
uint16 switch_value = q_u->switch_value;
@@ -3186,14 +3331,16 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
return NT_STATUS_INVALID_INFO_CLASS;
}
- pdb_init_sam(&pwd);
+ if ( !(pwd = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
become_root();
ret = pdb_getsampwsid(pwd, &sid);
unbecome_root();
if ( !ret ) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return NT_STATUS_NO_SUCH_USER;
}
@@ -3239,27 +3386,27 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
break;
case 25:
-#if 0
- /*
- * Currently we don't really know how to unmarshall
- * the level 25 struct, and the password encryption
- * is different. This is a placeholder for when we
- * do understand it. In the meantime just return INVALID
- * info level and W2K SP2 drops down to level 23... JRA.
- */
-
if (!p->session_key.length) {
r_u->status = NT_STATUS_NO_USER_SESSION_KEY;
}
- SamOEMhashBlob(ctr->info.id25->pass, 532, &p->session_key);
+ encode_or_decode_arc4_passwd_buffer(ctr->info.id25->pass, &p->session_key);
dump_data(100, (char *)ctr->info.id25->pass, 532);
- if (!set_user_info_pw(ctr->info.id25->pass, &sid))
+ if (!set_user_info_pw(ctr->info.id25->pass, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
-#endif
- r_u->status = NT_STATUS_INVALID_INFO_CLASS;
+
+ case 26:
+ if (!p->session_key.length) {
+ r_u->status = NT_STATUS_NO_USER_SESSION_KEY;
+ }
+ encode_or_decode_arc4_passwd_buffer(ctr->info.id26->pass, &p->session_key);
+
+ dump_data(100, (char *)ctr->info.id26->pass, 516);
+
+ if (!set_user_info_pw(ctr->info.id26->pass, pwd))
+ r_u->status = NT_STATUS_ACCESS_DENIED;
break;
case 23:
@@ -3270,8 +3417,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
dump_data(100, (char *)ctr->info.id23->pass, 516);
- if (!set_user_info_23(ctr->info.id23, pwd))
- r_u->status = NT_STATUS_ACCESS_DENIED;
+ r_u->status = set_user_info_23(p->mem_ctx,
+ ctr->info.id23, pwd);
break;
default:
@@ -3297,7 +3444,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_SET_USERINFO2 *r_u)
{
- SAM_ACCOUNT *pwd = NULL;
+ struct samu *pwd = NULL;
DOM_SID sid;
SAM_USERINFO_CTR *ctr = q_u->ctr;
POLICY_HND *pol = &q_u->pol;
@@ -3317,9 +3464,14 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
- /* observed when joining XP client to Samba domain */
+#if 0 /* this really should be applied on a per info level basis --jerry */
+
+ /* observed when joining XP client to Samba domain */
acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY;
+#else
+ acc_required = SA_RIGHT_USER_SET_ATTRIBUTES;
+#endif
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) {
return r_u->status;
@@ -3334,14 +3486,16 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
switch_value=ctr->switch_value;
- pdb_init_sam(&pwd);
-
+ if ( !(pwd = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
become_root();
ret = pdb_getsampwsid(pwd, &sid);
unbecome_root();
if ( !ret ) {
- pdb_free_sam(&pwd);
+ TALLOC_FREE(pwd);
return NT_STATUS_NO_SUCH_USER;
}
@@ -3355,7 +3509,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
}
- DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
+ DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n",
p->pipe_user_name, has_enough_rights ? "" : " not"));
/* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
@@ -3367,7 +3521,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
switch (switch_value) {
case 7:
- r_u->status = set_user_info_7(ctr->info.id7, pwd);
+ r_u->status = set_user_info_7(p->mem_ctx,
+ ctr->info.id7, pwd);
break;
case 16:
if (!set_user_info_16(ctr->info.id16, pwd))
@@ -3383,8 +3538,30 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
case 21:
- if (!set_user_info_21(ctr->info.id21, pwd))
- return NT_STATUS_ACCESS_DENIED;
+ r_u->status = set_user_info_21(p->mem_ctx,
+ ctr->info.id21, pwd);
+ break;
+ case 23:
+ if (!p->session_key.length) {
+ r_u->status = NT_STATUS_NO_USER_SESSION_KEY;
+ }
+ SamOEMhashBlob(ctr->info.id23->pass, 516, &p->session_key);
+
+ dump_data(100, (char *)ctr->info.id23->pass, 516);
+
+ r_u->status = set_user_info_23(p->mem_ctx,
+ ctr->info.id23, pwd);
+ break;
+ case 26:
+ if (!p->session_key.length) {
+ r_u->status = NT_STATUS_NO_USER_SESSION_KEY;
+ }
+ encode_or_decode_arc4_passwd_buffer(ctr->info.id26->pass, &p->session_key);
+
+ dump_data(100, (char *)ctr->info.id26->pass, 516);
+
+ if (!set_user_info_pw(ctr->info.id26->pass, pwd))
+ r_u->status = NT_STATUS_ACCESS_DENIED;
break;
default:
r_u->status = NT_STATUS_INVALID_INFO_CLASS;
@@ -3417,7 +3594,6 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
NTSTATUS ntstatus2;
DOM_SID *members;
- BOOL res;
r_u->status = NT_STATUS_OK;
@@ -3453,13 +3629,14 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
num_alias_rids = 0;
become_root();
- res = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members,
- q_u->num_sids1,
- &alias_rids, &num_alias_rids);
+ ntstatus1 = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members,
+ q_u->num_sids1,
+ &alias_rids, &num_alias_rids);
unbecome_root();
- if (!res)
- return NT_STATUS_UNSUCCESSFUL;
+ if (!NT_STATUS_IS_OK(ntstatus1)) {
+ return ntstatus1;
+ }
init_samr_r_query_useraliases(r_u, num_alias_rids, alias_rids,
NT_STATUS_OK);
@@ -3472,6 +3649,7 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_R_QUERY_ALIASMEM *r_u)
{
+ NTSTATUS status;
size_t i;
size_t num_sids = 0;
DOM_SID2 *sid;
@@ -3492,8 +3670,11 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
- if (!pdb_enum_aliasmem(&alias_sid, &sids, &num_sids))
- return NT_STATUS_NO_SUCH_ALIAS;
+ status = pdb_enum_aliasmem(&alias_sid, &sids, &num_sids);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
sid = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_SID2, num_sids);
if (num_sids!=0 && sid == NULL) {
@@ -3512,70 +3693,6 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
return NT_STATUS_OK;
}
-static void add_uid_to_array_unique(uid_t uid, uid_t **uids, int *num)
-{
- int i;
-
- for (i=0; i<*num; i++) {
- if ((*uids)[i] == uid)
- return;
- }
-
- *uids = SMB_REALLOC_ARRAY(*uids, uid_t, *num+1);
-
- if (*uids == NULL)
- return;
-
- (*uids)[*num] = uid;
- *num += 1;
-}
-
-
-static BOOL get_memberuids(gid_t gid, uid_t **uids, int *num)
-{
- struct group *grp;
- char **gr;
- struct sys_pwent *userlist, *user;
-
- *uids = NULL;
- *num = 0;
-
- /* We only look at our own sam, so don't care about imported stuff */
-
- winbind_off();
-
- if ((grp = getgrgid(gid)) == NULL) {
- winbind_on();
- return False;
- }
-
- /* Primary group members */
-
- userlist = getpwent_list();
-
- for (user = userlist; user != NULL; user = user->next) {
- if (user->pw_gid != gid)
- continue;
- add_uid_to_array_unique(user->pw_uid, uids, num);
- }
-
- pwent_free(userlist);
-
- /* Secondary group members */
-
- for (gr = grp->gr_mem; (*gr != NULL) && ((*gr)[0] != '\0'); gr += 1) {
- struct passwd *pw = getpwnam(*gr);
-
- if (pw == NULL)
- continue;
- add_uid_to_array_unique(pw->pw_uid, uids, num);
- }
-
- winbind_on();
-
- return True;
-}
-
/*********************************************************************
_samr_query_groupmem
*********************************************************************/
@@ -3642,7 +3759,7 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
- BOOL ret;
+ NTSTATUS ret;
DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
@@ -3670,11 +3787,11 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
/******** END SeAddUsers BLOCK *********/
- if (ret) {
+ if (NT_STATUS_IS_OK(ret)) {
force_flush_samr_cache(disp_info);
}
- return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+ return ret;
}
/*********************************************************************
@@ -3687,7 +3804,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
- BOOL ret;
+ NTSTATUS ret;
DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
@@ -3716,11 +3833,11 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
/******** END SeAddUsers BLOCK *********/
- if (ret) {
+ if (NT_STATUS_IS_OK(ret)) {
force_flush_samr_cache(disp_info);
}
- return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+ return ret;
}
/*********************************************************************
@@ -3730,16 +3847,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_ADD_GROUPMEM *r_u)
{
DOM_SID group_sid;
- DOM_SID user_sid;
- fstring group_sid_str;
- uid_t uid;
- struct passwd *pwd;
- struct group *grp;
- fstring grp_name;
- GROUP_MAP map;
- NTSTATUS ret;
- SAM_ACCOUNT *sam_user=NULL;
- BOOL check;
+ uint32 group_rid;
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
@@ -3753,55 +3861,11 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
return r_u->status;
}
- sid_to_string(group_sid_str, &group_sid);
- DEBUG(10, ("sid is %s\n", group_sid_str));
-
- if (sid_compare(&group_sid, get_global_sam_sid())<=0)
- return NT_STATUS_NO_SUCH_GROUP;
-
- DEBUG(10, ("lookup on Domain SID\n"));
-
- if(!get_domain_group_from_sid(group_sid, &map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- sid_copy(&user_sid, get_global_sam_sid());
- sid_append_rid(&user_sid, q_u->rid);
-
- ret = pdb_init_sam(&sam_user);
- if (!NT_STATUS_IS_OK(ret))
- return ret;
-
- check = pdb_getsampwsid(sam_user, &user_sid);
-
- if (check != True) {
- pdb_free_sam(&sam_user);
- return NT_STATUS_NO_SUCH_USER;
- }
-
- /* check a real user exist before we run the script to add a user to a group */
- if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) {
- pdb_free_sam(&sam_user);
- return NT_STATUS_NO_SUCH_USER;
- }
-
- pdb_free_sam(&sam_user);
+ DEBUG(10, ("sid is %s\n", sid_string_static(&group_sid)));
- if ((pwd=getpwuid_alloc(uid)) == NULL) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- if ((grp=getgrgid(map.gid)) == NULL) {
- passwd_free(&pwd);
- return NT_STATUS_NO_SUCH_GROUP;
- }
-
- /* we need to copy the name otherwise it's overloaded in user_in_unix_group_list */
- fstrcpy(grp_name, grp->gr_name);
-
- /* if the user is already in the group */
- if(user_in_unix_group_list(pwd->pw_name, grp_name)) {
- passwd_free(&pwd);
- return NT_STATUS_MEMBER_IN_GROUP;
+ if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
+ &group_rid)) {
+ return NT_STATUS_INVALID_HANDLE;
}
se_priv_copy( &se_rights, &se_add_users );
@@ -3811,31 +3875,17 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
if ( can_add_accounts )
become_root();
-
- /*
- * ok, the group exist, the user exist, the user is not in the group,
- *
- * we can (finally) add it to the group !
- */
-
- smb_add_user_group(grp_name, pwd->pw_name);
+ r_u->status = pdb_add_groupmem(p->mem_ctx, group_rid, q_u->rid);
+
if ( can_add_accounts )
unbecome_root();
/******** END SeAddUsers BLOCK *********/
- /* check if the user has been added then ... */
- if(!user_in_unix_group_list(pwd->pw_name, grp_name)) {
- passwd_free(&pwd);
- return NT_STATUS_MEMBER_NOT_IN_GROUP; /* don't know what to reply else */
- }
-
- passwd_free(&pwd);
-
force_flush_samr_cache(disp_info);
- return NT_STATUS_OK;
+ return r_u->status;
}
/*********************************************************************
@@ -3845,11 +3895,7 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DEL_GROUPMEM *r_u)
{
DOM_SID group_sid;
- DOM_SID user_sid;
- SAM_ACCOUNT *sam_pass=NULL;
- GROUP_MAP map;
- fstring grp_name;
- struct group *grp;
+ uint32 group_rid;
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
@@ -3868,36 +3914,11 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_REMOVE_MEMBER, "_samr_del_groupmem"))) {
return r_u->status;
}
-
- if (!sid_check_is_in_our_domain(&group_sid))
- return NT_STATUS_NO_SUCH_GROUP;
-
- sid_copy(&user_sid, get_global_sam_sid());
- sid_append_rid(&user_sid, q_u->rid);
-
- if (!get_domain_group_from_sid(group_sid, &map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- if ((grp=getgrgid(map.gid)) == NULL)
- return NT_STATUS_NO_SUCH_GROUP;
-
- /* we need to copy the name otherwise it's overloaded in user_in_group_list */
- fstrcpy(grp_name, grp->gr_name);
-
- /* check if the user exists before trying to remove it from the group */
- pdb_init_sam(&sam_pass);
- if (!pdb_getsampwsid(sam_pass, &user_sid)) {
- DEBUG(5,("User %s doesn't exist.\n", pdb_get_username(sam_pass)));
- pdb_free_sam(&sam_pass);
- return NT_STATUS_NO_SUCH_USER;
- }
- /* if the user is not in the group */
- if (!user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
- pdb_free_sam(&sam_pass);
- return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
+ &group_rid)) {
+ return NT_STATUS_INVALID_HANDLE;
}
-
se_priv_copy( &se_rights, &se_add_users );
can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
@@ -3907,45 +3928,16 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
if ( can_add_accounts )
become_root();
- smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
+ r_u->status = pdb_del_groupmem(p->mem_ctx, group_rid, q_u->rid);
if ( can_add_accounts )
unbecome_root();
/******** END SeAddUsers BLOCK *********/
- /* check if the user has been removed then ... */
- if (user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
- pdb_free_sam(&sam_pass);
- return NT_STATUS_ACCESS_DENIED; /* don't know what to reply else */
- }
-
- pdb_free_sam(&sam_pass);
-
force_flush_samr_cache(disp_info);
- return NT_STATUS_OK;
-
-}
-
-/****************************************************************************
- Delete a UNIX user on demand.
-****************************************************************************/
-
-static int smb_delete_user(const char *unix_user)
-{
- pstring del_script;
- int ret;
-
- pstrcpy(del_script, lp_deluser_script());
- if (! *del_script)
- return -1;
- all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
- ret = smbrun(del_script,NULL);
- flush_pwnam_cache();
- DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
-
- return ret;
+ return r_u->status;
}
/*********************************************************************
@@ -3955,10 +3947,10 @@ static int smb_delete_user(const char *unix_user)
NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAMR_R_DELETE_DOM_USER *r_u )
{
DOM_SID user_sid;
- SAM_ACCOUNT *sam_pass=NULL;
+ struct samu *sam_pass=NULL;
uint32 acc_granted;
BOOL can_add_accounts;
- BOOL ret;
+ uint32 acb_info;
DISP_INFO *disp_info = NULL;
DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
@@ -3975,48 +3967,48 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
return NT_STATUS_CANNOT_DELETE;
/* check if the user exists before trying to delete */
- pdb_init_sam(&sam_pass);
+ if ( !(sam_pass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
if(!pdb_getsampwsid(sam_pass, &user_sid)) {
DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n",
sid_string_static(&user_sid)));
- pdb_free_sam(&sam_pass);
+ TALLOC_FREE(sam_pass);
return NT_STATUS_NO_SUCH_USER;
}
- can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_add_users );
+ acb_info = pdb_get_acct_ctrl(sam_pass);
+
+ /* For machine accounts it's the SeMachineAccountPrivilege that counts. */
+ if ( acb_info & ACB_WSTRUST ) {
+ can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_machine_account );
+ } else {
+ can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_add_users );
+ }
/******** BEGIN SeAddUsers BLOCK *********/
if ( can_add_accounts )
become_root();
- /* First delete the samba side....
- code is order to prevent unnecessary returns out of the admin
- block of code */
-
- if ( (ret = pdb_delete_sam_account(sam_pass)) == True ) {
- /*
- * Now delete the unix side ....
- * note: we don't check if the delete really happened
- * as the script is not necessary present
- * and maybe the sysadmin doesn't want to delete the unix side
- */
- smb_delete_user( pdb_get_username(sam_pass) );
- }
-
+ r_u->status = pdb_delete_user(p->mem_ctx, sam_pass);
+
if ( can_add_accounts )
unbecome_root();
/******** END SeAddUsers BLOCK *********/
- if ( !ret ) {
- DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
- pdb_free_sam(&sam_pass);
- return NT_STATUS_CANNOT_DELETE;
+ if ( !NT_STATUS_IS_OK(r_u->status) ) {
+ DEBUG(5,("_samr_delete_dom_user: Failed to delete entry for "
+ "user %s: %s.\n", pdb_get_username(sam_pass),
+ nt_errstr(r_u->status)));
+ TALLOC_FREE(sam_pass);
+ return r_u->status;
}
- pdb_free_sam(&sam_pass);
+ TALLOC_FREE(sam_pass);
if (!close_policy_hnd(p, &q_u->user_pol))
return NT_STATUS_OBJECT_NAME_INVALID;
@@ -4033,16 +4025,10 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, SAMR_R_DELETE_DOM_GROUP *r_u)
{
DOM_SID group_sid;
- DOM_SID dom_sid;
uint32 group_rid;
- fstring group_sid_str;
- gid_t gid;
- struct group *grp;
- GROUP_MAP map;
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
- BOOL ret;
DISP_INFO *disp_info = NULL;
DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__));
@@ -4054,27 +4040,13 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_group"))) {
return r_u->status;
}
-
- sid_copy(&dom_sid, &group_sid);
- sid_to_string(group_sid_str, &dom_sid);
- sid_split_rid(&dom_sid, &group_rid);
-
- DEBUG(10, ("sid is %s\n", group_sid_str));
- /* we check if it's our SID before deleting */
- if (!sid_equal(&dom_sid, get_global_sam_sid()))
- return NT_STATUS_NO_SUCH_GROUP;
-
- DEBUG(10, ("lookup on Domain SID\n"));
+ DEBUG(10, ("sid is %s\n", sid_string_static(&group_sid)));
- if(!get_domain_group_from_sid(group_sid, &map))
- return NT_STATUS_NO_SUCH_GROUP;
-
- gid=map.gid;
-
- /* check if group really exists */
- if ( (grp=getgrgid(gid)) == NULL)
+ if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
+ &group_rid)) {
return NT_STATUS_NO_SUCH_GROUP;
+ }
se_priv_copy( &se_rights, &se_add_users );
can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
@@ -4084,26 +4056,21 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
if ( can_add_accounts )
become_root();
- /* delete mapping first */
-
- if ( (ret = pdb_delete_group_mapping_entry(group_sid)) == True ) {
- smb_delete_group( grp->gr_name );
- }
+ r_u->status = pdb_delete_dom_group(p->mem_ctx, group_rid);
if ( can_add_accounts )
unbecome_root();
/******** END SeAddUsers BLOCK *********/
- if ( !ret ) {
- DEBUG(5,("_samr_delete_dom_group: Failed to delete mapping entry for group %s.\n",
- group_sid_str));
- return NT_STATUS_ACCESS_DENIED;
+ if ( !NT_STATUS_IS_OK(r_u->status) ) {
+ DEBUG(5,("_samr_delete_dom_group: Failed to delete mapping "
+ "entry for group %s: %s\n",
+ sid_string_static(&group_sid),
+ nt_errstr(r_u->status)));
+ return r_u->status;
}
- /* don't check that the unix group has been deleted. Work like
- _samr_delet_dom_user() */
-
if (!close_policy_hnd(p, &q_u->group_pol))
return NT_STATUS_OBJECT_NAME_INVALID;
@@ -4131,12 +4098,22 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
+ /* copy the handle to the outgoing reply */
+
+ memcpy( &r_u->pol, &q_u->alias_pol, sizeof(r_u->pol) );
+
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_alias"))) {
return r_u->status;
}
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
+ /* Don't let Windows delete builtin groups */
+
+ if ( sid_check_is_in_builtin( &alias_sid ) ) {
+ return NT_STATUS_SPECIAL_ACCOUNT;
+ }
+
if (!sid_check_is_in_our_domain(&alias_sid))
return NT_STATUS_NO_SUCH_ALIAS;
@@ -4177,15 +4154,11 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
{
DOM_SID dom_sid;
DOM_SID info_sid;
- fstring name;
- fstring sid_string;
- struct group *grp;
+ const char *name;
struct samr_info *info;
uint32 acc_granted;
- gid_t gid;
SE_PRIV se_rights;
BOOL can_add_accounts;
- NTSTATUS result;
DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
@@ -4199,11 +4172,15 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
if (!sid_equal(&dom_sid, get_global_sam_sid()))
return NT_STATUS_ACCESS_DENIED;
- unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
+ name = rpcstr_pull_unistr2_talloc(p->mem_ctx, &q_u->uni_acct_desc);
+ if (name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- /* check if group already exist */
- if ((grp=getgrnam(name)) != NULL)
- return NT_STATUS_GROUP_EXISTS;
+ r_u->status = can_create(p->mem_ctx, name);
+ if (!NT_STATUS_IS_OK(r_u->status)) {
+ return r_u->status;
+ }
se_priv_copy( &se_rights, &se_add_users );
can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
@@ -4215,26 +4192,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
/* check that we successfully create the UNIX group */
- result = NT_STATUS_ACCESS_DENIED;
- if ( (smb_create_group(name, &gid) == 0) && ((grp=getgrgid(gid)) != NULL) ) {
-
- /* so far, so good */
-
- result = NT_STATUS_OK;
-
- r_u->rid = pdb_gid_to_group_rid( grp->gr_gid );
-
- /* add the group to the mapping table */
-
- sid_copy( &info_sid, get_global_sam_sid() );
- sid_append_rid( &info_sid, r_u->rid );
- sid_to_string( sid_string, &info_sid );
-
- /* reset the error code if we fail to add the mapping entry */
-
- if ( !add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL) )
- result = NT_STATUS_ACCESS_DENIED;
- }
+ r_u->status = pdb_create_dom_group(p->mem_ctx, name, &r_u->rid);
if ( can_add_accounts )
unbecome_root();
@@ -4243,13 +4201,14 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
/* check if we should bail out here */
- if ( !NT_STATUS_IS_OK(result) )
- return result;
+ if ( !NT_STATUS_IS_OK(r_u->status) )
+ return r_u->status;
+
+ sid_compose(&info_sid, get_global_sam_sid(), r_u->rid);
if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
return NT_STATUS_NO_MEMORY;
-
/* they created it; let the user do what he wants with it */
info->acc_granted = GENERIC_RIGHTS_GROUP_ALL_ACCESS;
@@ -4296,6 +4255,11 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
se_priv_copy( &se_rights, &se_add_users );
can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
+ result = can_create(p->mem_ctx, name);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
/******** BEGIN SeAddUsers BLOCK *********/
if ( can_add_accounts )
@@ -4309,18 +4273,26 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
/******** END SeAddUsers BLOCK *********/
- if (!NT_STATUS_IS_OK(result))
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("pdb_create_alias failed: %s\n",
+ nt_errstr(result)));
return result;
+ }
sid_copy(&info_sid, get_global_sam_sid());
sid_append_rid(&info_sid, r_u->rid);
- if (!NT_STATUS_IS_OK(sid_to_gid(&info_sid, &gid)))
+ if (!sid_to_gid(&info_sid, &gid)) {
+ DEBUG(10, ("Could not find alias just created\n"));
return NT_STATUS_ACCESS_DENIED;
+ }
/* check if the group has been successfully created */
- if ( getgrgid(gid) == NULL )
+ if ( getgrgid(gid) == NULL ) {
+ DEBUG(10, ("getgrgid(%d) of just created alias failed\n",
+ gid));
return NT_STATUS_ACCESS_DENIED;
+ }
if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -4349,9 +4321,6 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
{
DOM_SID group_sid;
GROUP_MAP map;
- DOM_SID *sids=NULL;
- uid_t *uids;
- int num=0;
GROUP_INFO_CTR *ctr;
uint32 acc_granted;
BOOL ret;
@@ -4374,13 +4343,28 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
return NT_STATUS_NO_MEMORY;
switch (q_u->switch_level) {
- case 1:
+ case 1: {
+ uint32 *members;
+ size_t num_members;
+
ctr->switch_value1 = 1;
- if(!get_memberuids(map.gid, &uids, &num))
- return NT_STATUS_NO_SUCH_GROUP;
- SAFE_FREE(uids);
- init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num);
- SAFE_FREE(sids);
+
+ become_root();
+ r_u->status = pdb_enum_group_members(
+ p->mem_ctx, &group_sid, &members, &num_members);
+ unbecome_root();
+
+ if (!NT_STATUS_IS_OK(r_u->status)) {
+ return r_u->status;
+ }
+
+ init_samr_group_info1(&ctr->group.info1, map.nt_name,
+ map.comment, num_members);
+ break;
+ }
+ case 2:
+ ctr->switch_value1 = 2;
+ init_samr_group_info2(&ctr->group.info2, map.nt_name);
break;
case 3:
ctr->switch_value1 = 3;
@@ -4390,6 +4374,28 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
ctr->switch_value1 = 4;
init_samr_group_info4(&ctr->group.info4, map.comment);
break;
+ case 5: {
+ /*
+ uint32 *members;
+ size_t num_members;
+ */
+
+ ctr->switch_value1 = 5;
+
+ /*
+ become_root();
+ r_u->status = pdb_enum_group_members(
+ p->mem_ctx, &group_sid, &members, &num_members);
+ unbecome_root();
+
+ if (!NT_STATUS_IS_OK(r_u->status)) {
+ return r_u->status;
+ }
+ */
+ init_samr_group_info5(&ctr->group.info5, map.nt_name,
+ map.comment, 0 /* num_members */); /* in w2k3 this is always 0 */
+ break;
+ }
default:
return NT_STATUS_INVALID_INFO_CLASS;
}
@@ -4411,7 +4417,8 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
GROUP_MAP map;
GROUP_INFO_CTR *ctr;
uint32 acc_granted;
- BOOL ret;
+ NTSTATUS ret;
+ BOOL result;
BOOL can_mod_accounts;
DISP_INFO *disp_info = NULL;
@@ -4421,8 +4428,11 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_SET_INFO, "_samr_set_groupinfo"))) {
return r_u->status;
}
-
- if (!get_domain_group_from_sid(group_sid, &map))
+
+ become_root();
+ result = get_domain_group_from_sid(group_sid, &map);
+ unbecome_root();
+ if (!result)
return NT_STATUS_NO_SUCH_GROUP;
ctr=q_u->ctr;
@@ -4452,11 +4462,11 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
/******** End SeAddUsers BLOCK *********/
- if (ret) {
+ if (NT_STATUS_IS_OK(ret)) {
force_flush_samr_cache(disp_info);
}
- return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+ return ret;
}
/*********************************************************************
@@ -4484,7 +4494,30 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
ctr=&q_u->ctr;
+ /* get the current group information */
+
+ if ( !pdb_get_aliasinfo( &group_sid, &info ) ) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
switch (ctr->level) {
+ case 2:
+ /* 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
+ where you can rename builtin groups, just not delete them */
+
+ if ( sid_check_is_in_builtin( &group_sid ) ) {
+ 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, "" );
+ break;
case 3:
if ( ctr->alias.info3.description.string ) {
unistr2_to_ascii( info.acct_desc,
@@ -4684,7 +4717,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p,
{
struct samr_info *info = NULL;
SAM_UNK_CTR *ctr;
- uint32 min_pass_len,pass_hist,flag;
+ uint32 min_pass_len,pass_hist,password_properties;
time_t u_expire, u_min_age;
NTTIME nt_expire, nt_min_age;
@@ -4724,7 +4757,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p,
pass_hist = account_policy_temp;
pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
- flag = account_policy_temp;
+ password_properties = account_policy_temp;
pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
u_expire = account_policy_temp;
@@ -4736,7 +4769,7 @@ NTSTATUS _samr_query_domain_info2(pipes_struct *p,
unix_to_nt_time_abs(&nt_min_age, u_min_age);
init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist,
- flag, nt_expire, nt_min_age);
+ password_properties, nt_expire, nt_min_age);
break;
case 0x02:
become_root();
diff --git a/source/rpc_server/srv_samr_util.c b/source/rpc_server/srv_samr_util.c
index 1d9a8ecd1db..03a726dd926 100644
--- a/source/rpc_server/srv_samr_util.c
+++ b/source/rpc_server/srv_samr_util.c
@@ -36,10 +36,10 @@
((s1) && (s2) && (strcmp((s1), (s2)) != 0))
/*************************************************************
- Copies a SAM_USER_INFO_20 to a SAM_ACCOUNT
+ Copies a SAM_USER_INFO_20 to a struct samu
**************************************************************/
-void copy_id20_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_20 *from)
+void copy_id20_to_sam_passwd(struct samu *to, SAM_USER_INFO_20 *from)
{
const char *old_string;
char *new_string;
@@ -63,10 +63,10 @@ void copy_id20_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_20 *from)
}
/*************************************************************
- Copies a SAM_USER_INFO_21 to a SAM_ACCOUNT
+ Copies a SAM_USER_INFO_21 to a struct samu
**************************************************************/
-void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
+void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from)
{
time_t unix_time, stored_time;
const char *old_string, *new_string;
@@ -312,10 +312,10 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
/*************************************************************
- Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
+ Copies a SAM_USER_INFO_23 to a struct samu
**************************************************************/
-void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
+void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from)
{
time_t unix_time, stored_time;
const char *old_string, *new_string;
diff --git a/source/rpc_server/srv_spoolss.c b/source/rpc_server/srv_spoolss.c
index b3a67dd6cfd..0a43e8ae8ac 100755
--- a/source/rpc_server/srv_spoolss.c
+++ b/source/rpc_server/srv_spoolss.c
@@ -1519,66 +1519,34 @@ static BOOL api_spoolss_deleteprinterdriverex(pipes_struct *p)
return True;
}
-#if 0
-
-/****************************************************************************
-****************************************************************************/
-
-static BOOL api_spoolss_replyopenprinter(pipes_struct *p)
-{
- SPOOL_Q_REPLYOPENPRINTER q_u;
- SPOOL_R_REPLYOPENPRINTER r_u;
- prs_struct *data = &p->in_data.data;
- prs_struct *rdata = &p->out_data.rdata;
-
- ZERO_STRUCT(q_u);
- ZERO_STRUCT(r_u);
-
- if(!spoolss_io_q_replyopenprinter("", &q_u, data, 0)) {
- DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_REPLYOPENPRINTER.\n"));
- return False;
- }
-
- r_u.status = _spoolss_replyopenprinter(p, &q_u, &r_u);
-
- if(!spoolss_io_r_replyopenprinter("", &r_u, rdata, 0)) {
- DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_REPLYOPENPRINTER.\n"));
- return False;
- }
-
- return True;
-}
-
/****************************************************************************
****************************************************************************/
-static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
+static BOOL api_spoolss_xcvdataport(pipes_struct *p)
{
- SPOOL_Q_REPLYCLOSEPRINTER q_u;
- SPOOL_R_REPLYCLOSEPRINTER r_u;
+ SPOOL_Q_XCVDATAPORT q_u;
+ SPOOL_R_XCVDATAPORT r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!spoolss_io_q_replycloseprinter("", &q_u, data, 0)) {
- DEBUG(0,("spoolss_io_q_replycloseprinter: unable to unmarshall SPOOL_Q_REPLYCLOSEPRINTER.\n"));
+ if(!spoolss_io_q_xcvdataport("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_XCVDATAPORT.\n"));
return False;
}
- r_u.status = _spoolss_replycloseprinter(p, &q_u, &r_u);
+ r_u.status = _spoolss_xcvdataport(p, &q_u, &r_u);
- if(!spoolss_io_r_replycloseprinter("", &r_u, rdata, 0)) {
- DEBUG(0,("spoolss_io_r_replycloseprinter: unable to marshall SPOOL_R_REPLYCLOSEPRINTER.\n"));
+ if(!spoolss_io_r_xcvdataport("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_XCVDATAPORT.\n"));
return False;
}
return True;
}
-#endif
-
/*******************************************************************
\pipe\spoolss commands
********************************************************************/
@@ -1636,11 +1604,8 @@ static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
{"SPOOLSS_GETPRINTPROCESSORDIRECTORY",SPOOLSS_GETPRINTPROCESSORDIRECTORY,api_spoolss_getprintprocessordirectory},
{"SPOOLSS_ADDPRINTERDRIVEREX", SPOOLSS_ADDPRINTERDRIVEREX, api_spoolss_addprinterdriverex },
{"SPOOLSS_DELETEPRINTERDRIVEREX", SPOOLSS_DELETEPRINTERDRIVEREX, api_spoolss_deleteprinterdriverex },
-#if 0
- {"SPOOLSS_REPLYOPENPRINTER", SPOOLSS_REPLYOPENPRINTER, api_spoolss_replyopenprinter },
- {"SPOOLSS_REPLYCLOSEPRINTER", SPOOLSS_REPLYCLOSEPRINTER, api_spoolss_replycloseprinter }
-#endif
- };
+ {"SPOOLSS_XCVDATAPORT", SPOOLSS_XCVDATAPORT, api_spoolss_xcvdataport },
+};
void spoolss_get_pipe_fns( struct api_struct **fns, int *n_fns )
{
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index bf7e01ddf3c..aede762ed43 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -86,6 +86,15 @@ 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 {
+ const char *name;
+ WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
+};
+
+
/* translate between internal status numbers and NT status numbers */
static int nt_printj_status(int v)
{
@@ -200,10 +209,10 @@ static void free_printer_entry(void *ptr)
if (Printer->notify.client_connected==True) {
int snum = -1;
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
+ if ( Printer->printer_type == SPLHND_SERVER) {
snum = -1;
srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
- } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
+ } else if (Printer->printer_type == SPLHND_PRINTER) {
snum = print_queue_snum(Printer->sharename);
if (snum != -1)
srv_spoolss_replycloseprinter(snum,
@@ -395,11 +404,11 @@ static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
}
switch (Printer->printer_type) {
- case PRINTER_HANDLE_IS_PRINTER:
+ case SPLHND_PRINTER:
DEBUG(4,("short name:%s\n", Printer->sharename));
*number = print_queue_snum(Printer->sharename);
return (*number != -1);
- case PRINTER_HANDLE_IS_PRINTSERVER:
+ case SPLHND_SERVER:
return False;
default:
return False;
@@ -423,19 +432,22 @@ static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename
/* it's a print server */
if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
DEBUGADD(4,("Printer is a print server\n"));
- Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
+ Printer->printer_type = SPLHND_SERVER;
}
- /* it's a printer */
+ /* it's a printer (set_printer_hnd_name() will handle port monitors */
else {
DEBUGADD(4,("Printer is a printer\n"));
- Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
+ Printer->printer_type = SPLHND_PRINTER;
}
return True;
}
/****************************************************************************
- Set printer handle name.
+ Set printer handle name.. Accept names like \\server, \\server\printer,
+ \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
+ the MSDN docs regarding OpenPrinter() for details on the XcvData() and
+ XcvDataPort() interface.
****************************************************************************/
static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
@@ -470,13 +482,26 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
fstrcpy( Printer->servername, servername );
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
+ if ( Printer->printer_type == SPLHND_SERVER )
return True;
- if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type != SPLHND_PRINTER )
return False;
DEBUGADD(5, ("searching for [%s]\n", aprinter ));
+
+ /* check for the Port Monitor Interface */
+
+ if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
+ Printer->printer_type = SPLHND_PORTMON_TCP;
+ fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
+ found = True;
+ }
+ else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
+ Printer->printer_type = SPLHND_PORTMON_LOCAL;
+ fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
+ found = True;
+ }
/* Search all sharenames first as this is easier than pulling
the printer_info_2 off of disk. Don't use find_service() since
@@ -698,14 +723,21 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
+ prs_mem_free(&ps);
return;
}
- if (!spoolss_io_system_time("", &ps, 0, &systime))
+ if (!spoolss_io_system_time("", &ps, 0, &systime)) {
+ prs_mem_free(&ps);
return;
+ }
data->notify_data.data.length = prs_offset(&ps);
data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
+ if (!data->notify_data.data.string) {
+ prs_mem_free(&ps);
+ return;
+ }
prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
@@ -943,7 +975,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
/* For this printer? Print servers always receive
notifications. */
- if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
+ if ( ( p->printer_type == SPLHND_PRINTER ) &&
( !strequal(msg_group->printername, p->sharename) ) )
continue;
@@ -952,6 +984,10 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
/* allocate the max entries possible */
data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
+ if (!data) {
+ return;
+ }
+
ZERO_STRUCTP(data);
/* build the array of change notifications */
@@ -985,7 +1021,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
* --jerry
*/
- if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
+ if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
id = 0;
else
id = msg->id;
@@ -1249,7 +1285,7 @@ void update_monitored_printq_cache( void )
client_connected == True */
while ( printer )
{
- if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
+ if ( (printer->printer_type == SPLHND_PRINTER)
&& printer->notify.client_connected )
{
snum = print_queue_snum(printer->sharename);
@@ -1368,6 +1404,9 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
len = unistrlen(devmode->devicename.buffer);
if (len != -1) {
d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
+ if (!d->devicename.buffer) {
+ return NULL;
+ }
if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
return NULL;
}
@@ -1376,12 +1415,17 @@ static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
len = unistrlen(devmode->formname.buffer);
if (len != -1) {
d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
+ if (!d->devicename.buffer) {
+ return NULL;
+ }
if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
return NULL;
}
d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
-
+ if (!d->dev_private) {
+ return NULL;
+ }
return d;
}
@@ -1473,60 +1517,6 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R
}
/********************************************************************
- * spoolss_open_printer
- *
- * If the openprinterex rpc call contains a devmode,
- * it's a per-user one. This per-user devmode is derivated
- * from the global devmode. Openprinterex() contains a per-user
- * devmode for when you do EMF printing and spooling.
- * In the EMF case, the NT workstation is only doing half the job
- * of rendering the page. The other half is done by running the printer
- * driver on the server.
- * The EMF file doesn't contain the page description (paper size, orientation, ...).
- * The EMF file only contains what is to be printed on the page.
- * So in order for the server to know how to print, the NT client sends
- * a devicemode attached to the openprinterex call.
- * But this devicemode is short lived, it's only valid for the current print job.
- *
- * If Samba would have supported EMF spooling, this devicemode would
- * have been attached to the handle, to sent it to the driver to correctly
- * rasterize the EMF file.
- *
- * As Samba only supports RAW spooling, we only receive a ready-to-print file,
- * we just act as a pass-thru between windows and the printer.
- *
- * In order to know that Samba supports only RAW spooling, NT has to call
- * getprinter() at level 2 (attribute field) or NT has to call startdoc()
- * and until NT sends a RAW job, we refuse it.
- *
- * But to call getprinter() or startdoc(), you first need a valid handle,
- * and to get an handle you have to call openprintex(). Hence why you have
- * a devicemode in the openprinterex() call.
- *
- *
- * Differences between NT4 and NT 2000.
- * NT4:
- * ---
- * On NT4, you only have a global devicemode. This global devicemode can be changed
- * by the administrator (or by a user with enough privs). Everytime a user
- * wants to print, the devicemode is resetted to the default. In Word, everytime
- * you print, the printer's characteristics are always reset to the global devicemode.
- *
- * NT 2000:
- * -------
- * In W2K, there is the notion of per-user devicemode. The first time you use
- * a printer, a per-user devicemode is build from the global devicemode.
- * If you change your per-user devicemode, it is saved in the registry, under the
- * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
- * printer preferences available.
- *
- * To change the per-user devicemode: it's the "Printing Preferences ..." button
- * on the General Tab of the printer properties windows.
- *
- * To change the global devicemode: it's the "Printing Defaults..." button
- * on the Advanced Tab of the printer properties window.
- *
- * JFM.
********************************************************************/
WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
@@ -1581,10 +1571,16 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
* Second case: the user is opening a printer:
* NT doesn't let us connect to a printer if the connecting user
* doesn't have print permission.
+ *
+ * Third case: user is opening a Port Monitor
+ * access checks same as opening a handle to the print server.
*/
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ switch (Printer->printer_type )
{
+ case SPLHND_SERVER:
+ case SPLHND_PORTMON_TCP:
+ case SPLHND_PORTMON_LOCAL:
/* Printserver handles use global struct... */
snum = -1;
@@ -1620,10 +1616,13 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
and not a printer admin, then fail */
- if ( user.uid != 0
- && !user_has_privileges( user.nt_user_token, &se_printop )
- && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
- {
+ if ((user.ut.uid != 0) &&
+ !user_has_privileges(user.nt_user_token,
+ &se_printop ) &&
+ !token_contains_name_in_list(
+ uidtoname(user.ut.uid), NULL,
+ user.nt_user_token,
+ lp_printer_admin(snum))) {
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
}
@@ -1639,10 +1638,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
/* We fall through to return WERR_OK */
-
- }
- else
- {
+ break;
+
+ case SPLHND_PRINTER:
/* NT doesn't let us connect to a printer if the connecting user
doesn't have print permission. */
@@ -1676,7 +1674,10 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
return WERR_ACCESS_DENIED;
}
- if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
+ if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
+ snum) ||
+ !print_access_check(&user, snum,
+ printer_default->access_required)) {
DEBUG(3, ("access DENIED for printer open\n"));
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
@@ -1696,6 +1697,11 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
+ break;
+
+ default:
+ /* sanity check to prevent programmer error */
+ return WERR_BADFID;
}
Printer->access_granted = printer_default->access_required;
@@ -1705,7 +1711,7 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
* save it here in case we get a job submission on this handle
*/
- if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
+ if ( (Printer->printer_type != SPLHND_SERVER)
&& q_u->printer_default.devmode_cont.devmode_ptr )
{
convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
@@ -1869,7 +1875,7 @@ static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handl
return WERR_BADFID;
Printer->document_started=False;
- print_job_end(snum, Printer->jobid,True);
+ print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
/* error codes unhandled so far ... */
return WERR_OK;
@@ -1974,9 +1980,10 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
and not a printer admin, then fail */
- if ( (user.uid != 0)
+ if ( (user.ut.uid != 0)
&& !user_has_privileges(user.nt_user_token, &se_printop )
- && !user_in_list(uidtoname(user.uid), lp_printer_admin(-1), user.groups, user.ngroups) )
+ && !token_contains_name_in_list( uidtoname(user.ut.uid),
+ NULL, user.nt_user_token, lp_printer_admin(-1)) )
{
return WERR_ACCESS_DENIED;
}
@@ -2071,9 +2078,10 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
and not a printer admin, then fail */
- if ( (user.uid != 0)
+ if ( (user.ut.uid != 0)
&& !user_has_privileges(user.nt_user_token, &se_printop )
- && !user_in_list(uidtoname(user.uid), lp_printer_admin(-1), user.groups, user.ngroups) )
+ && !token_contains_name_in_list( uidtoname(user.ut.uid),
+ NULL, user.nt_user_token, lp_printer_admin(-1)) )
{
return WERR_ACCESS_DENIED;
}
@@ -2457,7 +2465,7 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
unistr2_to_ascii(value, valuename, sizeof(value)-1);
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
+ if ( Printer->printer_type == SPLHND_SERVER )
status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
else
{
@@ -2676,9 +2684,9 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE
/* Connect to the client machine and send a ReplyOpenPrinter */
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ if ( Printer->printer_type == SPLHND_SERVER)
snum = -1;
- else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
+ else if ( (Printer->printer_type == SPLHND_PRINTER) &&
!get_printer_snum(p, handle, &snum) )
return WERR_BADFID;
@@ -3452,25 +3460,22 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
{
int i=0;
- for (i = 0; i < sizeof(notify_info_data_table); i++)
- {
+ for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
if ( (notify_info_data_table[i].type == type)
- && (notify_info_data_table[i].field == field) )
- {
- switch(notify_info_data_table[i].size)
- {
- case NOTIFY_ONE_VALUE:
- case NOTIFY_TWO_VALUE:
- return 1;
- case NOTIFY_STRING:
- return 2;
-
- /* The only pointer notify data I have seen on
- the wire is the submitted time and this has
- the notify size set to 4. -tpot */
-
- case NOTIFY_POINTER:
- return 4;
+ && (notify_info_data_table[i].field == field) ) {
+ switch(notify_info_data_table[i].size) {
+ case NOTIFY_ONE_VALUE:
+ case NOTIFY_TWO_VALUE:
+ return 1;
+ case NOTIFY_STRING:
+ return 2;
+
+ /* The only pointer notify data I have seen on
+ the wire is the submitted time and this has
+ the notify size set to 4. -tpot */
+
+ case NOTIFY_POINTER:
+ return 4;
case NOTIFY_SECDESC:
return 5;
@@ -3487,23 +3492,23 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
Return the type of notify_info_data.
********************************************************************/
-static int type_of_notify_info_data(uint16 type, uint16 field)
+static uint32 type_of_notify_info_data(uint16 type, uint16 field)
{
- int i=0;
+ uint32 i=0;
- for (i = 0; i < sizeof(notify_info_data_table); i++) {
+ for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
if (notify_info_data_table[i].type == type &&
notify_info_data_table[i].field == field)
return notify_info_data_table[i].size;
}
- return False;
+ return 0;
}
/****************************************************************************
****************************************************************************/
-static int search_notify(uint16 type, uint16 field, int *value)
+static BOOL search_notify(uint16 type, uint16 field, int *value)
{
int i;
@@ -3532,10 +3537,8 @@ void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16
info_data->enc_type = type_of_notify_info_data(type, field);
info_data->id = id;
-
}
-
/*******************************************************************
*
* fill a notify_info struct with info asked
@@ -3551,7 +3554,7 @@ static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
uint16 type;
uint16 field;
- SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
+ SPOOL_NOTIFY_INFO_DATA *current_data;
NT_PRINTER_INFO_LEVEL *printer = NULL;
print_queue_struct *queue=NULL;
@@ -3572,11 +3575,10 @@ static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
if (!search_notify(type, field, &j) )
continue;
- if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+ if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
return False;
- } else
- info->data = tid;
+ }
current_data = &info->data[info->count];
@@ -3612,7 +3614,7 @@ static BOOL construct_notify_jobs_info(print_queue_struct *queue,
uint16 type;
uint16 field;
- SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
+ SPOOL_NOTIFY_INFO_DATA *current_data;
DEBUG(4,("construct_notify_jobs_info\n"));
@@ -3628,11 +3630,10 @@ static BOOL construct_notify_jobs_info(print_queue_struct *queue,
if (!search_notify(type, field, &j) )
continue;
- if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+ if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
return False;
}
- else info->data = tid;
current_data=&(info->data[info->count]);
@@ -3868,11 +3869,11 @@ WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCN
/* just ignore the SPOOL_NOTIFY_OPTION */
switch (Printer->printer_type) {
- case PRINTER_HANDLE_IS_PRINTSERVER:
+ case SPLHND_SERVER:
result = printserver_notify_info(p, handle, info, p->mem_ctx);
break;
- case PRINTER_HANDLE_IS_PRINTER:
+ case SPLHND_PRINTER:
result = printer_notify_info(p, handle, info, p->mem_ctx);
break;
}
@@ -4307,7 +4308,7 @@ static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32
int snum;
int i;
int n_services=lp_numservices();
- PRINTER_INFO_1 *tp, *printers=NULL;
+ PRINTER_INFO_1 *printers=NULL;
PRINTER_INFO_1 current_prt;
WERROR result = WERR_OK;
@@ -4318,13 +4319,11 @@ static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32
DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
- if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
+ if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
- SAFE_FREE(printers);
*returned=0;
return WERR_NOMEM;
}
- else printers = tp;
DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
@@ -4495,26 +4494,25 @@ static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint3
int snum;
int i;
int n_services=lp_numservices();
- PRINTER_INFO_2 *tp, *printers=NULL;
+ PRINTER_INFO_2 *printers=NULL;
PRINTER_INFO_2 current_prt;
WERROR result = WERR_OK;
+ *returned = 0;
+
for (snum=0; snum<n_services; snum++) {
if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
- if (construct_printer_info_2(NULL, &current_prt, snum))
- {
- if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
+ if (construct_printer_info_2(NULL, &current_prt, snum)) {
+ if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
- SAFE_FREE(printers);
*returned = 0;
return WERR_NOMEM;
}
- DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
+ DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
- printers = tp;
memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
(*returned)++;
@@ -4642,11 +4640,13 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_enumprinters\n"));
*needed=0;
@@ -4837,8 +4837,10 @@ static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER
if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
return WERR_NOMEM;
- if (!construct_printer_info_4(print_hnd, printer, snum))
+ if (!construct_printer_info_4(print_hnd, printer, snum)) {
+ SAFE_FREE(printer);
return WERR_NOMEM;
+ }
/* check the required size. */
*needed += spoolss_size_printer_info_4(printer);
@@ -4874,8 +4876,10 @@ static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER
if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
return WERR_NOMEM;
- if (!construct_printer_info_5(print_hnd, printer, snum))
+ if (!construct_printer_info_5(print_hnd, printer, snum)) {
+ free_printer_info_5(printer);
return WERR_NOMEM;
+ }
/* check the required size. */
*needed += spoolss_size_printer_info_5(printer);
@@ -4951,11 +4955,13 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
*needed=0;
if (!get_printer_snum(p, handle, &snum))
@@ -5085,7 +5091,6 @@ static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const c
int j=0;
const char *v;
pstring line;
- uint16 *tuary;
DEBUG(6,("init_unistr_array\n"));
*uni_array=NULL;
@@ -5113,12 +5118,11 @@ static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const c
/* add one extra unit16 for the second terminating NULL */
- if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
+ if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
DEBUG(2,("init_unistr_array: Realloc error\n" ));
return 0;
- } else
- *uni_array = tuary;
-
+ }
+
if ( !strlen(v) )
break;
@@ -5550,11 +5554,13 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_getprinterdriver2\n"));
if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
@@ -5900,6 +5906,10 @@ static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
}
new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
+ if (!new_secdesc_ctr) {
+ result = WERR_NOMEM;
+ goto done;
+ }
if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
result = WERR_OK;
@@ -5967,6 +5977,52 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
/****************************************************************************
****************************************************************************/
+WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
+{
+ char *cmd = lp_addport_cmd();
+ pstring command;
+ int ret;
+ int fd;
+ SE_PRIV se_printop = SE_PRINT_OPERATOR;
+ BOOL is_print_op = False;
+
+ if ( !*cmd ) {
+ return WERR_ACCESS_DENIED;
+ }
+
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
+
+ if ( token )
+ is_print_op = user_has_privileges( token, &se_printop );
+
+ DEBUG(10,("Running [%s]\n", command));
+
+ /********* BEGIN SePrintOperatorPrivilege **********/
+
+ if ( is_print_op )
+ become_root();
+
+ ret = smbrun(command, &fd);
+
+ if ( is_print_op )
+ unbecome_root();
+
+ /********* END SePrintOperatorPrivilege **********/
+
+ DEBUGADD(10,("returned [%d]\n", ret));
+
+ if ( ret != 0 ) {
+ if (fd != -1)
+ close(fd);
+ return WERR_ACCESS_DENIED;
+ }
+
+ return WERR_OK;
+}
+
+/****************************************************************************
+****************************************************************************/
+
BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
{
char *cmd = lp_addprinter_cmd();
@@ -6019,7 +6075,7 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
numlines = 0;
/* Get lines and convert them back to dos-codepage */
- qlines = fd_lines_load(fd, &numlines);
+ qlines = fd_lines_load(fd, &numlines, 0);
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
close(fd);
@@ -6036,6 +6092,7 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
return True;
}
+
/********************************************************************
* Called by spoolss_api_setprinter
* when updating a printer description.
@@ -6313,9 +6370,9 @@ WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
if (Printer->notify.client_connected==True) {
int snum = -1;
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ if ( Printer->printer_type == SPLHND_SERVER)
snum = -1;
- else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
+ else if ( (Printer->printer_type == SPLHND_PRINTER) &&
!get_printer_snum(p, handle, &snum) )
return WERR_BADFID;
@@ -6340,8 +6397,11 @@ WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u
{
/* that's an [in out] buffer */
- if ( q_u->buffer )
- rpcbuf_move(q_u->buffer, &r_u->buffer);
+ if (!q_u->buffer && (q_u->offered!=0)) {
+ return WERR_INVALID_PARAM;
+ }
+
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
r_u->needed = 0;
return WERR_INVALID_PARAM; /* this is what a NT server
@@ -6552,11 +6612,13 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_enumjobs\n"));
*needed=0;
@@ -6663,7 +6725,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
uint32 version;
fstring *list = NULL;
NT_PRINTER_DRIVER_INFO_LEVEL driver;
- DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
+ DRIVER_INFO_1 *driver_info_1=NULL;
WERROR result = WERR_OK;
*returned=0;
@@ -6673,17 +6735,17 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
- if(ndrivers == -1)
+ if(ndrivers == -1) {
+ SAFE_FREE(driver_info_1);
return WERR_NOMEM;
+ }
if(ndrivers != 0) {
- if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
+ if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
- SAFE_FREE(driver_info_1);
SAFE_FREE(list);
return WERR_NOMEM;
}
- else driver_info_1 = tdi1;
}
for (i=0; i<ndrivers; i++) {
@@ -6694,6 +6756,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
architecture, version);
if (!W_ERROR_IS_OK(status)) {
SAFE_FREE(list);
+ SAFE_FREE(driver_info_1);
return status;
}
fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
@@ -6746,7 +6809,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
uint32 version;
fstring *list = NULL;
NT_PRINTER_DRIVER_INFO_LEVEL driver;
- DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
+ DRIVER_INFO_2 *driver_info_2=NULL;
WERROR result = WERR_OK;
*returned=0;
@@ -6756,17 +6819,17 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
- if(ndrivers == -1)
+ if(ndrivers == -1) {
+ SAFE_FREE(driver_info_2);
return WERR_NOMEM;
+ }
if(ndrivers != 0) {
- if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
+ if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
- SAFE_FREE(driver_info_2);
SAFE_FREE(list);
return WERR_NOMEM;
}
- else driver_info_2 = tdi2;
}
for (i=0; i<ndrivers; i++) {
@@ -6778,6 +6841,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
architecture, version);
if (!W_ERROR_IS_OK(status)) {
SAFE_FREE(list);
+ SAFE_FREE(driver_info_2);
return status;
}
fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
@@ -6829,8 +6893,8 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
int ndrivers;
uint32 version;
fstring *list = NULL;
+ DRIVER_INFO_3 *driver_info_3=NULL;
NT_PRINTER_DRIVER_INFO_LEVEL driver;
- DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
WERROR result = WERR_OK;
*returned=0;
@@ -6840,17 +6904,17 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
- if(ndrivers == -1)
+ if(ndrivers == -1) {
+ SAFE_FREE(driver_info_3);
return WERR_NOMEM;
+ }
if(ndrivers != 0) {
- if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
+ if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
- SAFE_FREE(driver_info_3);
SAFE_FREE(list);
return WERR_NOMEM;
}
- else driver_info_3 = tdi3;
}
for (i=0; i<ndrivers; i++) {
@@ -6862,6 +6926,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
architecture, version);
if (!W_ERROR_IS_OK(status)) {
SAFE_FREE(list);
+ SAFE_FREE(driver_info_3);
return status;
}
fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
@@ -6895,8 +6960,9 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
}
out:
- for (i=0; i<*returned; i++)
+ for (i=0; i<*returned; i++) {
SAFE_FREE(driver_info_3[i].dependentfiles);
+ }
SAFE_FREE(driver_info_3);
@@ -6923,11 +6989,13 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_enumprinterdrivers\n"));
*needed = 0;
@@ -6986,11 +7054,13 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0) ) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_enumforms\n"));
DEBUGADD(5,("Offered buffer size [%d]\n", offered));
DEBUGADD(5,("Info level [%d]\n", level));
@@ -7001,12 +7071,17 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
*numofforms += numbuiltinforms;
- if (*numofforms == 0)
+ if (*numofforms == 0) {
+ SAFE_FREE(builtinlist);
+ SAFE_FREE(list);
return WERR_NO_MORE_ITEMS;
+ }
switch (level) {
case 1:
if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
+ SAFE_FREE(builtinlist);
+ SAFE_FREE(list);
*numofforms=0;
return WERR_NOMEM;
}
@@ -7069,7 +7144,6 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
SAFE_FREE(builtinlist);
return WERR_UNKNOWN_LEVEL;
}
-
}
/****************************************************************************
@@ -7093,11 +7167,13 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
DEBUG(4,("_spoolss_getform\n"));
@@ -7167,13 +7243,15 @@ static void fill_port_1(PORT_INFO_1 *port, const char *name)
}
/****************************************************************************
+ TODO: This probably needs distinguish between TCP/IP and Local ports
+ somehow.
****************************************************************************/
static void fill_port_2(PORT_INFO_2 *port, const char *name)
{
init_unistr(&port->port_name, name);
init_unistr(&port->monitor_name, "Local Monitor");
- init_unistr(&port->description, "Local Port");
+ init_unistr(&port->description, SPL_LOCAL_PORT );
port->port_type=PORT_TYPE_WRITE;
port->reserved=0x0;
}
@@ -7192,6 +7270,8 @@ WERROR enumports_hook( int *count, char ***lines )
int ret;
int fd;
+ *count = 0;
+ *lines = NULL;
/* if no hook then just fill in the default port */
@@ -7210,14 +7290,14 @@ WERROR enumports_hook( int *count, char ***lines )
ret = smbrun(command, &fd);
DEBUG(10,("Returned [%d]\n", ret));
if (ret != 0) {
- if (fd != -1)
+ if (fd != -1) {
close(fd);
-
+ }
return WERR_ACCESS_DENIED;
}
numlines = 0;
- qlines = fd_lines_load(fd, &numlines);
+ qlines = fd_lines_load(fd, &numlines, 0);
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
close(fd);
}
@@ -7237,11 +7317,14 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
PORT_INFO_1 *ports=NULL;
int i=0;
WERROR result = WERR_OK;
- char **qlines;
- int numlines;
+ char **qlines = NULL;
+ int numlines = 0;
- if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
+ result = enumports_hook( &numlines, &qlines );
+ if (!W_ERROR_IS_OK(result)) {
+ file_lines_free(qlines);
return result;
+ }
if(numlines) {
if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
@@ -7255,9 +7338,8 @@ static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *need
DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
fill_port_1(&ports[i], qlines[i]);
}
-
- file_lines_free(qlines);
}
+ file_lines_free(qlines);
*returned = numlines;
@@ -7301,12 +7383,14 @@ static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *need
PORT_INFO_2 *ports=NULL;
int i=0;
WERROR result = WERR_OK;
- char **qlines;
- int numlines;
+ char **qlines = NULL;
+ int numlines = 0;
- if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
+ result = enumports_hook( &numlines, &qlines );
+ if ( !W_ERROR_IS_OK(result)) {
+ file_lines_free(qlines);
return result;
-
+ }
if(numlines) {
if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
@@ -7318,10 +7402,10 @@ static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *need
DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
fill_port_2(&(ports[i]), qlines[i]);
}
-
- file_lines_free(qlines);
}
+ file_lines_free(qlines);
+
*returned = numlines;
/* check the required size. */
@@ -7369,11 +7453,13 @@ WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUM
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_enumports\n"));
*returned=0;
@@ -7576,12 +7662,12 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
case 3:
fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
- driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
+ driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
break;
case 6:
fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
- driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
+ driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
break;
}
/* END_ADMIN_LOG */
@@ -7777,11 +7863,13 @@ WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRI
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
*needed=0;
@@ -7948,7 +8036,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
goto done;
}
- *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
+ *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
/* type */
@@ -7997,7 +8085,7 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
return WERR_BADFID;
}
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
+ if ( Printer->printer_type == SPLHND_SERVER ) {
DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
return WERR_INVALID_PARAM;
}
@@ -8154,7 +8242,7 @@ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM
/* forms can be added on printer of on the print server handle */
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type == SPLHND_PRINTER )
{
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
@@ -8190,7 +8278,7 @@ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM
* ChangeID must always be set if this is a printer
*/
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type == SPLHND_PRINTER )
status = mod_a_printer(printer, 2);
done:
@@ -8225,7 +8313,7 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE
/* forms can be deleted on printer of on the print server handle */
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type == SPLHND_PRINTER )
{
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
@@ -8257,7 +8345,7 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE
* ChangeID must always be set if this is a printer
*/
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type == SPLHND_PRINTER )
status = mod_a_printer(printer, 2);
done:
@@ -8293,7 +8381,7 @@ WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *
/* forms can be modified on printer of on the print server handle */
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type == SPLHND_PRINTER )
{
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
@@ -8323,7 +8411,7 @@ WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *
* ChangeID must always be set if this is a printer
*/
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ if ( Printer->printer_type == SPLHND_PRINTER )
status = mod_a_printer(printer, 2);
@@ -8387,11 +8475,13 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(5,("spoolss_enumprintprocessors\n"));
/*
@@ -8464,11 +8554,13 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
*returned=0;
@@ -8488,18 +8580,22 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
- PRINTMONITOR_1 *info_1=NULL;
+ PRINTMONITOR_1 *info_1;
WERROR result = WERR_OK;
+ int i;
- if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
+ if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
return WERR_NOMEM;
- (*returned) = 0x1;
+ *returned = 2;
- init_unistr(&info_1->name, "Local Port");
-
- *needed += spoolss_size_printmonitor_info_1(info_1);
+ init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
+ init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
+ for ( i=0; i<*returned; i++ ) {
+ *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
+ }
+
if (*needed > offered) {
result = WERR_INSUFFICIENT_BUFFER;
goto out;
@@ -8510,7 +8606,9 @@ static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint
goto out;
}
- smb_io_printmonitor_info_1("", buffer, info_1, 0);
+ for ( i=0; i<*returned; i++ ) {
+ smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
+ }
out:
SAFE_FREE(info_1);
@@ -8527,20 +8625,27 @@ out:
static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
- PRINTMONITOR_2 *info_2=NULL;
+ PRINTMONITOR_2 *info_2;
WERROR result = WERR_OK;
+ int i;
- if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
+ if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
return WERR_NOMEM;
- (*returned) = 0x1;
+ *returned = 2;
- init_unistr(&info_2->name, "Local Port");
- init_unistr(&info_2->environment, "Windows NT X86");
- init_unistr(&info_2->dll_name, "localmon.dll");
-
- *needed += spoolss_size_printmonitor_info_2(info_2);
+ init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
+ init_unistr( &(info_2[0].environment), "Windows NT X86" );
+ init_unistr( &(info_2[0].dll_name), "localmon.dll" );
+
+ init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
+ init_unistr( &(info_2[1].environment), "Windows NT X86" );
+ init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
+ for ( i=0; i<*returned; i++ ) {
+ *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
+ }
+
if (*needed > offered) {
result = WERR_INSUFFICIENT_BUFFER;
goto out;
@@ -8551,7 +8656,9 @@ static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint
goto out;
}
- smb_io_printmonitor_info_2("", buffer, info_2, 0);
+ for ( i=0; i<*returned; i++ ) {
+ smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
+ }
out:
SAFE_FREE(info_2);
@@ -8575,11 +8682,13 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(5,("spoolss_enumprintmonitors\n"));
/*
@@ -8749,11 +8858,13 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(5,("spoolss_getjob\n"));
*needed = 0;
@@ -8835,7 +8946,7 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
/* Is the handle to a printer or to the server? */
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
+ if (Printer->printer_type == SPLHND_SERVER) {
DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
status = WERR_INVALID_PARAM;
goto done;
@@ -8922,7 +9033,7 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
return WERR_BADFID;
}
- if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
+ if ( Printer->printer_type == SPLHND_SERVER ) {
DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
return WERR_INVALID_PARAM;
}
@@ -9369,11 +9480,13 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
/* that's an [in out] buffer */
- if ( q_u->buffer ) {
- rpcbuf_move(q_u->buffer, &r_u->buffer);
- buffer = r_u->buffer;
+ if (!q_u->buffer && (offered!=0)) {
+ return WERR_INVALID_PARAM;
}
+ rpcbuf_move(q_u->buffer, &r_u->buffer);
+ buffer = r_u->buffer;
+
DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
*needed=0;
@@ -9390,23 +9503,191 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
return result;
}
-#if 0
+/*******************************************************************
+ Streams the monitor UI DLL name in UNICODE
+*******************************************************************/
-WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
- SPOOL_R_REPLYOPENPRINTER *r_u)
+static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
+ RPC_BUFFER *out, uint32 *needed )
{
- DEBUG(5,("_spoolss_replyopenprinter\n"));
+ const char *dllname = "tcpmonui.dll";
+
+ *needed = (strlen(dllname)+1) * 2;
+
+ if ( rpcbuf_get_size(out) < *needed ) {
+ return WERR_INSUFFICIENT_BUFFER;
+ }
+
+ if ( !make_monitorui_buf( out, dllname ) ) {
+ return WERR_NOMEM;
+ }
+
+ return WERR_OK;
+}
- DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
+/*******************************************************************
+ Create a new TCP/IP port
+*******************************************************************/
- return WERR_OK;
+static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
+ RPC_BUFFER *out, uint32 *needed )
+{
+ NT_PORT_DATA_1 port1;
+ pstring device_uri;
+
+ ZERO_STRUCT( port1 );
+
+ /* convert to our internal port data structure */
+
+ if ( !convert_port_data_1( &port1, in ) ) {
+ return WERR_NOMEM;
+ }
+
+ /* create the device URI and call the add_port_hook() */
+
+ switch ( port1.protocol ) {
+ case PORT_PROTOCOL_DIRECT:
+ pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
+ break;
+
+ case PORT_PROTOCOL_LPR:
+ pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
+ break;
+
+ default:
+ return WERR_UNKNOWN_PORT;
+ }
+
+ return add_port_hook( token, port1.name, device_uri );
}
-WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
- SPOOL_R_REPLYCLOSEPRINTER *r_u)
+/*******************************************************************
+*******************************************************************/
+
+struct xcv_api_table xcvtcp_cmds[] = {
+ { "MonitorUI", xcvtcp_monitorui },
+ { "AddPort", xcvtcp_addport},
+ { NULL, NULL }
+};
+
+static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
+ RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
+ uint32 *needed )
{
- DEBUG(5,("_spoolss_replycloseprinter\n"));
+ int i;
+
+ DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
+
+ for ( i=0; xcvtcp_cmds[i].name; i++ ) {
+ if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
+ return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
+ }
+
+ return WERR_BADFUNC;
+}
+
+/*******************************************************************
+*******************************************************************/
+#if 0 /* don't support management using the "Local Port" monitor */
+
+static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
+ RPC_BUFFER *out, uint32 *needed )
+{
+ const char *dllname = "localui.dll";
+
+ *needed = (strlen(dllname)+1) * 2;
+
+ if ( rpcbuf_get_size(out) < *needed ) {
+ return WERR_INSUFFICIENT_BUFFER;
+ }
+
+ if ( !make_monitorui_buf( out, dllname )) {
+ return WERR_NOMEM;
+ }
+
return WERR_OK;
}
+/*******************************************************************
+*******************************************************************/
+
+struct xcv_api_table xcvlocal_cmds[] = {
+ { "MonitorUI", xcvlocal_monitorui },
+ { NULL, NULL }
+};
+#else
+struct xcv_api_table xcvlocal_cmds[] = {
+ { NULL, NULL }
+};
#endif
+
+
+
+/*******************************************************************
+*******************************************************************/
+
+static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
+ RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
+ uint32 *needed )
+{
+ int i;
+
+ DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
+
+ for ( i=0; xcvlocal_cmds[i].name; i++ ) {
+ if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
+ return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
+ }
+ return WERR_BADFUNC;
+}
+
+/*******************************************************************
+*******************************************************************/
+
+WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
+{
+ Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
+ fstring command;
+
+ if (!Printer) {
+ DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
+ return WERR_BADFID;
+ }
+
+ /* Has to be a handle to the TCP/IP port monitor */
+
+ if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
+ DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
+ return WERR_BADFID;
+ }
+
+ /* requires administrative access to the server */
+
+ if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
+ DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
+ return WERR_ACCESS_DENIED;
+ }
+
+ /* Get the command name. There's numerous commands supported by the
+ TCPMON interface. */
+
+ rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
+ q_u->dataname.uni_str_len*2, 0);
+
+ /* Allocate the outgoing buffer */
+
+ rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
+
+ switch ( Printer->printer_type ) {
+ case SPLHND_PORTMON_TCP:
+ return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
+ &q_u->indata, &r_u->outdata, &r_u->needed );
+ case SPLHND_PORTMON_LOCAL:
+ return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
+ &q_u->indata, &r_u->outdata, &r_u->needed );
+ }
+
+ return WERR_INVALID_PRINT_MONITOR;
+}
+
+
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index 65e0504e678..f279c98c312 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -29,26 +29,6 @@ extern struct generic_mapping file_generic_mapping;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
-#define INVALID_SHARENAME_CHARS "<>*?|/\\+=;:\","
-
-/********************************************************************
- Check a string for any occurrences of a specified list of invalid
- characters.
-********************************************************************/
-
-static BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
-{
- int i;
-
- for ( i=0; i<max_len && name[i]; i++ ) {
- /* fail if strchr_m() finds one of the invalid characters */
- if ( name[i] && strchr_m( invalid_chars, name[i] ) )
- return False;
- }
-
- return True;
-}
-
/*******************************************************************
Utility function to get the 'type' of a share from an snum.
********************************************************************/
@@ -132,189 +112,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
}
/*******************************************************************
- 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)
-{
- DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
- reload_services(False);
-}
-
-/*******************************************************************
- Create the share security tdb.
- ********************************************************************/
-
-static TDB_CONTEXT *share_tdb; /* used for share security descriptors */
-#define SHARE_DATABASE_VERSION_V1 1
-#define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */
-
-BOOL share_info_db_init(void)
-{
- static pid_t local_pid;
- const char *vstring = "INFO/version";
- int32 vers_id;
-
- if (share_tdb && local_pid == sys_getpid())
- return True;
- share_tdb = tdb_open_log(lock_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
- if (!share_tdb) {
- DEBUG(0,("Failed to open share info database %s (%s)\n",
- lock_path("share_info.tdb"), strerror(errno) ));
- return False;
- }
-
- local_pid = sys_getpid();
-
- /* handle a Samba upgrade */
- tdb_lock_bystring(share_tdb, vstring, 0);
-
- /* Cope with byte-reversed older versions of the db. */
- vers_id = tdb_fetch_int32(share_tdb, vstring);
- if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) {
- /* Written on a bigendian machine with old fetch_int code. Save as le. */
- tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
- vers_id = SHARE_DATABASE_VERSION_V2;
- }
-
- if (vers_id != SHARE_DATABASE_VERSION_V2) {
- tdb_traverse(share_tdb, tdb_traverse_delete_fn, NULL);
- tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
- }
- tdb_unlock_bystring(share_tdb, vstring);
-
- message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated);
-
- return True;
-}
-
-/*******************************************************************
- Fake up a Everyone, full access as a default.
- ********************************************************************/
-
-static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *psize)
-{
- SEC_ACCESS sa;
- SEC_ACE ace;
- SEC_ACL *psa = NULL;
- SEC_DESC *psd = NULL;
- uint32 def_access = GENERIC_ALL_ACCESS;
-
- se_map_generic(&def_access, &file_generic_mapping);
-
- init_sec_access(&sa, GENERIC_ALL_ACCESS | def_access );
- init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
- psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize);
- }
-
- if (!psd) {
- DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
- return NULL;
- }
-
- return psd;
-}
-
-/*******************************************************************
- Pull a security descriptor from the share tdb.
- ********************************************************************/
-
-static SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
-{
- prs_struct ps;
- fstring key;
- SEC_DESC *psd = NULL;
-
- *psize = 0;
-
- /* Fetch security descriptor from tdb */
-
- slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
-
- 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) ));
-
- return get_share_security_default(ctx, snum, psize);
- }
-
- if (psd)
- *psize = sec_desc_size(psd);
-
- prs_mem_free(&ps);
- return psd;
-}
-
-/*******************************************************************
- Store a security descriptor in the share db.
- ********************************************************************/
-
-static BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
-{
- prs_struct ps;
- TALLOC_CTX *mem_ctx = NULL;
- fstring key;
- BOOL ret = False;
-
- mem_ctx = talloc_init("set_share_security");
- if (mem_ctx == NULL)
- return False;
-
- prs_init(&ps, (uint32)sec_desc_size(psd), mem_ctx, MARSHALL);
-
- if (!sec_io_desc("share_security", &psd, &ps, 1))
- goto out;
-
- slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name);
-
- if (tdb_prs_store(share_tdb, key, &ps)==0) {
- ret = True;
- DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name ));
- } else {
- DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name ));
- }
-
- /* Free malloc'ed memory */
-
-out:
-
- prs_mem_free(&ps);
- if (mem_ctx)
- talloc_destroy(mem_ctx);
- return ret;
-}
-
-/*******************************************************************
- Delete a security descriptor.
-********************************************************************/
-
-static BOOL delete_share_security(int snum)
-{
- TDB_DATA kbuf;
- fstring key;
-
- slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
- kbuf.dptr = key;
- kbuf.dsize = strlen(key)+1;
-
- if (tdb_delete(share_tdb, kbuf) != 0) {
- DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n",
- lp_servicename(snum) ));
- return False;
- }
-
- return True;
-}
-
-/*******************************************************************
Map any generic bits to file specific bits.
********************************************************************/
-void map_generic_share_sd_bits(SEC_DESC *psd)
+static void map_generic_share_sd_bits(SEC_DESC *psd)
{
int i;
SEC_ACL *ps_dacl = NULL;
@@ -517,7 +318,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
uint32 info_level, uint32 *resume_hnd, uint32 *total_entries, BOOL all_shares)
{
int num_entries = 0;
- int num_services = lp_numservices();
+ int num_services = 0;
int snum;
TALLOC_CTX *ctx = p->mem_ctx;
@@ -528,6 +329,11 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
ctr->info_level = ctr->switch_value = info_level;
*resume_hnd = 0;
+ /* Ensure all the usershares are loaded. */
+ become_root();
+ num_services = load_usershare_shares();
+ unbecome_root();
+
/* Count the number of entries. */
for (snum = 0; snum < num_services; snum++) {
if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) )
@@ -1401,7 +1207,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES
/* fail out now if you are not root or not a domain admin */
- if ((user.uid != sec_initial_uid()) &&
+ if ((user.ut.uid != sec_initial_uid()) &&
( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
goto done;
@@ -1412,7 +1218,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES
if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
strequal(session_list[snum].remote_machine, machine)) {
- if (user.uid != sec_initial_uid()) {
+ if (user.ut.uid != sec_initial_uid()) {
not_root = True;
become_root();
}
@@ -1572,7 +1378,7 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
/* fail out now if you are not root and not a disk op */
- if ( user.uid != sec_initial_uid() && !is_disk_op )
+ if ( user.ut.uid != sec_initial_uid() && !is_disk_op )
return WERR_ACCESS_DENIED;
switch (q_u->info_level) {
@@ -1739,7 +1545,7 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
- if (user.uid != sec_initial_uid() && !is_disk_op )
+ if (user.ut.uid != sec_initial_uid() && !is_disk_op )
return WERR_ACCESS_DENIED;
if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
@@ -1906,7 +1712,7 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
- if (user.uid != sec_initial_uid() && !is_disk_op )
+ if (user.ut.uid != sec_initial_uid() && !is_disk_op )
return WERR_ACCESS_DENIED;
if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
@@ -2098,7 +1904,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
psd->dacl->revision = (uint16) NT4_ACL_REVISION;
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
unbecome_user();
close_cnum(conn, user.vuid);
return r_u->status;
@@ -2106,7 +1912,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
error_exit:
if(fsp) {
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
}
if (became_user)
@@ -2207,7 +2013,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
goto error_exit;
}
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
unbecome_user();
close_cnum(conn, user.vuid);
return r_u->status;
@@ -2215,7 +2021,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
error_exit:
if(fsp) {
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
}
if (became_user) {
diff --git a/source/rpc_server/srv_svcctl_nt.c b/source/rpc_server/srv_svcctl_nt.c
index a0b8b66f508..6062dcee5ce 100644
--- a/source/rpc_server/srv_svcctl_nt.c
+++ b/source/rpc_server/srv_svcctl_nt.c
@@ -404,7 +404,7 @@ static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_
WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
{
ENUM_SERVICES_STATUS *services = NULL;
- uint32 num_services;
+ int num_services;
int i = 0;
size_t buffer_size = 0;
WERROR result = WERR_OK;
@@ -416,11 +416,14 @@ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STAT
if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
return WERR_BADFID;
- if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) )
+ if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
return WERR_ACCESS_DENIED;
+ }
- if ( (num_services = enumerate_status( p->mem_ctx, &services, token )) == -1 )
+ num_services = enumerate_status( p->mem_ctx, &services, token );
+ if (num_services == -1 ) {
return WERR_NOMEM;
+ }
for ( i=0; i<num_services; i++ ) {
buffer_size += svcctl_sizeof_enum_services_status(&services[i]);
@@ -441,7 +444,7 @@ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STAT
}
r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
- r_u->returned = num_services;
+ r_u->returned = (uint32)num_services;
if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
return WERR_NOMEM;
diff --git a/source/rpcclient/cmd_dfs.c b/source/rpcclient/cmd_dfs.c
index 956dbfa4027..b4d43bda5ee 100644
--- a/source/rpcclient/cmd_dfs.c
+++ b/source/rpcclient/cmd_dfs.c
@@ -3,6 +3,7 @@
RPC pipe client
Copyright (C) Tim Potter 2000
+ 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
@@ -27,7 +28,7 @@
static NTSTATUS cmd_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
int argc, const char **argv)
{
- BOOL dfs_exists;
+ uint32 dfs_exists;
NTSTATUS result;
if (argc != 1) {
@@ -35,7 +36,7 @@ static NTSTATUS cmd_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
- result = rpccli_dfs_exist(cli, mem_ctx, &dfs_exists);
+ result = rpccli_dfs_GetManagerVersion(cli, mem_ctx, &dfs_exists);
if (NT_STATUS_IS_OK(result))
printf("dfs is %spresent\n", dfs_exists ? "" : "not ");
@@ -47,21 +48,21 @@ static NTSTATUS cmd_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
int argc, const char **argv)
{
NTSTATUS result;
- const char *entrypath, *servername, *sharename, *comment;
+ const char *path, *servername, *sharename, *comment;
uint32 flags = 0;
if (argc != 5) {
- printf("Usage: %s entrypath servername sharename comment\n",
+ printf("Usage: %s path servername sharename comment\n",
argv[0]);
return NT_STATUS_OK;
}
- entrypath = argv[1];
+ path = argv[1];
servername = argv[2];
sharename = argv[3];
comment = argv[4];
- result = rpccli_dfs_add(cli, mem_ctx, entrypath, servername,
+ result = rpccli_dfs_Add(cli, mem_ctx, path, servername,
sharename, comment, flags);
return result;
@@ -71,18 +72,18 @@ static NTSTATUS cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
int argc, const char **argv)
{
NTSTATUS result;
- const char *entrypath, *servername, *sharename;
+ const char *path, *servername, *sharename;
if (argc != 4) {
- printf("Usage: %s entrypath servername sharename\n", argv[0]);
+ printf("Usage: %s path servername sharename\n", argv[0]);
return NT_STATUS_OK;
}
- entrypath = argv[1];
+ path = argv[1];
servername = argv[2];
sharename = argv[3];
- result = rpccli_dfs_remove(cli, mem_ctx, entrypath, servername,
+ result = rpccli_dfs_Remove(cli, mem_ctx, path, servername,
sharename);
return result;
@@ -90,78 +91,92 @@ static NTSTATUS cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
/* Display a DFS_INFO_1 structure */
-static void display_dfs_info_1(DFS_INFO_1 *info1)
+static void display_dfs_info_1(NETDFS_DFS_INFO1 *info1)
{
fstring temp;
- unistr2_to_ascii(temp, &info1->entrypath, sizeof(temp) - 1);
- printf("entrypath: %s\n", temp);
+ unistr2_to_ascii(temp, &info1->path, sizeof(temp) - 1);
+ printf("path: %s\n", temp);
}
/* Display a DFS_INFO_2 structure */
-static void display_dfs_info_2(DFS_INFO_2 *info2)
+static void display_dfs_info_2(NETDFS_DFS_INFO2 *info2)
{
fstring temp;
- unistr2_to_ascii(temp, &info2->entrypath, sizeof(temp) - 1);
- printf("entrypath: %s\n", temp);
+ unistr2_to_ascii(temp, &info2->path, sizeof(temp) - 1);
+ printf("path: %s\n", temp);
unistr2_to_ascii(temp, &info2->comment, sizeof(temp) - 1);
printf("\tcomment: %s\n", temp);
printf("\tstate: %d\n", info2->state);
- printf("\tnum_storages: %d\n", info2->num_storages);
+ printf("\tnum_stores: %d\n", info2->num_stores);
}
/* Display a DFS_INFO_3 structure */
-static void display_dfs_info_3(DFS_INFO_3 *info3)
+static void display_dfs_info_3(NETDFS_DFS_INFO3 *info3)
{
fstring temp;
int i;
- unistr2_to_ascii(temp, &info3->entrypath, sizeof(temp) - 1);
- printf("entrypath: %s\n", temp);
+ unistr2_to_ascii(temp, &info3->path, sizeof(temp) - 1);
+ printf("path: %s\n", temp);
unistr2_to_ascii(temp, &info3->comment, sizeof(temp) - 1);
printf("\tcomment: %s\n", temp);
printf("\tstate: %d\n", info3->state);
- printf("\tnum_storages: %d\n", info3->num_storages);
+ printf("\tnum_stores: %d\n", info3->num_stores);
- for (i = 0; i < info3->num_storages; i++) {
- DFS_STORAGE_INFO *dsi = &info3->storages[i];
+ for (i = 0; i < info3->num_stores; i++) {
+ NETDFS_DFS_STORAGEINFO *dsi = &info3->stores[i];
- unistr2_to_ascii(temp, &dsi->servername, sizeof(temp) - 1);
- printf("\t\tstorage[%d] servername: %s\n", i, temp);
+ unistr2_to_ascii(temp, &dsi->server, sizeof(temp) - 1);
+ printf("\t\tstorage[%d] server: %s\n", i, temp);
- unistr2_to_ascii(temp, &dsi->sharename, sizeof(temp) - 1);
- printf("\t\tstorage[%d] sharename: %s\n", i, temp);
+ unistr2_to_ascii(temp, &dsi->share, sizeof(temp) - 1);
+ printf("\t\tstorage[%d] share: %s\n", i, temp);
}
}
-/* Display a DFS_INFO_CTR structure */
-static void display_dfs_info_ctr(DFS_INFO_CTR *ctr)
+/* Display a DFS_INFO_CTR structure */
+static void display_dfs_info(NETDFS_DFS_INFO_CTR *ctr)
{
- int i;
-
- for (i = 0; i < ctr->num_entries; i++) {
- switch (ctr->switch_value) {
+ switch (ctr->switch_value) {
case 0x01:
- display_dfs_info_1(&ctr->dfs.info1[i]);
+ display_dfs_info_1(&ctr->u.info1);
break;
case 0x02:
- display_dfs_info_2(&ctr->dfs.info2[i]);
+ display_dfs_info_2(&ctr->u.info2);
break;
case 0x03:
- display_dfs_info_3(&ctr->dfs.info3[i]);
+ display_dfs_info_3(&ctr->u.info3);
break;
default:
printf("unsupported info level %d\n",
ctr->switch_value);
break;
+ }
+}
+
+static void display_dfs_enumstruct(NETDFS_DFS_ENUMSTRUCT *ctr)
+{
+ int i;
+
+ /* count is always the first element, so we can just use info1 here */
+ for (i = 0; i < ctr->e.u.info1.count; i++) {
+ switch (ctr->level) {
+ case 1: display_dfs_info_1(&ctr->e.u.info1.s[i]); break;
+ case 2: display_dfs_info_2(&ctr->e.u.info2.s[i]); break;
+ case 3: display_dfs_info_3(&ctr->e.u.info3.s[i]); break;
+ default:
+ printf("unsupported info level %d\n",
+ ctr->level);
+ return;
}
}
}
@@ -171,9 +186,11 @@ static void display_dfs_info_ctr(DFS_INFO_CTR *ctr)
static NTSTATUS cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
int argc, const char **argv)
{
- DFS_INFO_CTR ctr;
+ NETDFS_DFS_ENUMSTRUCT str;
+ NETDFS_DFS_ENUMINFO_CTR ctr;
NTSTATUS result;
uint32 info_level = 1;
+ uint32 unknown = 0, total = 0;
if (argc > 2) {
printf("Usage: %s [info_level]\n", argv[0]);
@@ -183,10 +200,14 @@ static NTSTATUS cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
if (argc == 2)
info_level = atoi(argv[1]);
- result = rpccli_dfs_enum(cli, mem_ctx, info_level, &ctr);
+ ZERO_STRUCT(ctr);
+ init_netdfs_dfs_EnumStruct(&str, info_level, ctr);
+ str.e.ptr0 = 1;
+
+ result = rpccli_dfs_Enum(cli, mem_ctx, info_level, 0xFFFFFFFF, &str, &unknown, &total);
if (NT_STATUS_IS_OK(result))
- display_dfs_info_ctr(&ctr);
+ display_dfs_enumstruct(&str);
return result;
}
@@ -195,28 +216,28 @@ static NTSTATUS cmd_dfs_getinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx
int argc, const char **argv)
{
NTSTATUS result;
- const char *entrypath, *servername, *sharename;
+ const char *path, *servername, *sharename;
uint32 info_level = 1;
- DFS_INFO_CTR ctr;
+ NETDFS_DFS_INFO_CTR ctr;
if (argc < 4 || argc > 5) {
- printf("Usage: %s entrypath servername sharename "
+ printf("Usage: %s path servername sharename "
"[info_level]\n", argv[0]);
return NT_STATUS_OK;
}
- entrypath = argv[1];
+ path = argv[1];
servername = argv[2];
sharename = argv[3];
if (argc == 5)
info_level = atoi(argv[4]);
- result = rpccli_dfs_get_info(cli, mem_ctx, entrypath, servername,
+ result = rpccli_dfs_GetInfo(cli, mem_ctx, path, servername,
sharename, info_level, &ctr);
if (NT_STATUS_IS_OK(result))
- display_dfs_info_ctr(&ctr);
+ display_dfs_info(&ctr);
return result;
}
diff --git a/source/rpcclient/cmd_ds.c b/source/rpcclient/cmd_ds.c
index 951d18a710e..478b9f89e79 100644
--- a/source/rpcclient/cmd_ds.c
+++ b/source/rpcclient/cmd_ds.c
@@ -52,11 +52,15 @@ static NTSTATUS cmd_ds_enum_domain_trusts(struct rpc_pipe_client *cli,
const char **argv)
{
NTSTATUS result;
- uint32 flags = 0x1;
+ uint32 flags = DS_DOMAIN_IN_FOREST;
struct ds_domain_trust *trusts = NULL;
unsigned int num_domains = 0;
int i;
+ if (argc > 1) {
+ flags = atoi(argv[1]);
+ }
+
result = rpccli_ds_enum_domain_trusts( cli, mem_ctx, cli->cli->desthost, flags,
&trusts, &num_domains );
diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c
index 5adaf469818..0e22b982873 100644
--- a/source/rpcclient/cmd_lsarpc.c
+++ b/source/rpcclient/cmd_lsarpc.c
@@ -47,7 +47,7 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *cli,
if (!NT_STATUS_IS_OK(result))
goto done;
- result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+ result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, NULL, &sids, &sid_types);
if (!NT_STATUS_IS_OK(result))
goto done;
@@ -59,8 +59,109 @@ done:
return result;
}
+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("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("next_audit_record:\t%d\n", d.next_audit_record);
+ d_printf("unknown:\t%d\n", d.unknown);
+}
+
+static void display_query_info_2(DOM_QUERY_2 d, TALLOC_CTX *mem_ctx)
+{
+ int i;
+ d_printf("Auditing enabled:\t%d\n", d.auditing_enabled);
+ d_printf("Auditing categories:\t%d\n", d.count1);
+ d_printf("Auditsettings:\n");
+ for (i=0; i<d.count1; i++) {
+ const char *val = audit_policy_str(mem_ctx, d.auditsettings[i]);
+ const char *policy = audit_description_str(i);
+ d_printf("%s:\t%s\n", policy, val);
+ }
+}
+
+static void display_query_info_3(DOM_QUERY_3 d)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &d.uni_domain_name, d.uni_dom_max_len);
+
+ d_printf("Domain Name: %s\n", name);
+ d_printf("Domain Sid: %s\n", sid_string_static(&d.dom_sid.sid));
+}
+
+static void display_query_info_5(DOM_QUERY_5 d)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &d.uni_domain_name, d.uni_dom_max_len);
+
+ d_printf("Domain Name: %s\n", name);
+ d_printf("Domain Sid: %s\n", sid_string_static(&d.dom_sid.sid));
+}
+
+static void display_query_info_10(DOM_QUERY_10 d)
+{
+ d_printf("Shutdown on full: %d\n", d.shutdown_on_full);
+}
+
+static void display_query_info_11(DOM_QUERY_11 d)
+{
+ d_printf("Shutdown on full: %d\n", d.shutdown_on_full);
+ d_printf("Log is full: %d\n", d.log_is_full);
+ d_printf("Unknown: %d\n", d.unknown);
+}
+
+static void display_query_info_12(DOM_QUERY_12 d)
+{
+ fstring dom_name, dns_dom_name, forest_name;
+
+ unistr2_to_ascii(dom_name, &d.uni_nb_dom_name, d.hdr_nb_dom_name.uni_max_len);
+ unistr2_to_ascii(dns_dom_name, &d.uni_dns_dom_name, d.hdr_dns_dom_name.uni_max_len);
+ unistr2_to_ascii(forest_name, &d.uni_forest_name, d.hdr_forest_name.uni_max_len);
+
+ d_printf("Domain NetBios Name: %s\n", dom_name);
+ d_printf("Domain DNS Name: %s\n", dns_dom_name);
+ d_printf("Domain Forest Name: %s\n", forest_name);
+ d_printf("Domain Sid: %s\n", sid_string_static(&d.dom_sid.sid));
+ d_printf("Domain GUID: %s\n", smb_uuid_string_static(d.dom_guid));
+
+}
-/* Look up domain related information on a remote host */
+
+
+static void display_lsa_query_info(LSA_INFO_CTR *dom, TALLOC_CTX *mem_ctx)
+{
+ switch (dom->info_class) {
+ case 1:
+ display_query_info_1(dom->info.id1);
+ break;
+ case 2:
+ display_query_info_2(dom->info.id2, mem_ctx);
+ break;
+ case 3:
+ display_query_info_3(dom->info.id3);
+ break;
+ case 5:
+ display_query_info_5(dom->info.id5);
+ break;
+ case 10:
+ display_query_info_10(dom->info.id10);
+ break;
+ case 11:
+ display_query_info_11(dom->info.id11);
+ break;
+ case 12:
+ display_query_info_12(dom->info.id12);
+ break;
+ default:
+ printf("can't display info level: %d\n", dom->info_class);
+ break;
+ }
+}
static NTSTATUS cmd_lsa_query_info_policy(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx, int argc,
@@ -68,11 +169,7 @@ static NTSTATUS cmd_lsa_query_info_policy(struct rpc_pipe_client *cli,
{
POLICY_HND pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- DOM_SID *dom_sid = NULL;
- struct uuid *dom_guid;
- char *domain_name = NULL;
- char *dns_name = NULL;
- char *forest_name = NULL;
+ LSA_INFO_CTR dom;
uint32 info_class = 3;
@@ -83,56 +180,33 @@ static NTSTATUS cmd_lsa_query_info_policy(struct rpc_pipe_client *cli,
if (argc == 2)
info_class = atoi(argv[1]);
-
- /* Lookup info policy */
+
switch (info_class) {
case 12:
result = rpccli_lsa_open_policy2(cli, mem_ctx, True,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &pol);
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
if (!NT_STATUS_IS_OK(result))
goto done;
- result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
- info_class, &domain_name,
- &dns_name, &forest_name,
- &dom_guid, &dom_sid);
+
+ result = rpccli_lsa_query_info_policy2_new(cli, mem_ctx, &pol,
+ info_class, &dom);
break;
default:
result = rpccli_lsa_open_policy(cli, mem_ctx, True,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &pol);
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
if (!NT_STATUS_IS_OK(result))
goto done;
- result = rpccli_lsa_query_info_policy(cli, mem_ctx, &pol,
- info_class, &domain_name,
- &dom_sid);
+
+ result = rpccli_lsa_query_info_policy_new(cli, mem_ctx, &pol,
+ info_class, &dom);
}
- if (!NT_STATUS_IS_OK(result))
- goto done;
-
- if (domain_name) {
- if (dom_sid == NULL) {
- printf("got no sid for domain %s\n", domain_name);
- } else {
- printf("domain %s has sid %s\n", domain_name,
- sid_string_static(dom_sid));
- }
- } else {
- printf("could not query info for level %d\n", info_class);
- }
- if (dns_name)
- printf("domain dns name is %s\n", dns_name);
- if (forest_name)
- printf("forest name is %s\n", forest_name);
-
- if (info_class == 12) {
- printf("domain GUID is %s\n",
- smb_uuid_string_static(*dom_guid));
- }
+ display_lsa_query_info(&dom, mem_ctx);
rpccli_lsa_close(cli, mem_ctx, &pol);
@@ -165,7 +239,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct rpc_pipe_client *cli,
goto done;
result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1,
- (const char**)(argv + 1), &sids, &types);
+ (const char**)(argv + 1), NULL, &sids, &types);
if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) !=
NT_STATUS_V(STATUS_SOME_UNMAPPED))
@@ -736,10 +810,10 @@ static NTSTATUS cmd_lsa_query_secobj(struct rpc_pipe_client *cli,
POLICY_HND pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
SEC_DESC_BUF *sdb;
- uint32 sec_info = 0x00000004; /* ??? */
+ uint32 sec_info = DACL_SECURITY_INFORMATION;
- if (argc != 1 ) {
- printf("Usage: %s\n", argv[0]);
+ if (argc < 1 || argc > 2) {
+ printf("Usage: %s [sec_info]\n", argv[0]);
return NT_STATUS_OK;
}
@@ -747,6 +821,9 @@ static NTSTATUS cmd_lsa_query_secobj(struct rpc_pipe_client *cli,
SEC_RIGHTS_MAXIMUM_ALLOWED,
&pol);
+ if (argc == 2)
+ sscanf(argv[1], "%x", &sec_info);
+
if (!NT_STATUS_IS_OK(result))
goto done;
diff --git a/source/rpcclient/cmd_netlogon.c b/source/rpcclient/cmd_netlogon.c
index 9377f8fde8c..35b8accdb6a 100644
--- a/source/rpcclient/cmd_netlogon.c
+++ b/source/rpcclient/cmd_netlogon.c
@@ -294,45 +294,44 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
/* Log on a domain user */
static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli,
- TALLOC_CTX *mem_ctx, int argc,
- const char **argv)
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
{
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- int logon_type = NET_LOGON_TYPE;
- const char *username, *password;
- uint32 neg_flags = 0x000001ff;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ int logon_type = NET_LOGON_TYPE;
+ const char *username, *password;
int auth_level = 2;
+ uint32 logon_param = 0;
- /* Check arguments */
+ /* Check arguments */
- if (argc < 3 || argc > 6) {
- fprintf(stderr, "Usage: samlogon <username> <password> "
- "[logon_type] [neg flags] [auth level (2 or 3)]\n"
- "neg flags being 0x000001ff or 0x6007ffff\n");
- return NT_STATUS_OK;
- }
+ if (argc < 3 || argc > 6) {
+ fprintf(stderr, "Usage: samlogon <username> <password> "
+ "[logon_type (1 or 2)] [auth level (2 or 3)] [logon_parameter]\n");
+ return NT_STATUS_OK;
+ }
- username = argv[1];
- password = argv[2];
+ username = argv[1];
+ password = argv[2];
- if (argc >= 4)
- sscanf(argv[3], "%i", &logon_type);
+ if (argc >= 4)
+ sscanf(argv[3], "%i", &logon_type);
if (argc >= 5)
- sscanf(argv[4], "%i", &neg_flags);
+ sscanf(argv[4], "%i", &auth_level);
if (argc == 6)
- sscanf(argv[5], "%i", &auth_level);
+ sscanf(argv[5], "%x", &logon_param);
- /* Perform the sam logon */
+ /* Perform the sam logon */
- result = rpccli_netlogon_sam_logon(cli, mem_ctx, 0, lp_workgroup(), username, password, logon_type);
+ result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, logon_type);
if (!NT_STATUS_IS_OK(result))
goto done;
done:
- return result;
+ return result;
}
/* Change the trust account password */
diff --git a/source/rpcclient/cmd_reg.c b/source/rpcclient/cmd_reg.c
index fcc18cd9f52..e8038d094e6 100644
--- a/source/rpcclient/cmd_reg.c
+++ b/source/rpcclient/cmd_reg.c
@@ -42,7 +42,7 @@
*
*/
-#if 0 /* This whole file need to be rewritten for the cirrent rpcclient interface */
+#if 0 /* This whole file need to be rewritten for the current rpcclient interface */
/****************************************************************************
nt registry enum
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index 991b55a13c8..ca0b6e96245 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -100,7 +100,7 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
printf("\tuser_rid :\t0x%x\n" , usr->user_rid ); /* User ID */
printf("\tgroup_rid:\t0x%x\n" , usr->group_rid); /* Group ID */
- printf("\tacb_info :\t0x%04x\n", usr->acb_info ); /* Account Control Info */
+ printf("\tacb_info :\t0x%08x\n", usr->acb_info ); /* Account Control Info */
printf("\tfields_present:\t0x%08x\n", usr->fields_present); /* 0x00ff ffff */
printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
@@ -149,33 +149,35 @@ static const char *display_time(NTTIME nttime)
return (string);
}
-static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
+static void display_password_properties(uint32 password_properties)
{
-
- printf("Minimum password length:\t\t\t%d\n", info1->min_length_password);
- printf("Password uniqueness (remember x passwords):\t%d\n", info1->password_history);
- printf("Password Properties:\t\t\t\t0x%08x\n", info1->password_properties);
-
- if (info1->password_properties & DOMAIN_PASSWORD_COMPLEX)
+ printf("password_properties: 0x%08x\n", password_properties);
+
+ if (password_properties & DOMAIN_PASSWORD_COMPLEX)
printf("\tDOMAIN_PASSWORD_COMPLEX\n");
- if (info1->password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE) {
+ if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
- printf("users must open a session to change password ");
- }
- if (info1->password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
+ if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
- if (info1->password_properties & DOMAIN_LOCKOUT_ADMINS)
+ if (password_properties & DOMAIN_LOCKOUT_ADMINS)
printf("\tDOMAIN_LOCKOUT_ADMINS\n");
- if (info1->password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
+ if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
- if (info1->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
+ if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
+}
+static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
+{
+
+ printf("Minimum password length:\t\t\t%d\n", info1->min_length_password);
+ printf("Password uniqueness (remember x passwords):\t%d\n", info1->password_history);
+ display_password_properties(info1->password_properties);
printf("password expire in:\t\t\t\t%s\n", display_time(info1->expire));
printf("Min password age (allow changing in x days):\t%s\n", display_time(info1->min_passwordage));
}
@@ -440,6 +442,18 @@ static void display_group_info1(GROUP_INFO1 *info1)
/****************************************************************************
display group info
****************************************************************************/
+static void display_group_info2(GROUP_INFO2 *info2)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &info2->uni_acct_name, sizeof(name)-1);
+ printf("\tGroup Description:%s\n", name);
+}
+
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
static void display_group_info3(GROUP_INFO3 *info3)
{
printf("\tGroup Attribute:%d\n", info3->group_attr);
@@ -458,23 +472,42 @@ static void display_group_info4(GROUP_INFO4 *info4)
}
/****************************************************************************
+ display group info
+ ****************************************************************************/
+static void display_group_info5(GROUP_INFO5 *info5)
+{
+ fstring temp;
+
+ unistr2_to_ascii(temp, &info5->uni_acct_name, sizeof(temp)-1);
+ printf("\tGroup Name:\t%s\n", temp);
+ unistr2_to_ascii(temp, &info5->uni_acct_desc, sizeof(temp)-1);
+ printf("\tDescription:\t%s\n", temp);
+ printf("\tGroup Attribute:%d\n", info5->group_attr);
+ printf("\tNum Members:%d\n", info5->num_members);
+}
+
+/****************************************************************************
display sam sync structure
****************************************************************************/
static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
{
switch (ctr->switch_value1) {
- case 1: {
- display_group_info1(&ctr->group.info1);
- break;
- }
- case 3: {
- display_group_info3(&ctr->group.info3);
- break;
- }
- case 4: {
- display_group_info4(&ctr->group.info4);
- break;
- }
+ case 1:
+ display_group_info1(&ctr->group.info1);
+ break;
+ case 2:
+ display_group_info2(&ctr->group.info2);
+ break;
+ case 3:
+ display_group_info3(&ctr->group.info3);
+ break;
+ case 4:
+ display_group_info4(&ctr->group.info4);
+ break;
+ case 5:
+ display_group_info5(&ctr->group.info5);
+ break;
+
}
}
@@ -774,7 +807,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
char **dom_users;
uint32 *dom_rids;
uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
- uint16 acb_mask = ACB_NORMAL;
+ uint32 acb_mask = ACB_NORMAL;
BOOL got_connect_pol = False, got_domain_pol = False;
if ((argc < 1) || (argc > 3)) {
@@ -786,7 +819,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli,
sscanf(argv[1], "%x", &access_mask);
if (argc > 2)
- sscanf(argv[2], "%hx", &acb_mask);
+ sscanf(argv[2], "%x", &acb_mask);
/* Get sam policy handle */
@@ -1065,6 +1098,82 @@ static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli,
return result;
}
+/* Query delete an alias membership */
+
+static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, alias_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ uint32 alias_rid;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if (argc != 3) {
+ printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ alias_rid = strtoul(argv[2], NULL, 10);
+
+ /* Open SAMR handle */
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Open handle on domain */
+
+ if (StrCaseCmp(argv[1], "domain")==0)
+ result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &domain_sid, &domain_pol);
+ else if (StrCaseCmp(argv[1], "builtin")==0)
+ result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ &global_sid_Builtin, &domain_pol);
+ else
+ return NT_STATUS_INVALID_PARAMETER;
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Open handle on alias */
+
+ result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
+ access_mask,
+ alias_rid, &alias_pol);
+ if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
+ /* Probably this was a user name, try lookupnames */
+ uint32 num_rids;
+ uint32 *rids, *types;
+
+ result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+ 1000, 1, &argv[2],
+ &num_rids, &rids,
+ &types);
+
+ if (NT_STATUS_IS_OK(result)) {
+ result = rpccli_samr_open_alias(cli, mem_ctx,
+ &domain_pol,
+ access_mask,
+ rids[0], &alias_pol);
+ }
+ }
+
+ result = rpccli_samr_delete_dom_alias(cli, mem_ctx, &alias_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ rpccli_samr_close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_close(cli, mem_ctx, &connect_pol);
+ done:
+ return result;
+}
+
/* Query display info */
static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
@@ -1085,7 +1194,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli,
int loop_count = 0;
BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */
- if (argc > 5) {
+ if (argc > 6) {
printf("Usage: %s [info level] [start index] [max entries] [max size] [access mask]\n", argv[0]);
return NT_STATUS_OK;
}
@@ -1213,7 +1322,7 @@ static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli,
uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
SAM_UNK_CTR ctr;
- if (argc > 2) {
+ if (argc > 3) {
printf("Usage: %s [info level] [access mask]\n", argv[0]);
return NT_STATUS_OK;
}
@@ -1289,7 +1398,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli,
POLICY_HND connect_pol, domain_pol, user_pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
const char *acct_name;
- uint16 acb_info;
+ uint32 acb_info;
uint32 unknown, user_rid;
uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
@@ -1405,6 +1514,65 @@ static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli,
return result;
}
+/* Create domain alias */
+
+static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ POLICY_HND connect_pol, domain_pol, alias_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *alias_name;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+ if ((argc < 2) || (argc > 3)) {
+ printf("Usage: %s aliasname [access mask]\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ alias_name = argv[1];
+
+ if (argc > 2)
+ sscanf(argv[2], "%x", &access_mask);
+
+ /* 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;
+
+ /* Create domain user */
+
+ result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
+ alias_name, &alias_pol);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ result = rpccli_samr_close(cli, mem_ctx, &alias_pol);
+ 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;
+}
+
/* Lookup sam names */
static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli,
@@ -1620,7 +1788,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
{
POLICY_HND connect_pol, domain_pol, user_pol, *pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- uint32 info_level = 4;
+ uint32 sec_info = DACL_SECURITY_INFORMATION;
fstring server;
uint32 user_rid = 0;
TALLOC_CTX *ctx = NULL;
@@ -1629,8 +1797,8 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
ctx=talloc_init("cmd_samr_query_sec_obj");
- if ((argc < 1) || (argc > 2)) {
- printf("Usage: %s [rid|-d]\n", argv[0]);
+ if ((argc < 1) || (argc > 3)) {
+ printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
printf("\tSpecify rid for security on user, -d for security on domain\n");
return NT_STATUS_OK;
}
@@ -1641,6 +1809,10 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
else
sscanf(argv[1], "%i", &user_rid);
}
+
+ if (argc == 3) {
+ sec_info = atoi(argv[2]);
+ }
slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
strupper_m(server);
@@ -1678,14 +1850,14 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
/* Query SAM security object */
- result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx,
+ result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, sec_info, ctx,
&sec_desc_buf);
if (!NT_STATUS_IS_OK(result))
goto done;
display_sec_desc(sec_desc_buf->sec);
-
+
rpccli_samr_close(cli, mem_ctx, &user_pol);
rpccli_samr_close(cli, mem_ctx, &domain_pol);
rpccli_samr_close(cli, mem_ctx, &connect_pol);
@@ -1694,6 +1866,63 @@ done:
return result;
}
+static NTSTATUS cmd_samr_get_usrdom_pwinfo(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ uint16 min_pwd_length;
+ uint32 password_properties, unknown1, rid;
+
+ if (argc != 2) {
+ printf("Usage: %s rid\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ sscanf(argv[1], "%i", &rid);
+
+ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ rid, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_get_usrdom_pwinfo(cli, mem_ctx, &user_pol,
+ &min_pwd_length, &password_properties,
+ &unknown1) ;
+
+ if (NT_STATUS_IS_OK(result)) {
+ printf("min_pwd_length: %d\n", min_pwd_length);
+ printf("unknown1: %d\n", unknown1);
+ display_password_properties(password_properties);
+ }
+
+ done:
+ rpccli_samr_close(cli, mem_ctx, &user_pol);
+ rpccli_samr_close(cli, mem_ctx, &domain_pol);
+ rpccli_samr_close(cli, mem_ctx, &connect_pol);
+
+ return result;
+}
+
+
static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
int argc, const char **argv)
@@ -1711,25 +1940,7 @@ static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli,
if (NT_STATUS_IS_OK(result)) {
printf("min_pwd_length: %d\n", min_pwd_length);
- printf("password_properties: 0x%08x\n", password_properties);
-
- if (password_properties & DOMAIN_PASSWORD_COMPLEX)
- printf("\tDOMAIN_PASSWORD_COMPLEX\n");
-
- if (password_properties & DOMAIN_PASSWORD_NO_ANON_CHANGE)
- printf("\tDOMAIN_PASSWORD_NO_ANON_CHANGE\n");
-
- if (password_properties & DOMAIN_PASSWORD_NO_CLEAR_CHANGE)
- printf("\tDOMAIN_PASSWORD_NO_CLEAR_CHANGE\n");
-
- if (password_properties & DOMAIN_LOCKOUT_ADMINS)
- printf("\tDOMAIN_LOCKOUT_ADMINS\n");
-
- if (password_properties & DOMAIN_PASSWORD_STORE_CLEARTEXT)
- printf("\tDOMAIN_PASSWORD_STORE_CLEARTEXT\n");
-
- if (password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE)
- printf("\tDOMAIN_REFUSE_PASSWORD_CHANGE\n");
+ display_password_properties(password_properties);
}
return result;
@@ -1780,6 +1991,83 @@ 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)
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ const char *user, *oldpass, *newpass;
+ uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+ SAM_UNK_INFO_1 info;
+ SAMR_CHANGE_REJECT reject;
+
+ 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_chgpasswd3(cli, mem_ctx, user, newpass, oldpass, &info, &reject);
+
+ if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
+
+ display_sam_unk_info_1(&info);
+
+ switch (reject.reject_reason) {
+ case REJECT_REASON_TOO_SHORT:
+ d_printf("REJECT_REASON_TOO_SHORT\n");
+ break;
+ case REJECT_REASON_IN_HISTORY:
+ d_printf("REJECT_REASON_IN_HISTORY\n");
+ break;
+ case REJECT_REASON_NOT_COMPLEX:
+ d_printf("REJECT_REASON_NOT_COMPLEX\n");
+ break;
+ case REJECT_REASON_OTHER:
+ d_printf("REJECT_REASON_OTHER\n");
+ break;
+ default:
+ d_printf("unknown reject reason: %d\n", reject.reject_reason);
+ break;
+ }
+ }
+
+ 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;
+}
/* List of commands exported by this module */
@@ -1793,6 +2081,7 @@ struct cmd_set samr_commands[] = {
{ "queryuseraliases", RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases, NULL, PI_SAMR, NULL, "Query user aliases", "" },
{ "querygroupmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem, NULL, PI_SAMR, NULL, "Query group membership", "" },
{ "queryaliasmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem, NULL, PI_SAMR, NULL, "Query alias membership", "" },
+ { "deletealias", RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias, NULL, PI_SAMR, NULL, "Delete an alias", "" },
{ "querydispinfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo, NULL, PI_SAMR, NULL, "Query display info", "" },
{ "querydominfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo, NULL, PI_SAMR, NULL, "Query domain info", "" },
{ "enumdomusers", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users, NULL, PI_SAMR, NULL, "Enumerate domain users", "" },
@@ -1801,12 +2090,15 @@ struct cmd_set samr_commands[] = {
{ "createdomuser", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user, NULL, PI_SAMR, NULL, "Create domain user", "" },
{ "createdomgroup", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group, NULL, PI_SAMR, NULL, "Create domain group", "" },
+ { "createdomalias", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias, NULL, PI_SAMR, NULL, "Create domain alias", "" },
{ "samlookupnames", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names, NULL, PI_SAMR, NULL, "Look up names", "" },
{ "samlookuprids", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids, NULL, PI_SAMR, NULL, "Look up names", "" },
{ "deletedomuser", RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user, NULL, PI_SAMR, NULL, "Delete domain user", "" },
{ "samquerysecobj", RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj, NULL, PI_SAMR, NULL, "Query SAMR security object", "" },
{ "getdompwinfo", RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo, NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
+ { "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", "" },
+ { "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 afca3e747f2..f04b6a8ec9f 100644
--- a/source/rpcclient/cmd_spoolss.c
+++ b/source/rpcclient/cmd_spoolss.c
@@ -704,7 +704,7 @@ static void display_reg_value(REGISTRY_VALUE value)
}
putchar(hex[i]);
}
- talloc_free(hex);
+ TALLOC_FREE(hex);
putchar('\n');
break;
}
@@ -2396,9 +2396,10 @@ static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
curkey += strlen(subkey) + 1;
}
- safe_free(keylist);
-
done:
+
+ SAFE_FREE(keylist);
+
if (got_hnd)
rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c
index 6bed52c3960..50ddbd405ba 100644
--- a/source/rpcclient/rpcclient.c
+++ b/source/rpcclient/rpcclient.c
@@ -58,35 +58,43 @@ static char **completion_fn(const char *text, int start, int end)
#endif
/* make sure we have a list of valid commands */
- if (!commands)
+ if (!commands) {
return NULL;
+ }
matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
- if (!matches) return NULL;
+ if (!matches) {
+ return NULL;
+ }
matches[count++] = SMB_STRDUP(text);
- if (!matches[0]) return NULL;
+ if (!matches[0]) {
+ SAFE_FREE(matches);
+ return NULL;
+ }
- while (commands && count < MAX_COMPLETIONS-1)
- {
- if (!commands->cmd_set)
+ while (commands && count < MAX_COMPLETIONS-1) {
+ if (!commands->cmd_set) {
break;
+ }
- for (i=0; commands->cmd_set[i].name; i++)
- {
+ for (i=0; commands->cmd_set[i].name; i++) {
if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
(( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
commands->cmd_set[i].ntfn ) ||
( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
- commands->cmd_set[i].wfn)))
- {
+ commands->cmd_set[i].wfn))) {
matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
- if (!matches[count])
+ if (!matches[count]) {
+ for (i = 0; i < count; i++) {
+ SAFE_FREE(matches[count]);
+ }
+ SAFE_FREE(matches);
return NULL;
+ }
count++;
}
}
-
commands = commands->next;
}
@@ -663,13 +671,11 @@ out_free:
}
*/
- if (argv) {
- /* NOTE: popt allocates the whole argv, including the
- * strings, as a single block. So a single free is
- * enough to release it -- we don't free the
- * individual strings. rtfm. */
- free(argv);
- }
+ /* NOTE: popt allocates the whole argv, including the
+ * strings, as a single block. So a single free is
+ * enough to release it -- we don't free the
+ * individual strings. rtfm. */
+ free(argv);
return result;
}
@@ -679,7 +685,6 @@ out_free:
int main(int argc, char *argv[])
{
- BOOL interactive = True;
int opt;
static char *cmdstr = NULL;
const char *server;
@@ -713,9 +718,7 @@ out_free:
/* the following functions are part of the Samba debugging
facilities. See lib/debug.c */
- setup_logging("rpcclient", interactive);
- if (!interactive)
- reopen_logs();
+ setup_logging("rpcclient", True);
/* Parse options */
@@ -766,7 +769,7 @@ out_free:
/* Load smb.conf file */
- if (!lp_load(dyn_CONFIGFILE,True,False,False))
+ if (!lp_load(dyn_CONFIGFILE,True,False,False,True))
fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
if ( strlen(new_workgroup) != 0 )
diff --git a/source/sam/idmap.c b/source/sam/idmap.c
index 9fc1a573a92..aac8b70013a 100644
--- a/source/sam/idmap.c
+++ b/source/sam/idmap.c
@@ -188,6 +188,18 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
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",
@@ -225,6 +237,18 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
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) {
@@ -338,23 +362,6 @@ NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
}
/**************************************************************************
- Alloocate a new RID
-**************************************************************************/
-
-NTSTATUS idmap_allocate_rid(uint32 *rid, int type)
-{
- /* we have to allocate from the authoritative backend */
-
- if (proxyonly)
- return NT_STATUS_UNSUCCESSFUL;
-
- if ( remote_map )
- return remote_map->allocate_rid( rid, type );
-
- return cache_map->allocate_rid( rid, type );
-}
-
-/**************************************************************************
Shutdown maps.
**************************************************************************/
diff --git a/source/sam/idmap_ad.c b/source/sam/idmap_ad.c
index 47e349483dd..f9a959e7ec0 100644
--- a/source/sam/idmap_ad.c
+++ b/source/sam/idmap_ad.c
@@ -371,12 +371,6 @@ static NTSTATUS ad_idmap_close(void)
return NT_STATUS_OK;
}
-/* New for beta3 */
-static NTSTATUS ad_idmap_allocate_rid(uint32 *rid, int rid_type)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
static NTSTATUS ad_idmap_allocate_id(unid_t *id, int id_type)
{
return NT_STATUS_NOT_IMPLEMENTED;
@@ -389,7 +383,6 @@ static void ad_idmap_status(void)
static struct idmap_methods ad_methods = {
ad_idmap_init,
- ad_idmap_allocate_rid,
ad_idmap_allocate_id,
ad_idmap_get_sid_from_id,
ad_idmap_get_id_from_sid,
diff --git a/source/sam/idmap_ldap.c b/source/sam/idmap_ldap.c
index b4a8c8a7528..6169c89b3b9 100644
--- a/source/sam/idmap_ldap.c
+++ b/source/sam/idmap_ldap.c
@@ -113,260 +113,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
return NT_STATUS_OK;
}
-/**********************************************************************
- Even if the sambaDomain attribute in LDAP tells us that this RID is
- safe to use, always check before use.
-*********************************************************************/
-
-static BOOL sid_in_use(struct ldap_idmap_state *state,
- const DOM_SID *sid, int *error)
-{
- fstring filter;
- fstring sid_string;
- LDAPMessage *result = NULL;
- int rc;
- const char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
-
- slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
-
- rc = smbldap_search_suffix(state->smbldap_state,
- filter, sid_attr, &result);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
- sid_string, ld_error));
- SAFE_FREE(ld_error);
-
- *error = rc;
- return True;
- }
-
- if ((ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) {
- DEBUG(3, ("Sid %s already in use - trying next RID\n",
- sid_string));
- ldap_msgfree(result);
- return True;
- }
-
- ldap_msgfree(result);
-
- /* good, sid is not in use */
- return False;
-}
-
-/**********************************************************************
- Set the new nextRid attribute, and return one we can use.
-
- This also checks that this RID is actually free - in case the admin
- manually stole it :-).
-*********************************************************************/
-
-static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
- int rid_type)
-{
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- LDAPMessage *domain_result = NULL;
- LDAPMessage *entry = NULL;
- char *dn;
- LDAPMod **mods = NULL;
- fstring old_rid_string;
- fstring next_rid_string;
- fstring algorithmic_rid_base_string;
- uint32 next_rid;
- uint32 alg_rid_base;
- int attempts = 0;
- char *ld_error = NULL;
-
- while (attempts < 10) {
- if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state,
- &domain_result, get_global_sam_name(), True))) {
- return ret;
- }
-
- entry = ldap_first_entry(state->smbldap_state->ldap_struct, domain_result);
- if (!entry) {
- DEBUG(0, ("Could not get domain info entry\n"));
- ldap_msgfree(domain_result);
- return ret;
- }
-
- if ((dn = smbldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) {
- DEBUG(0, ("Could not get domain info DN\n"));
- ldap_msgfree(domain_result);
- return ret;
- }
-
- /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and
- algorithmic_rid_base. The other two are to avoid stomping on the
- different sets of algorithmic RIDs */
-
- if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
- algorithmic_rid_base_string)) {
-
- alg_rid_base = (uint32)atol(algorithmic_rid_base_string);
- } else {
- alg_rid_base = algorithmic_rid_base();
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base);
- smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
- algorithmic_rid_base_string);
- }
-
- next_rid = 0;
-
- if (alg_rid_base > BASE_RID) {
- /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we
- can allocate to new users */
- if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
- old_rid_string)) {
- *rid = (uint32)atol(old_rid_string);
- } else {
- *rid = BASE_RID;
- }
-
- next_rid = *rid+1;
- if (next_rid >= alg_rid_base) {
- ldap_msgfree(domain_result);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
-
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
- next_rid_string);
- }
-
- if (!next_rid) { /* not got one already */
- switch (rid_type) {
- case USER_RID_TYPE:
- if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- old_rid_string)) {
- *rid = (uint32)atol(old_rid_string);
- }
- break;
- case GROUP_RID_TYPE:
- if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
- old_rid_string)) {
- *rid = (uint32)atol(old_rid_string);
- }
- break;
- }
-
- /* This is the core of the whole routine. If we had
- scheme-style closures, there would be a *lot* less code
- duplication... */
-
- next_rid = *rid+RID_MULTIPLIER;
- slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
-
- switch (rid_type) {
- case USER_RID_TYPE:
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
- next_rid_string);
- break;
-
- case GROUP_RID_TYPE:
- /* Try to make the modification atomically by enforcing the
- old value in the delete mod. */
- smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
- next_rid_string);
- break;
- }
- }
-
- if ((smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) {
- DOM_SID dom_sid;
- DOM_SID sid;
- pstring domain_sid_string;
- int error = 0;
-
- if (!smbldap_get_single_pstring(state->smbldap_state->ldap_struct, domain_result,
- get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
- domain_sid_string)) {
- ldap_mods_free(mods, True);
- SAFE_FREE(dn);
- ldap_msgfree(domain_result);
- return ret;
- }
-
- if (!string_to_sid(&dom_sid, domain_sid_string)) {
- ldap_mods_free(mods, True);
- SAFE_FREE(dn);
- ldap_msgfree(domain_result);
- return ret;
- }
-
- ldap_mods_free(mods, True);
- mods = NULL;
- SAFE_FREE(dn);
- ldap_msgfree(domain_result);
-
- sid_copy(&sid, &dom_sid);
- sid_append_rid(&sid, *rid);
-
- /* check RID is not in use */
- if (sid_in_use(state, &sid, &error)) {
- if (error) {
- return ret;
- }
- continue;
- }
-
- return NT_STATUS_OK;
- }
-
- ld_error = NULL;
- ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL"));
- SAFE_FREE(ld_error);
-
- ldap_mods_free(mods, True);
- mods = NULL;
-
- SAFE_FREE(dn);
-
- ldap_msgfree(domain_result);
- domain_result = NULL;
-
- {
- /* Sleep for a random timeout */
- unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
- attempts += 1;
-
- sleeptime %= 100;
- smb_msleep(sleeptime);
- }
- }
-
- DEBUG(0, ("Failed to set new RID\n"));
- return ret;
-}
-
-
-/*****************************************************************************
- Allocate a new RID
-*****************************************************************************/
-
-static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type)
-{
- return ldap_next_rid( &ldap_state, rid, rid_type );
-}
-
/*****************************************************************************
Allocate a new uid or gid
*****************************************************************************/
@@ -394,12 +140,12 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
- attr_list = get_attr_list( idpool_attr_list );
+ 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);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL));
@@ -505,7 +251,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
LDAP_OBJ_IDMAP_ENTRY, type,
((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid));
- attr_list = get_attr_list( sidmap_attr_list );
+ 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);
@@ -534,7 +280,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
ret = NT_STATUS_OK;
out:
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (result)
ldap_msgfree(result);
@@ -577,7 +323,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
/* do the search and check for errors */
- attr_list = get_attr_list( sidmap_attr_list );
+ 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);
@@ -651,7 +397,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
}
out:
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (result)
ldap_msgfree(result);
SAFE_FREE(dn);
@@ -674,10 +420,10 @@ static NTSTATUS verify_idpool( void )
fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL );
- attr_list = get_attr_list( idpool_attr_list );
+ 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);
- free_attr_list ( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS)
return NT_STATUS_UNSUCCESSFUL;
@@ -776,7 +522,6 @@ static void ldap_idmap_status(void)
static struct idmap_methods ldap_methods = {
ldap_idmap_init,
- ldap_allocate_rid,
ldap_allocate_id,
ldap_get_sid_from_id,
ldap_get_id_from_sid,
diff --git a/source/sam/idmap_rid.c b/source/sam/idmap_rid.c
index eced549a557..58838512a68 100644
--- a/source/sam/idmap_rid.c
+++ b/source/sam/idmap_rid.c
@@ -287,7 +287,13 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name
*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);
@@ -527,11 +533,6 @@ static NTSTATUS rid_idmap_close(void)
return NT_STATUS_OK;
}
-static NTSTATUS rid_idmap_allocate_rid(uint32 *rid, int rid_type)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
static NTSTATUS rid_idmap_allocate_id(unid_t *id, int id_type)
{
return NT_STATUS_NOT_IMPLEMENTED;
@@ -544,7 +545,6 @@ static void rid_idmap_status(void)
static struct idmap_methods rid_methods = {
rid_idmap_init,
- rid_idmap_allocate_rid,
rid_idmap_allocate_id,
rid_idmap_get_sid_from_id,
rid_idmap_get_id_from_sid,
diff --git a/source/sam/idmap_smbldap.c b/source/sam/idmap_smbldap.c
index b1aae2b86f7..4d80364437c 100644
--- a/source/sam/idmap_smbldap.c
+++ b/source/sam/idmap_smbldap.c
@@ -87,15 +87,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
}
/*****************************************************************************
- Allocate a new RID
-*****************************************************************************/
-
-static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type)
-{
- return NT_STATUS_UNSUCCESSFUL;
-}
-
-/*****************************************************************************
Allocate a new uid or gid
*****************************************************************************/
@@ -437,7 +428,6 @@ static void ldap_idmap_status(void)
static struct idmap_methods ldap_methods = {
ldap_idmap_init,
- ldap_allocate_rid,
ldap_allocate_id,
ldap_get_sid_from_id,
ldap_get_id_from_sid,
diff --git a/source/sam/idmap_tdb.c b/source/sam/idmap_tdb.c
index e89a6cf547c..665c56d2f67 100644
--- a/source/sam/idmap_tdb.c
+++ b/source/sam/idmap_tdb.c
@@ -31,9 +31,6 @@
#define HWM_GROUP "GROUP HWM"
#define HWM_USER "USER HWM"
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
-
/* Globals */
static TDB_CONTEXT *idmap_tdb;
@@ -46,41 +43,6 @@ static struct idmap_state {
} idmap_state;
/**********************************************************************
- allocate a new RID; We don't care if is a user or group
-**********************************************************************/
-
-static NTSTATUS db_allocate_rid(uint32 *rid, int rid_type)
-{
- uint32 lowrid, highrid;
- uint32 tmp_rid;
-
- /* can't handle group rids right now. This is such a mess.... */
-
- if ( rid_type == GROUP_RID_TYPE )
- return NT_STATUS_UNSUCCESSFUL;
-
- /* cannot fail since idmap is only called winbindd */
-
- get_free_rid_range( &lowrid, &highrid );
-
- tmp_rid = lowrid;
-
- if ( !tdb_change_uint32_atomic(idmap_tdb, "RID_COUNTER", &tmp_rid, RID_MULTIPLIER) ) {
- DEBUG(3,("db_allocate_rid: Failed to locate next rid record in idmap db\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if ( tmp_rid > highrid ) {
- DEBUG(0, ("db_allocate_rid: no RIDs available!\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- *rid = tmp_rid;
-
- return NT_STATUS_OK;
-}
-
-/**********************************************************************
Allocate either a user or group id from the pool
**********************************************************************/
@@ -660,7 +622,6 @@ TDB_CONTEXT *idmap_tdb_handle( void )
static struct idmap_methods db_methods = {
db_idmap_init,
- db_allocate_rid,
db_allocate_id,
db_get_sid_from_id,
db_get_id_from_sid,
diff --git a/source/sam/idmap_util.c b/source/sam/idmap_util.c
index cac8934f7b6..7233cb48cd1 100644
--- a/source/sam/idmap_util.c
+++ b/source/sam/idmap_util.c
@@ -22,80 +22,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_IDMAP
-#if 0 /* NOT USED */
-
-/**********************************************************************
- Get the free RID base if idmap is configured, otherwise return 0
-**********************************************************************/
-
-uint32 idmap_get_free_rid_base(void)
-{
- uint32 low, high;
- if (idmap_get_free_rid_range(&low, &high)) {
- return low;
- }
- return 0;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-BOOL idmap_check_ugid_is_in_free_range(uint32 id)
-{
- uint32 low, high;
-
- if (!idmap_get_free_ugid_range(&low, &high)) {
- return False;
- }
- if (id < low || id > high) {
- return False;
- }
- return True;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-BOOL idmap_check_rid_is_in_free_range(uint32 rid)
-{
- uint32 low, high;
-
- if (!idmap_get_free_rid_range(&low, &high)) {
- return False;
- }
- if (rid < algorithmic_rid_base()) {
- return True;
- }
-
- if (rid < low || rid > high) {
- return False;
- }
-
- return True;
-}
-
-/**********************************************************************
- if it is a foreign SID or if the SID is in the free range, return true
-**********************************************************************/
-
-BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid)
-{
- if (sid_compare_domain(get_global_sam_sid(), sid) == 0) {
-
- uint32 rid;
-
- if (sid_peek_rid(sid, &rid)) {
- return idmap_check_rid_is_in_free_range(rid);
- }
-
- return False;
- }
-
- return True;
-}
-
-#endif /* NOT USED */
-
/*****************************************************************
Returns SID pointer.
*****************************************************************/
diff --git a/source/script/installbin.sh b/source/script/installbin.sh.in
index f9fd5298c09..6c578b3971a 100755
--- a/source/script/installbin.sh
+++ b/source/script/installbin.sh.in
@@ -2,12 +2,8 @@
INSTALLPERMS=$1
DESTDIR=$2
-BASEDIR=`echo $3 | sed 's/\/\//\//g'`
+prefix=`echo $3 | sed 's/\/\//\//g'`
BINDIR=`echo $4 | sed 's/\/\//\//g'`
-LIBDIR=`echo $5 | sed 's/\/\//\//g'`
-VARDIR=`echo $6 | sed 's/\/\//\//g'`
-shift
-shift
shift
shift
shift
@@ -15,20 +11,21 @@ shift
for p in $*; do
p2=`basename $p`
- echo Installing $p as $BINDIR/$p2
- if [ -f $BINDIR/$p2 ]; then
- rm -f $BINDIR/$p2.old
- mv $BINDIR/$p2 $BINDIR/$p2.old
+ echo "Installing $p as $DESTDIR/$BINDIR/$p2 "
+ if [ -f $DESTDIR/$BINDIR/$p2 ]; then
+ rm -f $DESTDIR/$BINDIR/$p2.old
+ mv $DESTDIR/$BINDIR/$p2 $DESTDIR/$BINDIR/$p2.old
fi
- cp $p $BINDIR/
- chmod $INSTALLPERMS $BINDIR/$p2
+ cp $p $DESTDIR/$BINDIR/
+ chmod $INSTALLPERMS $DESTDIR/$BINDIR/$p2
# this is a special case, mount needs this in a specific location
if [ $p2 = smbmount ]; then
- if [ ! -d $DESTDIR/sbin ]; then
- mkdir $DESTDIR/sbin
- fi
- ln -sf $BINDIR/$p2 $DESTDIR/sbin/mount.smbfs
+ if [ ! -d $DESTDIR/@rootsbindir@ ]; then
+ mkdir $DESTDIR/@rootsbindir@
+ fi
+ echo "Creating sym link $DESTDIR/@rootsbindir@/mount.smbfs to $BINDIR/$p2 "
+ ln -sf $BINDIR/$p2 $DESTDIR/@rootsbindir@/mount.smbfs
fi
done
diff --git a/source/script/installdat.sh b/source/script/installdat.sh
index 4a5b1de5dc8..59bf2f919dd 100755
--- a/source/script/installdat.sh
+++ b/source/script/installdat.sh
@@ -1,23 +1,65 @@
#!/bin/sh
#fist version March 2002, Herb Lewis
-DATDIR=`echo $1 | sed 's/\/\//\//g'`
-SRCDIR=$2/
+DESTDIR=$1
+DATDIR=`echo $2 | sed 's/\/\//\//g'`
+SRCDIR=$3/
+shift
+shift
+shift
-echo Installing dat files in $DATDIR
+case $0 in
+ *uninstall*)
+ if test ! -d "$DESTDIR/$DATDIR"; then
+ echo "Directory $DESTDIR/$DATDIR does not exist! "
+ echo "Do a "make installmsg" or "make install" first. "
+ exit 1
+ fi
+ mode='uninstall'
+ ;;
+ *) mode='install' ;;
+esac
for f in $SRCDIR/codepages/*.dat; do
- FNAME=$DATDIR/`basename $f`
- echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ FNAME="$DESTDIR/$DATDIR/`basename $f`"
+ if test "$mode" = 'install'; then
+ echo "Installing $f as $FNAME "
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 "$FNAME"
+ elif test "$mode" = 'uninstall'; then
+ echo "Removing $FNAME "
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ else
+ echo "Unknown mode, $mode. Script called as $0 "
+ exit 1
+ fi
done
-cat << EOF
+if test "$mode" = 'install'; then
+ cat << EOF
======================================================================
-The dat files have been installed.
+The dat files have been installed. You may uninstall the dat files
+using the command "make uninstalldat" or "make uninstall" to uninstall
+binaries, man pages, dat files, and shell scripts.
======================================================================
EOF
+else
+ cat << EOF
+======================================================================
+The dat files have been removed. You may restore these files using
+the command "make installdat" or "make install" to install binaries,
+man pages, modules, dat files, and shell scripts.
+======================================================================
+EOF
+fi
exit 0
diff --git a/source/script/installdirs.sh b/source/script/installdirs.sh
index 1db46b82ff2..062b34b8c69 100755
--- a/source/script/installdirs.sh
+++ b/source/script/installdirs.sh
@@ -1,19 +1,18 @@
#!/bin/sh
-while ( test -n "$1" ); do
+INSTALLPERMS=$1
+DESTDIR=`echo $2 | sed 's/\/\//\//g'`
+shift
+shift
- DIRNAME=`echo $1 | sed 's/\/\//\//g'`
- if [ ! -d $DIRNAME ]; then
- mkdir -p $DIRNAME
+for dir in $@; do
+ DIRNAME=`echo $dir | sed 's/\/\//\//g'`
+ if [ ! -d $DESTDIR/$DIRNAME ]; then
+ mkdir -m $INSTALLPERMS -p $DESTDIR/$DIRNAME
fi
- if [ ! -d $DIRNAME ]; then
- echo Failed to make directory $1
+ if [ ! -d $DESTDIR/$DIRNAME ]; then
+ echo "Failed to make directory $DESTDIR/$DIRNAME "
exit 1
fi
-
- shift;
done
-
-
-
diff --git a/source/script/installman.sh b/source/script/installman.sh
index 9235217ff00..3bbca1a8aa5 100755
--- a/source/script/installman.sh
+++ b/source/script/installman.sh
@@ -19,7 +19,8 @@ if test ! -d $SRCDIR../docs/manpages; then
fi
# Get the configured feature set
-test -f "${SRCDIR}/config.log" && eval `grep '^[A-Za-z0-9]*=.*' ${SRCDIR}/config.log`
+test -f "${SRCDIR}/config.log" && \
+ eval $( grep "^[[:alnum:]]*=.*" "${SRCDIR}/config.log")
for lang in $langs; do
if [ "X$lang" = XC ]; then
@@ -43,7 +44,7 @@ for lang in $langs; do
for sect in 1 5 7 8 ; do
for m in $langdir/man$sect ; do
for s in $SRCDIR../docs/manpages/$lang/*$sect; do
- MP_BASENAME=`basename $s`
+ MP_BASENAME=${s##*/}
# Check if this man page if required by the configured feature set
case "${MP_BASENAME}" in
diff --git a/source/script/installmodules.sh b/source/script/installmodules.sh
index f7c74733381..f6e52880fe8 100755
--- a/source/script/installmodules.sh
+++ b/source/script/installmodules.sh
@@ -1,17 +1,19 @@
#!/bin/sh
INSTALLPERMS=$1
-BASEDIR=`echo $2 | sed 's/\/\//\//g'`
-LIBDIR=`echo $3 | sed 's/\/\//\//g'`
+DESTDIR=$2
+prefix=`echo $3 | sed 's/\/\//\//g'`
+LIBDIR=`echo $4 | sed 's/\/\//\//g'`
+shift
shift
shift
shift
-for d in $BASEDIR $LIBDIR; do
-if [ ! -d $d ]; then
-mkdir $d
-if [ ! -d $d ]; then
- echo Failed to make directory $d
+for d in $prefix $LIBDIR; do
+if [ ! -d $DESTDIR/$d ]; then
+mkdir $DESTDIR/$d
+if [ ! -d $DESTDIR/$d ]; then
+ echo Failed to make directory $DESTDIR/$d
exit 1
fi
fi
@@ -19,9 +21,9 @@ done
for p in $*; do
p2=`basename $p`
- echo Installing $p as $LIBDIR/$p2
- cp -f $p $LIBDIR/
- chmod $INSTALLPERMS $LIBDIR/$p2
+ echo Installing $p as $DESTDIR/$LIBDIR/$p2
+ cp -f $p $DESTDIR/$LIBDIR/
+ chmod $INSTALLPERMS $DESTDIR/$LIBDIR/$p2
done
exit 0
diff --git a/source/script/installmsg.sh b/source/script/installmsg.sh
index 5a41fe1ca8d..859e4c10cf9 100644
--- a/source/script/installmsg.sh
+++ b/source/script/installmsg.sh
@@ -2,22 +2,64 @@
# first version (Sept 2003) written by Shiro Yamada <shiro@miraclelinux.com>
# based on the first verion (March 2002) of installdat.sh written by Herb Lewis
-MSGDIR=`echo $1 | sed 's/\/\//\//g'`
-SRCDIR=$2/
+DESTDIR=$1
+MSGDIR=`echo $2 | sed 's/\/\//\//g'`
+SRCDIR=$3/
+shift
+shift
+shift
-echo Installing msg files in $MSGDIR
+case $0 in
+ *uninstall*)
+ if test ! -d "$DESTDIR/$MSGDIR"; then
+ echo "Directory $DESTDIR/$MSGDIR does not exist! "
+ echo "Do a "make installmsg" or "make install" first. "
+ exit 1
+ fi
+ mode='uninstall'
+ ;;
+ *) mode='install' ;;
+esac
for f in $SRCDIR/po/*.msg; do
- FNAME=$MSGDIR/`basename $f`
- echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ FNAME="$DESTDIR/$MSGDIR/`basename $f`"
+ if test "$mode" = 'install'; then
+ echo "Installing $f as $FNAME "
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 "$FNAME"
+ elif test "$mode" = 'uninstall'; then
+ echo "Removing $FNAME "
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ else
+ echo "Unknown mode, $mode. Script called as $0 "
+ exit 1
+ fi
done
-cat << EOF
-======================================================================
-The msg files have been installed.
+if test "$mode" = 'install'; then
+ cat << EOF
+==============================================================================
+The SWAT msg files have been installed. You may uninstall the msg files using
+the command "make uninstallmsg" or "make uninstall" to uninstall binaries, man
+pages, msg files, and shell scripts.
+==============================================================================
+EOF
+else
+ cat << EOF
+=============================================================================
+The SWAT msg files have been removed. You may restore these files using the
+command "make installmsg" or "make install" to install binaries, man pages,
+modules, msg files, and shell scripts.
======================================================================
EOF
+fi
exit 0
diff --git a/source/script/installswat.sh b/source/script/installswat.sh
index c66fd29485d..427e1773620 100755
--- a/source/script/installswat.sh
+++ b/source/script/installswat.sh
@@ -1,77 +1,152 @@
#!/bin/sh
#first version March 1998, Andrew Tridgell
-SWATDIR=`echo $1 | sed 's/\/\//\//g'`
-SRCDIR=$2/
-BOOKDIR=$SWATDIR/help/using_samba
+DESTDIR=$1
+SWATDIR=`echo $2 | sed 's/\/\//\//g'`
+SRCDIR=$3/
+BOOKDIR="$DESTDIR/$SWATDIR/using_samba"
-echo Installing SWAT in $SWATDIR
-echo Installing the Samba Web Administration Tool
+case $0 in
+ *uninstall*)
+ echo "Removing SWAT from $DESTDIR/$SWATDIR "
+ echo "Removing the Samba Web Administration Tool "
+ echo -n "Removed "
+ mode='uninstall'
+ ;;
+ *)
+ echo "Installing SWAT in $DESTDIR/$SWATDIR "
+ echo "Installing the Samba Web Administration Tool "
+ echo -n "Installing "
+ mode='install'
+ ;;
+esac
LANGS=". `cd $SRCDIR../swat/; /bin/echo lang/??`"
-echo Installing langs are `cd $SRCDIR../swat/lang/; /bin/echo ??`
+echo "langs are `cd $SRCDIR../swat/lang/; /bin/echo ??` "
-for ln in $LANGS; do
- SWATLANGDIR=$SWATDIR/$ln
- for d in $SWATLANGDIR $SWATLANGDIR/help $SWATLANGDIR/images \
- $SWATLANGDIR/include; do
+if test "$mode" = 'install'; then
+ for ln in $LANGS; do
+ SWATLANGDIR="$DESTDIR/$SWATDIR/$ln"
+ for d in $SWATLANGDIR $SWATLANGDIR/help $SWATLANGDIR/images \
+ $SWATLANGDIR/include $SWATLANGDIR/js; do
+ if [ ! -d $d ]; then
+ mkdir -p $d
if [ ! -d $d ]; then
- mkdir -p $d
- if [ ! -d $d ]; then
- echo Failed to make directory $d, does $USER have privileges?
- exit 1
- fi
+ echo "Failed to make directory $d, does $USER have privileges? "
+ exit 1
fi
+ fi
+ done
done
-done
+fi
-# Install images
for ln in $LANGS; do
- for f in $SRCDIR../swat/$ln/images/*.gif; do
- if [ ! -f $f ] ; then
- continue
+ # images
+ for f in $SRCDIR../swat/$ln/images/*.png; do
+ if [ ! -f $f ] ; then
+ continue
+ fi
+ FNAME="$DESTDIR/$SWATDIR/$ln/images/`basename $f`"
+ echo $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
fi
- FNAME=$SWATDIR/$ln/images/`basename $f`
- echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ chmod 0644 "$FNAME"
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ else
+ echo "Unknown mode, $mode. Script called as $0 "
+ exit 1
+ fi
done
- # Install html help
-
+ # html help
for f in $SRCDIR../swat/$ln/help/*.html; do
- if [ ! -f $f ] ; then
- continue
- fi
- FNAME=$SWATDIR/$ln/help/`basename $f`
- echo $FNAME
+ if [ ! -f $f ] ; then
+ continue
+ fi
+ FNAME="$DESTDIR/$SWATDIR/$ln/help/`basename $f`"
+ echo $FNAME
+ if test "$mode" = 'install'; then
if [ "x$BOOKDIR" = "x" ]; then
cat $f | sed 's/@BOOKDIR@.*$//' > $f.tmp
else
cat $f | sed 's/@BOOKDIR@//' > $f.tmp
fi
f=$f.tmp
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- rm -f $f
- chmod 0644 $FNAME
+ cp "$f" "$FNAME"
+ rm -f "$f"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 "$FNAME"
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
- # Install "server-side" includes
+ # "server-side" includes
+ for f in $SRCDIR../swat/$ln/include/*; do
+ if [ ! -f $f ] ; then
+ continue
+ fi
+ FNAME="$DESTDIR/$SWATDIR/$ln/include/`basename $f`"
+ echo $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
+ done
- for f in $SRCDIR../swat/$ln/include/*.html; do
+ # javascripts
+ for f in $SRCDIR../swat/$ln/js/*.js; do
if [ ! -f $f ] ; then
continue
fi
- FNAME=$SWATDIR/$ln/include/`basename $f`
+ FNAME="$DESTDIR/$SWATDIR/$ln/js/`basename $f`"
echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
done
-# Install html documentation (if html documentation tree is here)
+# Install/ remove html documentation (if html documentation tree is here)
if [ -d $SRCDIR../docs/htmldocs/ ]; then
@@ -82,47 +157,75 @@ if [ -d $SRCDIR../docs/htmldocs/ ]; then
continue
fi
- INSTALLDIR=$SWATDIR/help/`echo $dir | sed 's/htmldocs\///g'`
- if [ ! -d $INSTALLDIR ]; then
- mkdir $INSTALLDIR
+ INSTALLDIR="$DESTDIR/$SWATDIR/help/`echo $dir | sed 's/htmldocs\///g'`"
+ if test ! -d "$INSTALLDIR" -a "$mode" = 'install'; then
+ mkdir "$INSTALLDIR"
+ if test ! -d "$INSTALLDIR"; then
+ echo "Failed to make directory $INSTALLDIR, does $USER have privileges? "
+ exit 1
+ fi
fi
for f in $SRCDIR../docs/$dir/*.html; do
FNAME=$INSTALLDIR/`basename $f`
echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
- if [ -d $SRCDIR../docs/$dir/images/ ]; then
- if [ ! -d $INSTALLDIR/images/ ]; then
- mkdir $INSTALLDIR/images
- if [ ! -d $INSTALLDIR/images/ ]; then
- echo Failed to make directory $SWATDIR/help/images, does $USER have privileges?
+ if test -d "$SRCDIR../docs/$dir/images/"; then
+ if test ! -d "$INSTALLDIR/images/" -a "$mode" = 'install'; then
+ mkdir "$INSTALLDIR/images"
+ if test ! -d "$INSTALLDIR/images/"; then
+ echo "Failed to make directory $INSTALLDIR/images, does $USER have privileges? "
exit 1
fi
fi
for f in $SRCDIR../docs/$dir/images/*.png; do
FNAME=$INSTALLDIR/images/`basename $f`
echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
fi
done
fi
-# Install Using Samba book (but only if it is there)
+# Install/ remove Using Samba book (but only if it is there)
if [ "x$BOOKDIR" != "x" -a -f $SRCDIR../docs/htmldocs/using_samba/toc.html ]; then
# Create directories
for d in $BOOKDIR $BOOKDIR/figs ; do
- if [ ! -d $d ]; then
+ if test ! -d "$d" -a "$mode" = 'install'; then
mkdir $d
- if [ ! -d $d ]; then
- echo Failed to make directory $d, does $USER have privileges?
+ if test ! -d "$d"; then
+ echo "Failed to make directory $d, does $USER have privileges? "
exit 1
fi
fi
@@ -133,15 +236,39 @@ if [ "x$BOOKDIR" != "x" -a -f $SRCDIR../docs/htmldocs/using_samba/toc.html ]; th
for f in $SRCDIR../docs/htmldocs/using_samba/*.html; do
FNAME=$BOOKDIR/`basename $f`
echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
for f in $SRCDIR../docs/htmldocs/using_samba/*.gif; do
FNAME=$BOOKDIR/`basename $f`
echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
# Figures
@@ -149,18 +276,40 @@ if [ "x$BOOKDIR" != "x" -a -f $SRCDIR../docs/htmldocs/using_samba/toc.html ]; th
for f in $SRCDIR../docs/htmldocs/using_samba/figs/*.gif; do
FNAME=$BOOKDIR/figs/`basename $f`
echo $FNAME
- cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
- chmod 0644 $FNAME
+ if test "$mode" = 'install'; then
+ cp "$f" "$FNAME"
+ if test ! -f "$FNAME"; then
+ echo "Cannot install $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ chmod 0644 $FNAME
+ elif test "$mode" = 'uninstall'; then
+ rm -f "$FNAME"
+ if test -f "$FNAME"; then
+ echo "Cannot remove $FNAME. Does $USER have privileges? "
+ exit 1
+ fi
+ fi
done
fi
-cat << EOF
+if test "$mode" = 'install'; then
+ cat << EOF
======================================================================
The SWAT files have been installed. Remember to read the documentation
for information on enabling and using SWAT
======================================================================
EOF
+else
+ cat << EOF
+======================================================================
+The SWAT files have been removed. You may restore these files using
+the command "make installswat" or "make install" to install binaries,
+man pages, modules, SWAT, and shell scripts.
+======================================================================
+EOF
+fi
exit 0
diff --git a/source/script/tests/dlopen.sh b/source/script/tests/dlopen.sh
new file mode 100755
index 00000000000..61279536927
--- /dev/null
+++ b/source/script/tests/dlopen.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+#
+# Copyright (C) Nalin Dahyabhai <nalin@redhat.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.
+
+tempdir=`mktemp -d /tmp/dlopenXXXXXX`
+test -n "$tempdir" || exit 1
+cat >> $tempdir/dlopen.c << _EOF
+#include <dlfcn.h>
+#include <stdio.h>
+#include <limits.h>
+#include <sys/stat.h>
+/* Simple program to see if dlopen() would succeed. */
+int main(int argc, char **argv)
+{
+ int i;
+ struct stat st;
+ char buf[PATH_MAX];
+ for (i = 1; i < argc; i++) {
+ if (dlopen(argv[i], RTLD_NOW)) {
+ fprintf(stdout, "dlopen() of \"%s\" succeeded.\n",
+ argv[i]);
+ } else {
+ snprintf(buf, sizeof(buf), "./%s", argv[i]);
+ if ((stat(buf, &st) == 0) && dlopen(buf, RTLD_NOW)) {
+ fprintf(stdout, "dlopen() of \"./%s\" "
+ "succeeded.\n", argv[i]);
+ } else {
+ fprintf(stdout, "dlopen() of \"%s\" failed: "
+ "%s\n", argv[i], dlerror());
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+_EOF
+
+for arg in $@ ; do
+ case "$arg" in
+ "")
+ ;;
+ -I*|-D*|-f*|-m*|-g*|-O*|-W*)
+ cflags="$cflags $arg"
+ ;;
+ -l*|-L*)
+ ldflags="$ldflags $arg"
+ ;;
+ /*)
+ modules="$modules $arg"
+ ;;
+ *)
+ modules="$modules $arg"
+ ;;
+ esac
+done
+
+${CC:-gcc} $RPM_OPT_FLAGS $CFLAGS -o $tempdir/dlopen $cflags $tempdir/dlopen.c $ldflags -ldl
+
+retval=0
+for module in $modules ; do
+ case "$module" in
+ "")
+ ;;
+ /*)
+ $tempdir/dlopen "$module"
+ retval=$?
+ ;;
+ *)
+ $tempdir/dlopen ./"$module"
+ retval=$?
+ ;;
+ esac
+done
+
+rm -f $tempdir/dlopen $tempdir/dlopen.c
+rmdir $tempdir
+exit $retval
diff --git a/source/script/tests/functions b/source/script/tests/functions
deleted file mode 100644
index 8cb8f0b1550..00000000000
--- a/source/script/tests/functions
+++ /dev/null
@@ -1,82 +0,0 @@
-##
-## library file for test functions
-##
-
-##
-## start/stop smbd daemon
-##
-check_smbd_running()
-{
- ## the smbcontrol ping will return a 0 on success
- smbcontrol $CONFIGURATION smbd ping 2>&1 > /dev/null
-}
-
-start_smbd()
-{
- echo "Starting smbd...."
-
- smbd $CONFIGURATION || return $?
-
- sleep 1
-
- smbcontrol $CONFIGURATION `cat $PIDDIR/smbd.pid` ping 2>&1 > /dev/null || return $?
-}
-
-stop_smbd()
-{
- smbd_pid=`cat $PIDDIR/smbd.pid`
- echo "Shutting down smbd (pid $smbd_pid)..."
-
- ## belt and braces; first kill and then send a shutdown message
-
- kill -TERM $smbd_pid
- smbcontrol $CONFIGURATION smbd shutdown
-
- ## check to see if smbd is already running
- check_smbd_running
- if test $? = 0; then
- echo "Unable to stop smbd!"
- exit 2
- fi
-}
-
-
-##
-## start/stop smbd daemon
-##
-check_nmbd_running()
-{
- ## the smbcontrol ping will return a 0 on success
- smbcontrol $CONFIGURATION nmbd ping 2>&1 > /dev/null
-}
-
-start_nmbd()
-{
- echo "Starting nmbd...."
-
- nmbd $CONFIGURATION || return $?
-
- sleep 1
-
- # smbcontrol $CONFIGURATION `cat $PIDDIR/nmbd.pid` ping 2>&1 > /dev/null || return $?
- kill -0 `cat $PIDDIR/nmbd.pid`
-}
-
-stop_nmbd()
-{
- nmbd_pid=`cat $PIDDIR/nmbd.pid`
- echo "Shutting down nmbd (pid $nmbd_pid)..."
-
- ## belt and braces; first kill and then send a shutdown message
-
- kill -TERM $nmbd_pid 2> /dev/null
- sleep 1
-
- ## check to see if smbd is already running
- kill -0 $nmbd_pid 2> /dev/null
- if test $? = 0; then
- echo "Unable to stop nmbd!"
- exit 2
- fi
-}
-
diff --git a/source/script/tests/runtests.sh b/source/script/tests/runtests.sh
deleted file mode 100644
index ddaf94e8ac5..00000000000
--- a/source/script/tests/runtests.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/sh
-
-if [ "x$1" = "x" ]; then
- echo "$0 <directory>"
- exit 1
-fi
-
-if [ $# = 2 ]; then
- testnum=$2
-fi
-
-##
-## create the test directory
-##
-PREFIX=`echo $1 | sed s+//+/+`
-mkdir -p $PREFIX || exit $?
-OLD_PWD=`pwd`
-cd $PREFIX || exit $?
-export PREFIX_ABS=`pwd`
-cd $OLD_PWD
-
-##
-## setup the various environment variables we need
-##
-
-USERNAME=`whoami`
-PASSWORD=test
-
-SRCDIR=`pwd`
-SCRIPTDIR=$SRCDIR/script/tests
-SHRDIR=$PREFIX_ABS/tmp
-LIBDIR=$PREFIX_ABS/lib
-PIDDIR=$PREFIX_ABS/pid
-CONFFILE=$LIBDIR/smb.conf
-PRIVATEDIR=$PREFIX_ABS/private
-LOCKDIR=$PREFIX_ABS/lockdir
-LOGDIR=$PREFIX_ABS/logs
-SOCKET_WRAPPER_DIR=$PREFIX_ABS/sockwrap
-CONFIGURATION="-s $CONFFILE"
-PATH=`pwd`/bin:$PATH
-
-export PREFIX_ABS CONFIGURATION CONFFILE PATH SOCKET_WRAPPER_DIR DOMAIN
-export PRIVATEDIR LIBDIR PIDDIR LOCKDIR LOGDIR
-export SRCDIR SCRIPTDIR
-export USERNAME PASSWORD
-
-
-##
-## verify that we were built with --enable-socket-wrapper
-##
-
-if test "x`smbd -b | grep SOCKET_WRAPPER`" = "x"; then
- echo "***"
- echo "*** You must include --enable-socket-wrapper when compiling Samba"
- echo "*** in order to execute 'make test'. Exiting...."
- echo "***"
- exit 1
-fi
-
-##
-## create the test directory layout
-##
-
-/bin/rm -rf $PREFIX/*
-mkdir -p $PRIVATEDIR $LIBDIR $PIDDIR $LOCKDIR $LOGDIR $SOCKET_WRAPPER_DIR
-
-##
-## Create the common config include file with the basic settings
-##
-
-cat >$LIBDIR/common.conf<<EOF
- netbios name = LOCALHOST
- workgroup = SAMBA-TEST
-
- private dir = $PRIVATEDIR
- pid directory = $PIDDIR
- lock directory = $LOCKDIR
- log file = $LOGDIR/log.%m
- log level = 0
-
- passdb backend = tdbsam
-
- interfaces = lo
- bind interfaces only = yes
-
- panic action = $SCRIPTDIR/gdb_backtrace %d
-EOF
-
-cat >$LIBDIR/smb.conf<<EOF
-[global]
- include = $LIBDIR/common.conf
-EOF
-
-
-##
-## create a test account
-##
-
-(echo $PASSWORD; echo $PASSWORD) | smbpasswd -c $LIBDIR/smb.conf -L -s -a $USERNAME
-
-
-##
-## ready to go...now loop through the tests
-##
-
-if [ -f $SCRIPTDIR/t_$testnum.sh ]; then
- testfile=$SCRIPTDIR/t_$testnum.sh
- echo ">>>>>> Starting test driver `basename $testfile` <<<<<"
- sh $testfile
- if [ $? = 0 ]; then
- echo ">>>>> test ok <<<<<"
- else
- echo ">>>>> test failed <<<<<"
- fi
-
- exit 0
-fi
-
-for testfile in `ls $SCRIPTDIR/t_*sh | sort`; do
- echo " "
- echo ">>>>>> Starting test driver `basename $testfile` <<<<<"
- sh $testfile
- if [ $? = 0 ]; then
- echo ">>>>> test ok <<<<<"
- else
- echo ">>>>> test failed <<<<<"
- fi
-done
-
diff --git a/source/script/tests/selftest.sh b/source/script/tests/selftest.sh
new file mode 100755
index 00000000000..e7b29f76c7a
--- /dev/null
+++ b/source/script/tests/selftest.sh
@@ -0,0 +1,211 @@
+#!/bin/sh
+
+if [ $# != 3 ]; then
+ echo "$0 <directory> <all | quick> <smbtorture4>"
+ exit 1
+fi
+
+SMBTORTURE4=$3
+TESTS=$2
+
+##
+## create the test directory
+##
+PREFIX=`echo $1 | sed s+//+/+`
+mkdir -p $PREFIX || exit $?
+OLD_PWD=`pwd`
+cd $PREFIX || exit $?
+export PREFIX_ABS=`pwd`
+cd $OLD_PWD
+
+if [ -z "$TORTURE_MAXTIME" ]; then
+ TORTURE_MAXTIME=300
+fi
+export TORTURE_MAXTIME
+
+##
+## setup the various environment variables we need
+##
+
+SERVER=localhost2
+SERVER_IP=127.0.0.2
+USERNAME=`whoami`
+PASSWORD=test
+
+SRCDIR=`pwd`
+SCRIPTDIR=$SRCDIR/script/tests
+SHRDIR=$PREFIX_ABS/tmp
+LIBDIR=$PREFIX_ABS/lib
+PIDDIR=$PREFIX_ABS/pid
+CONFFILE=$LIBDIR/client.conf
+SERVERCONFFILE=$LIBDIR/server.conf
+COMMONCONFFILE=$LIBDIR/common.conf
+PRIVATEDIR=$PREFIX_ABS/private
+LOCKDIR=$PREFIX_ABS/lockdir
+LOGDIR=$PREFIX_ABS/logs
+SOCKET_WRAPPER_DIR=$PREFIX/sw
+CONFIGURATION="-s $CONFFILE"
+
+export PREFIX_ABS CONFIGURATION CONFFILE PATH SOCKET_WRAPPER_DIR DOMAIN
+export PRIVATEDIR LIBDIR PIDDIR LOCKDIR LOGDIR SERVERCONFFILE
+export SRCDIR SCRIPTDIR
+export USERNAME PASSWORD
+export SMBTORTURE4
+export SERVER SERVER_IP
+
+PATH=bin:$PATH
+export PATH
+
+##
+## verify that we were built with --enable-socket-wrapper
+##
+
+if test "x`smbd -b | grep SOCKET_WRAPPER`" = "x"; then
+ echo "***"
+ echo "*** You must include --enable-socket-wrapper when compiling Samba"
+ echo "*** in order to execute 'make test'. Exiting...."
+ echo "***"
+ exit 1
+fi
+
+##
+## create the test directory layout
+##
+echo -n "CREATE TEST ENVIRONMENT IN '$PREFIX'"...
+/bin/rm -rf $PREFIX/*
+mkdir -p $PRIVATEDIR $LIBDIR $PIDDIR $LOCKDIR $LOGDIR $SOCKET_WRAPPER_DIR
+mkdir -p $PREFIX_ABS/tmp
+chmod 777 $PREFIX_ABS/tmp
+
+##
+## Create the common config include file with the basic settings
+##
+
+cat >$COMMONCONFFILE<<EOF
+ workgroup = SAMBA-TEST
+
+ private dir = $PRIVATEDIR
+ pid directory = $PIDDIR
+ lock directory = $LOCKDIR
+ log file = $LOGDIR/log.%m
+ log level = 0
+
+ passdb backend = tdbsam
+
+ name resolve order = bcast
+
+ panic action = $SCRIPTDIR/gdb_backtrace %d
+EOF
+
+cat >$CONFFILE<<EOF
+[global]
+ netbios name = TORTURE26
+ interfaces = 127.0.0.26/8
+ include = $COMMONCONFFILE
+EOF
+
+cat >$SERVERCONFFILE<<EOF
+[global]
+ netbios name = $SERVER
+ interfaces = $SERVER_IP/8
+ bind interfaces only = yes
+ include = $COMMONCONFFILE
+
+[tmp]
+ path = $PREFIX_ABS/tmp
+ read only = no
+ smbd:sharedelay = 100000
+EOF
+
+
+##
+## create a test account
+##
+
+(echo $PASSWORD; echo $PASSWORD) | \
+ smbpasswd -c $CONFFILE -L -s -a $USERNAME >/dev/null || exit 1
+
+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"
+export NMBD_TEST_LOG
+SMBD_TEST_LOG="$PREFIX/smbd_test.log"
+export SMBD_TEST_LOG
+
+# start off with 0 failures
+failed=0
+export failed
+
+. $SCRIPTDIR/test_functions.sh
+
+SOCKET_WRAPPER_DEFAULT_IFACE=2
+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
+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"
+export TORTURE4_OPTIONS
+
+if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
+ TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=\"torture:progress=no\""
+fi
+
+##
+## ready to go...now loop through the tests
+##
+
+START=`date`
+(
+ # give time for nbt server to register its names
+ echo "delaying for nbt name registration"
+ sleep 4
+ # This will return quickly when things are up, but be slow if we need to wait for (eg) SSL init
+ bin/nmblookup $CONFIGURATION -U $SERVER_IP __SAMBA__
+ bin/nmblookup $CONFIGURATION __SAMBA__
+ bin/nmblookup $CONFIGURATION -U 127.255.255.255 __SAMBA__
+ bin/nmblookup $CONFIGURATION -U $SERVER_IP $SERVER
+ 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
+
+ failed=0
+
+ . $SCRIPTDIR/tests_$TESTS.sh
+ exit $failed
+)
+failed=$?
+
+samba3_stop_sig_term
+
+END=`date`
+echo "START: $START ($0)";
+echo "END: $END ($0)";
+
+# if there were any valgrind failures, show them
+count=`find $PREFIX -name 'valgrind.log*' | wc -l`
+if [ "$count" != 0 ]; then
+ for f in $PREFIX/valgrind.log*; do
+ if [ -s $f ]; then
+ echo "VALGRIND FAILURE";
+ failed=`expr $failed + 1`
+ cat $f
+ fi
+ done
+fi
+
+sleep 2
+samba3_stop_sig_kill
+
+teststatus $0 $failed
diff --git a/source/script/tests/t_001.sh b/source/script/tests/t_001.sh
deleted file mode 100644
index 6d54d0e4895..00000000000
--- a/source/script/tests/t_001.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-
-. $SCRIPTDIR/functions
-
-cat >$CONFFILE<<EOF
-[global]
- include = $LIBDIR/common.conf
- smb ports = 139
-
-[test]
- path = $PREFIX_ABS/tmp
- read only = no
-EOF
-
-##
-## Test code
-##
-
-/bin/rm -rf $PREFIX_ABS/tmp
-mkdir $PREFIX_ABS/tmp
-chmod 1777 $PREFIX_ABS/tmp
-
-start_smbd || exit $?
-
-smbclient $CONFIGURATION -L localhost -N -p 139
-ret=$?
-
-stop_smbd
-
-exit $ret
diff --git a/source/script/tests/t_002.sh b/source/script/tests/t_002.sh
deleted file mode 100644
index 42070bed80a..00000000000
--- a/source/script/tests/t_002.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-
-. $SCRIPTDIR/functions
-
-cat >$CONFFILE<<EOF
-[global]
- include = $LIBDIR/common.conf
-
-[test]
- path = $PREFIX_ABS/tmp
- read only = no
-EOF
-
-##
-## Test code
-##
-
-/bin/rm -rf $PREFIX_ABS/tmp
-mkdir $PREFIX_ABS/tmp
-chmod 1777 $PREFIX_ABS/tmp
-
-
-start_smbd || exit $?
-
-smbtorture //localhost/test -U${USERNAME}%${PASSWORD} FDPASS
-ret=$?
-
-stop_smbd
-
-exit $ret
diff --git a/source/script/tests/test_functions.sh b/source/script/tests/test_functions.sh
new file mode 100644
index 00000000000..4e3b8ce7db8
--- /dev/null
+++ b/source/script/tests/test_functions.sh
@@ -0,0 +1,221 @@
+
+samba3_stop_sig_term() {
+ RET=0
+ kill -USR1 `cat $PIDDIR/timelimit.nmbd.pid` >/dev/null 2>&1 || \
+ kill -ALRM `cat $PIDDIR/timelimit.nmbd.pid` || RET=$?
+
+ kill -USR1 `cat $PIDDIR/timelimit.smbd.pid` >/dev/null 2>&1 || \
+ kill -ALRM `cat $PIDDIR/timelimit.smbd.pid` || RET=$?
+
+ return $RET;
+}
+
+samba3_stop_sig_kill() {
+ kill -ALRM `cat $PIDDIR/timelimit.nmbd.pid` >/dev/null 2>&1
+ kill -ALRM `cat $PIDDIR/timelimit.smbd.pid` >/dev/null 2>&1
+ return 0;
+}
+
+samba3_check_or_start() {
+ if [ -n "$SERVER_TEST_FIFO" ];then
+
+ trap samba3_stop_sig_kill SIGINT SIGQUIT
+ trap samba3_stop_sig_kill SIGTERM
+
+ if [ -p "$SERVER_TEST_FIFO" ];then
+ return 0;
+ fi
+
+ if [ -n "$SOCKET_WRAPPER_DIR" ];then
+ if [ -d "$SOCKET_WRAPPER_DIR" ]; then
+ rm -f $SOCKET_WRAPPER_DIR/*
+ else
+ mkdir -p $SOCKET_WRAPPER_DIR
+ fi
+ fi
+
+ rm -f $SERVER_TEST_FIFO
+ mkfifo $SERVER_TEST_FIFO
+
+ rm -f $NMBD_TEST_LOG
+ echo -n "STARTING NMBD..."
+ ((
+ if [ -z "$NMBD_MAXTIME" ]; 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 &
+ TIMELIMIT_NMBD_PID=$!
+ echo $TIMELIMIT_NMBD_PID > $PIDDIR/timelimit.nmbd.pid
+ wait $TIMELIMIT_NMBD_PID
+ ret=$?;
+ rm -f $SERVER_TEST_FIFO
+ if [ -n "$SOCKET_WRAPPER_DIR" -a -d "$SOCKET_WRAPPER_DIR" ]; then
+ rm -f $SOCKET_WRAPPER_DIR/*
+ fi
+ if [ x"$ret" = x"0" ];then
+ echo "nmbd exits with status $ret";
+ echo "nmbd exits with status $ret" >>$NMBD_TEST_LOG;
+ elif [ x"$ret" = x"137" ];then
+ echo "nmbd got SIGXCPU and exits with status $ret!"
+ echo "nmbd got SIGXCPU and exits with status $ret!">>$NMBD_TEST_LOG;
+ else
+ echo "nmbd failed with status $ret!"
+ echo "nmbd failed with status $ret!">>$NMBD_TEST_LOG;
+ fi
+ exit $ret;
+ ) || exit $? &) 2>/dev/null || exit $?
+ echo "DONE"
+
+ rm -f $SMBD_TEST_LOG
+ echo -n "STARTING SMBD..."
+ ((
+ if [ -z "$SMBD_MAXTIME" ]; 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 &
+ TIMELIMIT_SMBD_PID=$!
+ echo $TIMELIMIT_SMBD_PID > $PIDDIR/timelimit.smbd.pid
+ wait $TIMELIMIT_SMBD_PID
+ ret=$?;
+ rm -f $SERVER_TEST_FIFO
+ if [ -n "$SOCKET_WRAPPER_DIR" -a -d "$SOCKET_WRAPPER_DIR" ]; then
+ rm -f $SOCKET_WRAPPER_DIR/*
+ fi
+ if [ x"$ret" = x"0" ];then
+ echo "smbd exits with status $ret";
+ echo "smbd exits with status $ret" >>$SMBD_TEST_LOG;
+ elif [ x"$ret" = x"137" ];then
+ echo "smbd got SIGXCPU and exits with status $ret!"
+ echo "smbd got SIGXCPU and exits with status $ret!">>$SMBD_TEST_LOG;
+ else
+ echo "smbd failed with status $ret!"
+ echo "smbd failed with status $ret!">>$SMBD_TEST_LOG;
+ fi
+ exit $ret;
+ ) || exit $? &) 2>/dev/null || exit $?
+ echo "DONE"
+ fi
+ return 0;
+}
+
+samba3_nmbd_test_log() {
+ if [ -n "$NMBD_TEST_LOG" ];then
+ if [ -r "$NMBD_TEST_LOG" ];then
+ return 0;
+ fi
+ fi
+ return 1;
+}
+
+samba3_smbd_test_log() {
+ if [ -n "$SMBD_TEST_LOG" ];then
+ if [ -r "$SMBD_TEST_LOG" ];then
+ return 0;
+ fi
+ fi
+ return 1;
+}
+
+samba3_check_only() {
+ if [ -n "$SERVER_TEST_FIFO" ];then
+ if [ -p "$SERVER_TEST_FIFO" ];then
+ return 0;
+ fi
+ return 1;
+ fi
+ return 0;
+}
+
+testit() {
+ if [ -z "$PREFIX" ]; then
+ PREFIX=test_prefix
+ mkdir -p $PREFIX
+ fi
+ name=$1
+ shift 1
+ SERVERS_ARE_UP="no"
+ TEST_LOG="$PREFIX/test_log.$$"
+ trap "rm -f $TEST_LOG" EXIT
+ cmdline="$*"
+
+ if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
+ echo "--==--==--==--==--==--==--==--==--==--==--"
+ echo "Running test $name (level 0 stdout)"
+ echo "--==--==--==--==--==--==--==--==--==--==--"
+ date
+ echo "Testing $name"
+ else
+ echo "Testing $name ($failed)"
+ fi
+
+ samba3_check_only && SERVERS_ARE_UP="yes"
+ if [ x"$SERVERS_ARE_UP" != x"yes" ];then
+ if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
+ echo "SERVERS are down! Skipping: $cmdline"
+ echo "=========================================="
+ echo "TEST SKIPPED: $name (reason SERVERS are down)"
+ echo "=========================================="
+ else
+ echo "TEST SKIPPED: $name (reason SERVERS are down)"
+ fi
+ return 1
+ fi
+
+ ( $cmdline > $TEST_LOG 2>&1 )
+ status=$?
+ 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"$RUN_FROM_BUILD_FARM" = x"yes" ];then
+ echo "=========================================="
+ echo "TEST FAILED: $name (status $status)"
+ echo "=========================================="
+ else
+ echo "TEST FAILED: $cmdline (status $status)"
+ fi
+ return 1;
+ fi
+ rm -f $TEST_LOG;
+ if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
+ echo "ALL OK: $cmdline"
+ echo "=========================================="
+ echo "TEST PASSED: $name"
+ echo "=========================================="
+ fi
+ return 0;
+}
+
+testok() {
+ name=`basename $1`
+ failed=$2
+
+ if [ x"$failed" = x"0" ];then
+ :
+ else
+ echo "$failed TESTS FAILED or SKIPPED ($name)";
+ fi
+ exit $failed
+}
+
+teststatus() {
+ name=`basename $1`
+ failed=$2
+
+ if [ x"$failed" = x"0" ];then
+ echo "TEST STATUS: $failed";
+ else
+ echo "TEST STATUS: $failed";
+ fi
+ exit $failed
+}
+
+if [ -z "$VALGRIND" ]; then
+ MALLOC_CHECK_=2
+ export MALLOC_CHECK_
+fi
+
diff --git a/source/script/tests/test_posix_s3.sh b/source/script/tests/test_posix_s3.sh
new file mode 100755
index 00000000000..2f5f92ee807
--- /dev/null
+++ b/source/script/tests/test_posix_s3.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+# this runs the file serving tests that are expected to pass with samba3
+
+if [ $# -lt 3 ]; then
+cat <<EOF
+Usage: test_posix_s3.sh UNC USERNAME PASSWORD <first> <smbtorture args>
+EOF
+exit 1;
+fi
+
+unc="$1"
+username="$2"
+password="$3"
+start="$4"
+shift 4
+ADDARGS="$*"
+
+incdir=`dirname $0`
+. $incdir/test_functions.sh
+
+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-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"
+
+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"
+
+tests="$base"
+
+skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE BASE-DENY1 BASE-OPENATTR BASE-TCONDEV"
+
+echo "WARNING: Skipping tests $skipped"
+
+failed=0
+for t in $tests; do
+ if [ ! -z "$start" -a "$start" != $t ]; then
+ continue;
+ fi
+ skip=0
+ for s in $skipped; do
+ if [ x"$s" = x"$t" ]; then
+ skip=1;
+ break;
+ fi
+ done
+ if [ $skip = 1 ]; then
+ continue;
+ fi
+ start=""
+ name="$t"
+ testit "$name" $VALGRIND $SMBTORTURE4 $TORTURE4_OPTIONS $ADDARGS $unc -U"$username"%"$password" $t || failed=`expr $failed + 1`
+done
+
+testok $0 $failed
diff --git a/source/script/tests/test_smbclient_s3.sh b/source/script/tests/test_smbclient_s3.sh
new file mode 100755
index 00000000000..007f3839f7d
--- /dev/null
+++ b/source/script/tests/test_smbclient_s3.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# this runs the file serving tests that are expected to pass with samba3
+
+if [ $# != 2 ]; then
+cat <<EOF
+Usage: test_smbclient_s3.sh SERVER SERVER_IP
+EOF
+exit 1;
+fi
+
+SERVER="$1"
+SERVER_IP="$2"
+
+incdir=`dirname $0`
+. $incdir/test_functions.sh
+
+failed=0
+
+testit "smbclient -L $SERVER_IP" $VALGRIND $SRCDIR/bin/smbclient $CONFIGURATION -L $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
+testit "smbclient -L $SERVER" $VALGRIND $SRCDIR/bin/smbclient $CONFIGURATION -L $SERVER -N -p 139 || failed=`expr $failed + 1`
+
+testok $0 $failed
diff --git a/source/script/tests/test_smbtorture_s3.sh b/source/script/tests/test_smbtorture_s3.sh
new file mode 100755
index 00000000000..d0e15345df8
--- /dev/null
+++ b/source/script/tests/test_smbtorture_s3.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# this runs the file serving tests that are expected to pass with samba3
+
+if [ $# -lt 3 ]; then
+cat <<EOF
+Usage: test_smbtorture_s3.sh UNC USERNAME PASSWORD <first> <smbtorture args>
+EOF
+exit 1;
+fi
+
+unc="$1"
+username="$2"
+password="$3"
+start="$4"
+shift 4
+ADDARGS="$*"
+
+incdir=`dirname $0`
+. $incdir/test_functions.sh
+
+tests="FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7"
+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"
+
+skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN"
+skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST"
+skipped3="MANGLE UTABLE"
+echo "Skipping the following tests:"
+echo "$skipped1"
+echo "$skipped2"
+echo "$skipped3"
+
+failed=0
+for t in $tests; do
+ if [ ! -z "$start" -a "$start" != $t ]; then
+ continue;
+ fi
+ start=""
+ name="$t"
+ testit "$name" $VALGRIND $SRCDIR/bin/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
new file mode 100755
index 00000000000..64a7065ee97
--- /dev/null
+++ b/source/script/tests/tests_all.sh
@@ -0,0 +1,11 @@
+
+$SCRIPTDIR/test_smbtorture_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" || failed=`expr $failed + $?`
+$SCRIPTDIR/test_smbclient_s3.sh $SERVER $SERVER_IP || failed=`expr $failed + $?`
+
+if [ -n "$SMBTORTURE4" ];then
+ echo "Running Tests with Samba4's smbtorture"
+ $SMBTORTURE4 --version
+ $SCRIPTDIR/test_posix_s3.sh //$SERVER_IP/tmp $USERNAME $PASSWORD "" || failed=`expr $failed + $?`
+else
+ echo "Skip Tests with Samba4's smbtorture"
+fi
diff --git a/source/script/tests/timelimit.c b/source/script/tests/timelimit.c
new file mode 100644
index 00000000000..5b8281cb0dc
--- /dev/null
+++ b/source/script/tests/timelimit.c
@@ -0,0 +1,107 @@
+/* run a command with a limited timeout
+ tridge@samba.org, June 2005
+ metze@samba.org, March 2006
+
+ attempt to be as portable as possible (fighting posix all the way)
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static pid_t child_pid;
+
+static void usage(void)
+{
+ printf("usage: timelimit <time> <command>\n");
+ printf(" SIGUSR1 - passes SIGTERM to command's process group\n");
+ printf(" SIGALRM - passes SIGTERM to command's process group\n");
+ printf(" after 5s SIGKILL will be passed and exit(1)\n");
+ printf(" SIGTERM - passes SIGTERM to command's process group\n");
+ printf(" after 1s SIGKILL will be passed and exit(1)\n");
+}
+
+static void sig_alrm_kill(int sig)
+{
+ fprintf(stderr, "\nMaximum time expired in timelimit - killing\n");
+ kill(-child_pid, SIGKILL);
+ exit(1);
+}
+
+static void sig_alrm_term(int sig)
+{
+ kill(-child_pid, SIGTERM);
+ alarm(5);
+ signal(SIGALRM, sig_alrm_kill);
+}
+
+static void sig_term(int sig)
+{
+ kill(-child_pid, SIGTERM);
+ alarm(1);
+ signal(SIGALRM, sig_alrm_kill);
+}
+
+static void sig_usr1(int sig)
+{
+ kill(-child_pid, SIGTERM);
+}
+
+static void new_process_group(void)
+{
+#ifdef BSD_SETPGRP
+ if (setpgrp(0,0) == -1) {
+ perror("setpgrp");
+ exit(1);
+ }
+#else
+ if (setpgrp() == -1) {
+ perror("setpgrp");
+ exit(1);
+ }
+#endif
+}
+
+
+int main(int argc, char *argv[])
+{
+ int maxtime, ret=1;
+
+ if (argc < 3) {
+ usage();
+ exit(1);
+ }
+
+ maxtime = atoi(argv[1]);
+
+ child_pid = fork();
+ if (child_pid == 0) {
+ new_process_group();
+ execvp(argv[2], argv+2);
+ perror(argv[2]);
+ exit(1);
+ }
+
+ signal(SIGTERM, sig_term);
+ signal(SIGUSR1, sig_usr1);
+ signal(SIGALRM, sig_alrm_term);
+ alarm(maxtime);
+
+ do {
+ int status;
+ pid_t pid = wait(&status);
+ if (pid != -1) {
+ ret = WEXITSTATUS(status);
+ } else if (errno == ECHILD) {
+ break;
+ }
+ } while (1);
+
+ kill(-child_pid, SIGKILL);
+
+ exit(ret);
+}
diff --git a/source/script/uninstallbin.sh b/source/script/uninstallbin.sh
deleted file mode 100755
index 5de936fccfd..00000000000
--- a/source/script/uninstallbin.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-#4 July 96 Dan.Shearer@UniSA.edu.au
-
-INSTALLPERMS=$1
-BASEDIR=`echo $2 | sed 's/\/\//\//g'`
-BINDIR=`echo $3 | sed 's/\/\//\//g'`
-LIBDIR=`echo $4 | sed 's/\/\//\//g'`
-VARDIR=`echo $5 | sed 's/\/\//\//g'`
-shift
-shift
-shift
-shift
-shift
-
-if [ ! -d $BINDIR ]; then
- echo Directory $BINDIR does not exist!
- echo Do a "make installbin" or "make install" first.
- exit 1
-fi
-
-for p in $*; do
- p2=`basename $p`
- if [ -f $BINDIR/$p2 ]; then
- echo Removing $BINDIR/$p2
- rm -f $BINDIR/$p2
- if [ -f $BINDIR/$p2 ]; then
- echo Cannot remove $BINDIR/$p2 ... does $USER have privileges?
- fi
- fi
-done
-
-
-cat << EOF
-======================================================================
-The binaries have been uninstalled. You may restore the binaries using
-the command "make installbin" or "make install" to install binaries,
-man pages, modules and shell scripts. You can restore a previous
-version of the binaries (if there were any) using "make revert".
-======================================================================
-EOF
-
-exit 0
diff --git a/source/script/uninstallbin.sh.in b/source/script/uninstallbin.sh.in
new file mode 100755
index 00000000000..d8a48558230
--- /dev/null
+++ b/source/script/uninstallbin.sh.in
@@ -0,0 +1,46 @@
+#!/bin/sh
+#4 July 96 Dan.Shearer@UniSA.edu.au
+
+INSTALLPERMS=$1
+DESTDIR=$2
+prefix=`echo $3 | sed 's/\/\//\//g'`
+BINDIR=`echo $4 | sed 's/\/\//\//g'`
+shift
+shift
+shift
+shift
+
+if [ ! -d $DESTDIR/$BINDIR ]; then
+ echo "Directory $DESTDIR/$BINDIR does not exist! "
+ echo "Do a "make installbin" or "make install" first. "
+ exit 1
+fi
+
+for p in $*; do
+ p2=`basename $p`
+ if [ -f $DESTDIR/$BINDIR/$p2 ]; then
+ echo "Removing $DESTDIR/$BINDIR/$p2 "
+ rm -f $DESTDIR/$BINDIR/$p2
+ if [ -f $DESTDIR/$BINDIR/$p2 ]; then
+ echo "Cannot remove $DESTDIR/$BINDIR/$p2 ... does $USER have privileges? "
+ fi
+ fi
+
+ # this is a special case, mount needs this in a specific location
+ if test "$p2" = smbmount -a -f "$DESTDIR/sbin/mount.smbfs"; then
+ echo "Removing $DESTDIR/sbin/mount.smbfs "
+ rm -f "$DESTDIR/@rootsbindir@/sbin/mount.smbfs"
+ fi
+done
+
+
+cat << EOF
+======================================================================
+The binaries have been uninstalled. You may restore the binaries using
+the command "make installbin" or "make install" to install binaries,
+man pages, modules and shell scripts. You can restore a previous
+version of the binaries (if there were any) using "make revert".
+======================================================================
+EOF
+
+exit 0
diff --git a/source/script/uninstallmodules.sh b/source/script/uninstallmodules.sh
index ac83af3dc90..fc80565cb57 100755
--- a/source/script/uninstallmodules.sh
+++ b/source/script/uninstallmodules.sh
@@ -2,25 +2,27 @@
#4 July 96 Dan.Shearer@UniSA.edu.au
INSTALLPERMS=$1
-BASEDIR=`echo $2 | sed 's/\/\//\//g'`
-LIBDIR=`echo $3 | sed 's/\/\//\//g'`
+DESTDIR=$2
+prefix=`echo $3 | sed 's/\/\//\//g'`
+LIBDIR=`echo $4 | sed 's/\/\//\//g'`
+shift
shift
shift
shift
-if [ ! -d $LIBDIR ]; then
- echo Directory $LIBDIR does not exist!
- echo Do a "make installmodules" or "make install" first.
+if [ ! -d $DESTDIR/$LIBDIR ]; then
+ echo "Directory $DESTDIR/$LIBDIR does not exist! "
+ echo "Do a "make installmodules" or "make install" first. "
exit 1
fi
for p in $*; do
p2=`basename $p`
- if [ -f $LIBDIR/$p2 ]; then
- echo Removing $LIBDIR/$p2
- rm -f $LIBDIR/$p2
- if [ -f $LIBDIR/$p2 ]; then
- echo Cannot remove $LIBDIR/$p2 ... does $USER have privileges?
+ if [ -f $DESTDIR/$LIBDIR/$p2 ]; then
+ echo "Removing $DESTDIR/$LIBDIR/$p2 "
+ rm -f $DESTDIR/$LIBDIR/$p2
+ if [ -f $DESTDIR/$LIBDIR/$p2 ]; then
+ echo "Cannot remove $DESTDIR/$LIBDIR/$p2 ... does $USER have privileges? "
fi
fi
done
diff --git a/source/services/services_db.c b/source/services/services_db.c
index 6c38c6ed0a9..5b4f58d766d 100644
--- a/source/services/services_db.c
+++ b/source/services/services_db.c
@@ -160,7 +160,7 @@ static char* cleanup_string( const char *string )
while ( isspace(*begin) )
begin++;
- if ( !begin )
+ if ( *begin == '\0' )
return NULL;
/* trim any trailing whitespace or carriage returns.
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index 805e45f6ea3..a8db498ef5a 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -35,6 +35,8 @@ typedef struct _blocking_lock_record {
SMB_BIG_UINT offset;
SMB_BIG_UINT count;
uint16 lock_pid;
+ enum brl_flavour lock_flav;
+ enum brl_type lock_type;
char *inbuf;
int length;
} blocking_lock_record;
@@ -53,25 +55,6 @@ static void free_blocking_lock_record(blocking_lock_record *blr)
}
/****************************************************************************
- Get the files_struct given a particular queued SMB.
-*****************************************************************************/
-
-static files_struct *get_fsp_from_pkt(char *inbuf)
-{
- switch(CVAL(inbuf,smb_com)) {
- case SMBlock:
- case SMBlockread:
- return file_fsp(inbuf,smb_vwv0);
- case SMBlockingX:
- return file_fsp(inbuf,smb_vwv2);
- default:
- DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n"));
- exit_server("PANIC - unknown type on blocking lock queue");
- }
- return NULL; /* Keep compiler happy. */
-}
-
-/****************************************************************************
Determine if this is a secondary element of a chained SMB.
**************************************************************************/
@@ -87,12 +70,19 @@ static void received_unlock_msg(int msg_type, struct process_id src,
Function to push a blocking lock request onto the lock queue.
****************************************************************************/
-BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
- int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count)
+BOOL push_blocking_lock_request( char *inbuf, int length,
+ files_struct *fsp,
+ int lock_timeout,
+ int lock_num,
+ uint16 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;
NTSTATUS status;
if(in_chained_smb() ) {
@@ -110,6 +100,9 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
return False;
}
+ blr->next = NULL;
+ blr->prev = NULL;
+
if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) {
DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" ));
SAFE_FREE(blr);
@@ -117,19 +110,33 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
}
blr->com_type = CVAL(inbuf,smb_com);
- blr->fsp = get_fsp_from_pkt(inbuf);
+ blr->fsp = fsp;
blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout;
blr->lock_num = lock_num;
blr->lock_pid = lock_pid;
+ blr->lock_flav = lock_flav;
+ blr->lock_type = lock_type;
blr->offset = offset;
blr->count = count;
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(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
- lock_pid, procid_self(), blr->fsp->conn->cnum,
- offset, count, PENDING_LOCK, &my_lock_ctx);
+ status = brl_lock(br_lck,
+ lock_pid,
+ procid_self(),
+ offset,
+ count,
+ PENDING_LOCK,
+ blr->lock_flav,
+ &my_lock_ctx);
+ byte_range_lock_destructor(br_lck);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n"));
@@ -227,7 +234,6 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
{
char *inbuf = blr->inbuf;
files_struct *fsp = blr->fsp;
- connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT) 0;
uint16 lock_pid;
@@ -261,7 +267,11 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
* request would never have been queued. JRA.
*/
- do_unlock(fsp,conn,lock_pid,count,offset);
+ do_unlock(fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
}
generic_blocking_lock_error(blr, status);
@@ -274,19 +284,41 @@ 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;
+ case SMBtrans2:
+ case SMBtranss2:
+ {
+ char *outbuf = get_OutBuffer();
+ char *inbuf = blr->inbuf;
+ construct_reply_common(inbuf, outbuf);
+ /* construct_reply_common has done us the favor to pre-fill the
+ * command field with SMBtranss2 which is wrong :-)
+ */
+ SCVAL(outbuf,smb_com,SMBtrans2);
+ ERROR_NT(status);
+ if (!send_smb(smbd_server_fd(),outbuf)) {
+ exit_server("blocking_lock_reply_error: send_smb failed.");
+ }
+ break;
+ }
default:
DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n"));
exit_server("PANIC - unknown type on blocking lock queue");
}
}
+#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.
@@ -302,7 +334,6 @@ static BOOL process_lockread(blocking_lock_record *blr)
SMB_BIG_UINT startpos;
size_t numtoread;
NTSTATUS status;
- connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
files_struct *fsp = blr->fsp;
BOOL my_lock_ctx = False;
@@ -312,7 +343,14 @@ static BOOL process_lockread(blocking_lock_record *blr)
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
data = smb_buf(outbuf) + 3;
- status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, startpos, READ_LOCK, &my_lock_ctx);
+ 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)) {
@@ -371,7 +409,6 @@ static BOOL process_lock(blocking_lock_record *blr)
int outsize;
SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0;
NTSTATUS status;
- connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
files_struct *fsp = blr->fsp;
BOOL my_lock_ctx = False;
@@ -379,7 +416,14 @@ static BOOL process_lock(blocking_lock_record *blr)
offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
errno = 0;
- status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
+ 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)) {
@@ -412,6 +456,7 @@ static BOOL process_lock(blocking_lock_record *blr)
send_blocking_reply(outbuf,outsize);
return True;
}
+#endif
/****************************************************************************
Attempt to finish off getting all pending blocking locks for a lockingX call.
@@ -423,7 +468,6 @@ static BOOL process_lockingX(blocking_lock_record *blr)
char *inbuf = blr->inbuf;
unsigned char locktype = CVAL(inbuf,smb_vwv3);
files_struct *fsp = blr->fsp;
- connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
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;
@@ -452,9 +496,17 @@ static BOOL process_lockingX(blocking_lock_record *blr)
* request would never have been queued. JRA.
*/
errno = 0;
- status = do_lock_spin(fsp,conn,lock_pid,count,offset,
- ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
- if (NT_STATUS_IS_ERR(status)) break;
+ status = do_lock_spin(fsp,
+ lock_pid,
+ count,
+ offset,
+ ((locktype & 1) ? READ_LOCK : WRITE_LOCK),
+ WINDOWS_LOCK,
+ &my_lock_ctx);
+
+ if (NT_STATUS_IS_ERR(status)) {
+ break;
+ }
}
if(blr->lock_num == num_locks) {
@@ -491,6 +543,51 @@ Waiting....\n",
}
/****************************************************************************
+ Attempt to get the posix lock request from a SMBtrans2 call.
+ Returns True if we want to be removed from the list.
+*****************************************************************************/
+
+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);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ if (ERROR_WAS_LOCK_DENIED(status)) {
+ /* Still can't get the lock, just keep waiting. */
+ return False;
+ }
+ /*
+ * We have other than a "can't get lock"
+ * error. Send an error and return True so we get dequeued.
+ */
+ blocking_lock_reply_error(blr, status);
+ return True;
+ }
+
+ /* We finally got the lock, return success. */
+ outbuf = get_OutBuffer();
+ construct_reply_common(inbuf, outbuf);
+ SCVAL(outbuf,smb_com,SMBtrans2);
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, max_send, params, 2, NULL, 0);
+ return True;
+}
+
+
+/****************************************************************************
Process a blocking lock SMB.
Returns True if we want to be removed from the list.
*****************************************************************************/
@@ -498,12 +595,18 @@ Waiting....\n",
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:
+ case SMBtranss2:
+ return process_trans2(blr);
default:
DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n"));
exit_server("PANIC - unknown type on blocking lock queue");
@@ -522,13 +625,21 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp)
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);
- DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
+ 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_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
- blr->lock_pid, procid_self(), blr->fsp->conn->cnum,
- blr->offset, blr->count, True, NULL, NULL);
+ brl_remove_pending_lock(br_lck,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+ byte_range_lock_destructor(br_lck);
+
+ }
free_blocking_lock_record(blr);
}
@@ -547,14 +658,22 @@ 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);
- DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \
+ 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,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+ byte_range_lock_destructor(br_lck);
+ }
+
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
- brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
- blr->lock_pid, procid_self(), blr->fsp->conn->cnum,
- blr->offset, blr->count, True, NULL, NULL);
free_blocking_lock_record(blr);
}
}
@@ -635,16 +754,25 @@ void process_blocking_lock_queue(time_t t)
fsp->fnum, fsp->fsp_name ));
if((blr->expire_time != -1) && (blr->expire_time <= t)) {
+ struct byte_range_lock *br_lck = brl_get_locks(fsp);
+
/*
* Lock expired - throw away all previously
* obtained locks and return lock error.
*/
- DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
- fsp->fnum, fsp->fsp_name ));
- brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- blr->lock_pid, procid_self(), conn->cnum,
- blr->offset, blr->count, True, NULL, NULL);
+ if (br_lck) {
+ 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,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+ byte_range_lock_destructor(br_lck);
+ }
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
free_blocking_lock_record(blr);
@@ -652,32 +780,48 @@ void process_blocking_lock_queue(time_t t)
}
if(!change_to_user(conn,vuid)) {
- DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
- vuid ));
+ struct byte_range_lock *br_lck = brl_get_locks(fsp);
+
/*
* Remove the entry and return an error to the client.
*/
- blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
- brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- blr->lock_pid, procid_self(), conn->cnum,
- blr->offset, blr->count, True, NULL, NULL);
+ if (br_lck) {
+ brl_remove_pending_lock(br_lck,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+ byte_range_lock_destructor(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);
free_blocking_lock_record(blr);
continue;
}
if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
- DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
+ struct byte_range_lock *br_lck = brl_get_locks(fsp);
+
/*
* Remove the entry and return an error to the client.
*/
- blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
- brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- blr->lock_pid, procid_self(), conn->cnum,
- blr->offset, blr->count, True, NULL, NULL);
+ if (br_lck) {
+ brl_remove_pending_lock(br_lck,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+ byte_range_lock_destructor(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);
free_blocking_lock_record(blr);
change_to_root_user();
continue;
@@ -690,10 +834,17 @@ void process_blocking_lock_queue(time_t t)
*/
if(blocking_lock_record_process(blr)) {
-
- brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
- blr->lock_pid, procid_self(), conn->cnum,
- blr->offset, blr->count, True, NULL, NULL);
+ struct byte_range_lock *br_lck = brl_get_locks(fsp);
+
+ if (br_lck) {
+ brl_remove_pending_lock(br_lck,
+ blr->lock_pid,
+ procid_self(),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+ byte_range_lock_destructor(br_lck);
+ }
free_blocking_lock_record(blr);
}
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index 5a179dbf478..16b44a54bf9 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -55,7 +55,7 @@ static NTSTATUS check_oem_password(const char *user,
const uchar old_lm_hash_encrypted[16],
uchar password_encrypted_with_nt_hash[516],
const uchar old_nt_hash_encrypted[16],
- SAM_ACCOUNT **hnd, char *new_passwd,
+ struct samu **hnd, char *new_passwd,
int new_passwd_size);
#if ALLOW_CHANGE_PASSWORD
@@ -415,9 +415,10 @@ while we were waiting\n", WTERMSIG(wstat)));
/* CHILD */
/*
- * Lose any oplock capabilities.
+ * Lose any elevated privileges.
*/
- oplock_set_capability(False, False);
+ drop_effective_capability(KERNEL_OPLOCK_CAPABILITY);
+ drop_effective_capability(DMAPI_ACCESS_CAPABILITY);
/* make sure it doesn't freeze */
alarm(20);
@@ -570,12 +571,12 @@ BOOL chgpasswd(const char *name, const struct passwd *pass,
************************************************************/
BOOL check_lanman_password(char *user, uchar * pass1,
- uchar * pass2, SAM_ACCOUNT **hnd)
+ uchar * pass2, struct samu **hnd)
{
uchar unenc_new_pw[16];
uchar unenc_old_pw[16];
- SAM_ACCOUNT *sampass = NULL;
- uint16 acct_ctrl;
+ struct samu *sampass = NULL;
+ uint32 acct_ctrl;
const uint8 *lanman_pw;
BOOL ret;
@@ -585,7 +586,7 @@ BOOL check_lanman_password(char *user, uchar * pass1,
if (ret == False) {
DEBUG(0,("check_lanman_password: getsampwnam returned NULL\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
@@ -594,7 +595,7 @@ BOOL check_lanman_password(char *user, uchar * pass1,
if (acct_ctrl & ACB_DISABLED) {
DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
@@ -605,7 +606,7 @@ BOOL check_lanman_password(char *user, uchar * pass1,
return True;
} else {
DEBUG(0, ("check_lanman_password: no lanman password !\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
}
@@ -619,7 +620,7 @@ BOOL check_lanman_password(char *user, uchar * pass1,
/* Check that the two old passwords match. */
if (memcmp(lanman_pw, unenc_old_pw, 16)) {
DEBUG(0,("check_lanman_password: old password doesn't match.\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return False;
}
@@ -636,12 +637,12 @@ BOOL check_lanman_password(char *user, uchar * pass1,
is correct before calling. JRA.
************************************************************/
-BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2)
+BOOL change_lanman_password(struct samu *sampass, uchar *pass2)
{
static uchar null_pw[16];
uchar unenc_new_pw[16];
BOOL ret;
- uint16 acct_ctrl;
+ uint32 acct_ctrl;
const uint8 *pwd;
if (sampass == NULL) {
@@ -684,13 +685,13 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2)
}
if (!pdb_set_pass_changed_now (sampass)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
/* Not quite sure what this one qualifies as, but this will do */
return False;
}
/* Now flush the sam_passwd struct to persistent storage */
- ret = pdb_update_sam_account (sampass);
+ ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
return ret;
}
@@ -703,10 +704,11 @@ NTSTATUS pass_oem_change(char *user,
uchar password_encrypted_with_lm_hash[516],
const uchar old_lm_hash_encrypted[16],
uchar password_encrypted_with_nt_hash[516],
- const uchar old_nt_hash_encrypted[16])
+ const uchar old_nt_hash_encrypted[16],
+ uint32 *reject_reason)
{
pstring new_passwd;
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
NTSTATUS nt_status = check_oem_password(user, password_encrypted_with_lm_hash,
old_lm_hash_encrypted,
password_encrypted_with_nt_hash,
@@ -718,12 +720,12 @@ NTSTATUS pass_oem_change(char *user,
/* We've already checked the old password here.... */
become_root();
- nt_status = change_oem_password(sampass, NULL, new_passwd, True);
+ nt_status = change_oem_password(sampass, NULL, new_passwd, True, reject_reason);
unbecome_root();
memset(new_passwd, 0, sizeof(new_passwd));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return nt_status;
}
@@ -745,16 +747,16 @@ static NTSTATUS check_oem_password(const char *user,
const uchar old_lm_hash_encrypted[16],
uchar password_encrypted_with_nt_hash[516],
const uchar old_nt_hash_encrypted[16],
- SAM_ACCOUNT **hnd, char *new_passwd,
+ struct samu **hnd, char *new_passwd,
int new_passwd_size)
{
static uchar null_pw[16];
static uchar null_ntpw[16];
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
uint8 *password_encrypted;
const uint8 *encryption_key;
const uint8 *lanman_pw, *nt_pw;
- uint16 acct_ctrl;
+ uint32 acct_ctrl;
uint32 new_pw_len;
uchar new_nt_hash[16];
uchar new_lm_hash[16];
@@ -767,7 +769,9 @@ static NTSTATUS check_oem_password(const char *user,
*hnd = NULL;
- pdb_init_sam(&sampass);
+ if ( !(sampass = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
become_root();
ret = pdb_getsampwnam(sampass, user);
@@ -775,7 +779,7 @@ static NTSTATUS check_oem_password(const char *user,
if (ret == False) {
DEBUG(0, ("check_oem_password: getsmbpwnam returned NULL\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_NO_SUCH_USER;
}
@@ -783,7 +787,7 @@ static NTSTATUS check_oem_password(const char *user,
if (acct_ctrl & ACB_DISABLED) {
DEBUG(2,("check_lanman_password: account %s disabled.\n", user));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_ACCOUNT_DISABLED;
}
@@ -818,7 +822,7 @@ static NTSTATUS check_oem_password(const char *user,
} else if (nt_pass_set) {
DEBUG(1, ("NT password change supplied for user %s, but we have no NT password to check it with\n",
user));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
} else if (lm_pass_set) {
if (lp_lanman_auth()) {
@@ -828,12 +832,12 @@ static NTSTATUS check_oem_password(const char *user,
DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n",
user));
}
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
} else {
DEBUG(1, ("password change requested for user %s, but no password supplied!\n",
user));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
@@ -844,7 +848,7 @@ static NTSTATUS check_oem_password(const char *user,
if ( !decode_pw_buffer(password_encrypted, new_passwd, new_passwd_size, &new_pw_len,
nt_pass_set ? STR_UNICODE : STR_ASCII)) {
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
@@ -867,7 +871,7 @@ static NTSTATUS check_oem_password(const char *user,
E_old_pw_hash(new_nt_hash, nt_pw, verifier);
if (memcmp(verifier, old_nt_hash_encrypted, 16)) {
DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
@@ -895,7 +899,7 @@ static NTSTATUS check_oem_password(const char *user,
E_old_pw_hash(new_nt_hash, lanman_pw, verifier);
if (memcmp(verifier, old_lm_hash_encrypted, 16)) {
DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
#ifdef DEBUG_PASSWORD
@@ -917,7 +921,7 @@ static NTSTATUS check_oem_password(const char *user,
E_old_pw_hash(new_lm_hash, lanman_pw, verifier);
if (memcmp(verifier, old_lm_hash_encrypted, 16)) {
DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
@@ -930,7 +934,7 @@ static NTSTATUS check_oem_password(const char *user,
}
/* should not be reached */
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
return NT_STATUS_WRONG_PASSWORD;
}
@@ -940,7 +944,7 @@ static NTSTATUS check_oem_password(const char *user,
found in the history list.
************************************************************/
-static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext)
+static BOOL check_passwd_history(struct samu *sampass, const char *plaintext)
{
uchar new_nt_p16[NT_HASH_LEN];
uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN];
@@ -1007,35 +1011,66 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext)
is correct before calling. JRA.
************************************************************/
-NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root)
+NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason)
{
- BOOL ret;
- uint32 min_len;
+ uint32 min_len, min_age;
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 ((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)));
- return NT_STATUS_ACCOUNT_RESTRICTION;
+ 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;
+ }
+ } 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;
+ }
}
if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
DEBUG(1, ("user %s cannot change password - password too short\n",
username));
DEBUGADD(1, (" account policy min password len = %d\n", min_len));
+ if (samr_reject_reason) {
+ *samr_reject_reason = REJECT_REASON_TOO_SHORT;
+ }
return NT_STATUS_PASSWORD_RESTRICTION;
/* return NT_STATUS_PWD_TOO_SHORT; */
}
if (check_passwd_history(hnd,new_passwd)) {
+ if (samr_reject_reason) {
+ *samr_reject_reason = REJECT_REASON_IN_HISTORY;
+ }
return NT_STATUS_PASSWORD_RESTRICTION;
}
pass = Get_Pwnam(username);
if (!pass) {
- DEBUG(1, ("check_oem_password: Username %s does not exist in system !?!\n", username));
+ DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username));
return NT_STATUS_ACCESS_DENIED;
}
@@ -1048,6 +1083,9 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
if (check_ret != 0) {
DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
+ if (samr_reject_reason) {
+ *samr_reject_reason = REJECT_REASON_NOT_COMPLEX;
+ }
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
@@ -1074,11 +1112,5 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
}
/* Now write it into the file. */
- ret = pdb_update_sam_account (hnd);
-
- if (!ret) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- return NT_STATUS_OK;
+ return pdb_update_sam_account (hnd);
}
diff --git a/source/smbd/close.c b/source/smbd/close.c
index c0d87b1b212..bc1182032d7 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -145,13 +145,12 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
/****************************************************************************
Close a file.
- If normal_close is 1 then this came from a normal SMBclose (or equivalent)
- operation otherwise it came as the result of some other operation such as
- the closing of the connection. In the latter case printing and
- magic scripts are not run.
+ close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
+ printing and magic scripts are only run on normal close.
+ delete on close is done on normal and shutdown close.
****************************************************************************/
-static int close_normal_file(files_struct *fsp, BOOL normal_close)
+static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
{
BOOL delete_file = False;
connection_struct *conn = fsp->conn;
@@ -187,7 +186,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
}
if (fsp->print_file) {
- print_fsp_end(fsp, normal_close);
+ print_fsp_end(fsp, close_type);
file_free(fsp);
return 0;
}
@@ -209,7 +208,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name));
}
- delete_file = lck->delete_on_close;
+ delete_file = (lck->delete_on_close | lck->initial_delete_on_close);
if (delete_file) {
int i;
@@ -232,12 +231,26 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
* reference to a file.
*/
- if (normal_close && delete_file) {
+ if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
+ delete_file &&
+ lck->delete_token) {
SMB_STRUCT_STAT sbuf;
DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
fsp->fsp_name));
+ /* Become the user who requested the delete. */
+
+ if (!push_sec_ctx()) {
+ smb_panic("close_file: file %s. failed to push sec_ctx.\n");
+ }
+
+ 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. */
@@ -268,11 +281,14 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
"and unlink failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
}
- process_pending_change_notify_queue((time_t)0);
}
+ /* unbecome user. */
+ pop_sec_ctx();
+
+ process_pending_change_notify_queue((time_t)0);
}
- talloc_free(lck);
+ TALLOC_FREE(lck);
if(fsp->oplock_type)
release_file_oplock(fsp);
@@ -288,7 +304,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
}
/* check for magic scripts */
- if (normal_close) {
+ if (close_type == NORMAL_CLOSE) {
check_magic(fsp,conn);
}
@@ -324,7 +340,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
Close a directory opened by an NT SMB call.
****************************************************************************/
-static int close_directory(files_struct *fsp, BOOL normal_close)
+static int close_directory(files_struct *fsp, enum file_close_type close_type)
{
struct share_mode_lock *lck = 0;
BOOL delete_dir = False;
@@ -345,15 +361,35 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
}
- delete_dir = lck->delete_on_close;
+ delete_dir = (lck->delete_on_close | lck->initial_delete_on_close);
- talloc_free(lck);
+ if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
+ delete_dir &&
+ lck->delete_token) {
+ BOOL ok;
+
+ /* Become the user who requested the delete. */
+
+ if (!push_sec_ctx()) {
+ smb_panic("close_directory: failed to push sec_ctx.\n");
+ }
+
+ set_sec_ctx(lck->delete_token->uid,
+ lck->delete_token->gid,
+ lck->delete_token->ngroups,
+ lck->delete_token->groups,
+ NULL);
+
+ TALLOC_FREE(lck);
+
+ ok = rmdir_internals(fsp->conn, fsp->fsp_name);
- if (normal_close && delete_dir) {
- BOOL ok = 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" ));
+ /* unbecome user. */
+ pop_sec_ctx();
+
/*
* Ensure we remove any change notify requests that would
* now fail as the directory has been deleted.
@@ -366,6 +402,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
}
process_pending_change_notify_queue((time_t)0);
} else {
+ TALLOC_FREE(lck);
remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_CANCELLED);
}
@@ -404,12 +441,12 @@ static int close_stat(files_struct *fsp)
Close a files_struct.
****************************************************************************/
-int close_file(files_struct *fsp, BOOL normal_close)
+int close_file(files_struct *fsp, enum file_close_type close_type)
{
if(fsp->is_directory)
- return close_directory(fsp, normal_close);
+ return close_directory(fsp, close_type);
else if (fsp->is_stat)
return close_stat(fsp);
else
- return close_normal_file(fsp, normal_close);
+ return close_normal_file(fsp, close_type);
}
diff --git a/source/smbd/conn.c b/source/smbd/conn.c
index bb000bac30e..5aa8901d597 100644
--- a/source/smbd/conn.c
+++ b/source/smbd/conn.c
@@ -154,8 +154,9 @@ find_again:
}
/****************************************************************************
-close all conn structures
+ Close all conn structures.
****************************************************************************/
+
void conn_close_all(void)
{
connection_struct *conn, *next;
@@ -178,13 +179,20 @@ BOOL conn_idle_all(time_t t, int deadtime)
for (conn=Connections;conn;conn=next) {
next=conn->next;
+
+ /* Update if connection wasn't idle. */
+ if (conn->lastused != conn->lastused_count) {
+ conn->lastused = t;
+ }
+
/* close dirptrs on connections that are idle */
- if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT)
+ if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) {
dptr_idlecnum(conn);
+ }
- if (conn->num_files_open > 0 ||
- (t-conn->lastused)<deadtime)
+ if (conn->num_files_open > 0 || (t-conn->lastused)<deadtime) {
allidle = False;
+ }
}
/*
@@ -249,7 +257,7 @@ void conn_free_internal(connection_struct *conn)
}
if (conn->nt_user_token) {
- delete_nt_token(&(conn->nt_user_token));
+ TALLOC_FREE(conn->nt_user_token);
}
free_namearray(conn->veto_list);
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index 0635db22dbd..cd6c1b0bda3 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -645,6 +645,15 @@ BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, S
}
/****************************************************************************
+ Add the name we're returning into the underlying cache.
+****************************************************************************/
+
+void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
+{
+ DirCacheAdd(dptr->dir_hnd, name, offset);
+}
+
+/****************************************************************************
Fill the 5 byte server reserved dptr field.
****************************************************************************/
@@ -812,6 +821,8 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
found = True;
+
+ DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
}
}
@@ -866,7 +877,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
- close_file(fsp, True);
+ close_file(fsp, NORMAL_CLOSE);
/* No access if SD get failed. */
if (!sd_size) {
@@ -929,7 +940,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
- close_file(fsp, False);
+ close_file(fsp, NORMAL_CLOSE);
/* No access if SD get failed. */
if (!sd_size)
@@ -1109,21 +1120,15 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
}
while ((n = vfs_readdirname(conn, dirp->dir))) {
- struct name_cache_entry *e;
/* Ignore . and .. - we've already returned them. */
if (*n == '.') {
if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
continue;
}
}
- dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
- dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
- e = &dirp->name_cache[dirp->name_cache_index];
- SAFE_FREE(e->name);
- e->name = SMB_STRDUP(n);
- *poffset = e->offset= dirp->offset;
+ *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
dirp->file_number++;
- return e->name;
+ return n;
}
*poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
return NULL;
@@ -1184,6 +1189,21 @@ long TellDir(struct smb_Dir *dirp)
}
/*******************************************************************
+ Add an entry into the dcache.
+********************************************************************/
+
+void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
+{
+ struct name_cache_entry *e;
+
+ dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
+ e = &dirp->name_cache[dirp->name_cache_index];
+ SAFE_FREE(e->name);
+ e->name = SMB_STRDUP(name);
+ e->offset = offset;
+}
+
+/*******************************************************************
Find an entry by name. Leave us at the offset after it.
Don't check for veto or invisible files.
********************************************************************/
diff --git a/source/smbd/dmapi.c b/source/smbd/dmapi.c
new file mode 100644
index 00000000000..4a6cba293bc
--- /dev/null
+++ b/source/smbd/dmapi.c
@@ -0,0 +1,306 @@
+/*
+ Unix SMB/CIFS implementation.
+ DMAPI Support routines
+
+ 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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_DMAPI
+
+#if defined(HAVE_LIBDM) || defined(HAVE_LIBJFSDM) || defined(HAVE_LIBXDSM)
+#if defined(HAVE_XFS_DMAPI_H) || defined(HAVE_SYS_DMI_H) || defined(HAVE_SYS_JFSDMAPI_H) || defined(HAVE_SYS_DMAPI_H)
+#define USE_DMAPI 1
+#endif
+#endif
+
+#ifndef USE_DMAPI
+
+int dmapi_init_session(void) { return -1; }
+uint32 dmapi_file_flags(const char * const path) { return 0; }
+BOOL dmapi_have_session(void) { return False; }
+
+#else /* USE_DMAPI */
+
+#ifdef HAVE_XFS_DMAPI_H
+#include <xfs/dmapi.h>
+#elif defined(HAVE_SYS_DMI_H)
+#include <sys/dmi.h>
+#elif defined(HAVE_SYS_JFSDMAPI_H)
+#include <sys/jfsdmapi.h>
+#elif defined(HAVE_SYS_DMAPI_H)
+#include <sys/dmapi.h>
+#endif
+
+#define DMAPI_SESSION_NAME "samba"
+#define DMAPI_TRACE 10
+
+static dm_sessid_t dmapi_session = DM_NO_SESSION;
+
+/* Initialise the DMAPI interface. Make sure that we only end up initialising
+ * once per process to avoid resource leaks across different DMAPI
+ * implementations.
+ */
+static int init_dmapi_service(void)
+{
+ static pid_t lastpid;
+
+ pid_t mypid;
+
+ mypid = sys_getpid();
+ if (mypid != lastpid) {
+ char *version;
+
+ lastpid = mypid;
+ if (dm_init_service(&version) < 0) {
+ return -1;
+ }
+
+ DEBUG(0, ("Initializing DMAPI: %s\n", version));
+ }
+
+ return 0;
+}
+
+BOOL dmapi_have_session(void)
+{
+ return dmapi_session != DM_NO_SESSION;
+}
+
+static dm_sessid_t *realloc_session_list(dm_sessid_t * sessions, int count)
+{
+ dm_sessid_t *nsessions;
+
+ nsessions = TALLOC_REALLOC_ARRAY(NULL, sessions, dm_sessid_t, count);
+ if (nsessions == NULL) {
+ TALLOC_FREE(sessions);
+ return NULL;
+ }
+
+ return nsessions;
+}
+
+/* Initialise DMAPI session. The session is persistant kernel state, so it
+ * might already exist, in which case we merely want to reconnect to it. This
+ * function should be called as root.
+ */
+int dmapi_init_session(void)
+{
+ char buf[DM_SESSION_INFO_LEN];
+ size_t buflen;
+
+ uint nsessions = 10;
+ dm_sessid_t *sessions = NULL;
+
+ int i, err;
+
+ /* If we aren't root, something in the following will fail due to lack
+ * of privileges. Aborting seems a little extreme.
+ */
+ SMB_WARN(getuid() == 0, "dmapi_init_session must be called as root");
+
+ dmapi_session = DM_NO_SESSION;
+ if (init_dmapi_service() < 0) {
+ return -1;
+ }
+
+retry:
+
+ if ((sessions = realloc_session_list(sessions, nsessions)) == NULL) {
+ return -1;
+ }
+
+ err = dm_getall_sessions(nsessions, sessions, &nsessions);
+ if (err < 0) {
+ if (errno == E2BIG) {
+ nsessions *= 2;
+ goto retry;
+ }
+
+ DEBUGADD(DMAPI_TRACE,
+ ("failed to retrieve DMAPI sessions: %s\n",
+ strerror(errno)));
+ TALLOC_FREE(sessions);
+ return -1;
+ }
+
+ for (i = 0; i < nsessions; ++i) {
+ err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen);
+ buf[sizeof(buf) - 1] = '\0';
+ if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) {
+ dmapi_session = sessions[i];
+ DEBUGADD(DMAPI_TRACE,
+ ("attached to existing DMAPI session "
+ "named '%s'\n", buf));
+ break;
+ }
+ }
+
+ TALLOC_FREE(sessions);
+
+ /* No session already defined. */
+ if (dmapi_session == DM_NO_SESSION) {
+ err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME,
+ &dmapi_session);
+ if (err < 0) {
+ DEBUGADD(DMAPI_TRACE,
+ ("failed to create new DMAPI session: %s\n",
+ strerror(errno)));
+ dmapi_session = DM_NO_SESSION;
+ return -1;
+ }
+
+ DEBUGADD(DMAPI_TRACE,
+ ("created new DMAPI session named '%s'\n",
+ DMAPI_SESSION_NAME));
+ }
+
+ /* Note that we never end the DMAPI session. This enables child
+ * processes to continue to use the session after we exit. It also lets
+ * you run a second Samba server on different ports without any
+ * conflict.
+ */
+
+ return 0;
+}
+
+/* Reattach to an existing dmapi session. Called from service processes that
+ * might not be running as root.
+ */
+static int reattach_dmapi_session(void)
+{
+ char buf[DM_SESSION_INFO_LEN];
+ size_t buflen;
+
+ if (dmapi_session != DM_NO_SESSION ) {
+ become_root();
+
+ /* NOTE: On Linux, this call opens /dev/dmapi, costing us a
+ * file descriptor. Ideally, we would close this when we fork.
+ */
+ if (init_dmapi_service() < 0) {
+ dmapi_session = DM_NO_SESSION;
+ unbecome_root();
+ return -1;
+ }
+
+ if (dm_query_session(dmapi_session, sizeof(buf),
+ buf, &buflen) < 0) {
+ /* Session is stale. Disable DMAPI. */
+ dmapi_session = DM_NO_SESSION;
+ unbecome_root();
+ return -1;
+ }
+
+ set_effective_capability(DMAPI_ACCESS_CAPABILITY);
+
+ DEBUG(DMAPI_TRACE, ("reattached DMAPI session\n"));
+ unbecome_root();
+ }
+
+ return 0;
+}
+
+uint32 dmapi_file_flags(const char * const path)
+{
+ static int attached = 0;
+
+ int err;
+ dm_eventset_t events = {0};
+ uint nevents;
+
+ void *dm_handle;
+ size_t dm_handle_len;
+
+ uint32 flags = 0;
+
+ /* If a DMAPI session has been initialised, then we need to make sure
+ * we are attached to it and have the correct privileges. This is
+ * necessary to be able to do DMAPI operations across a fork(2). If
+ * it fails, there is no liklihood of that failure being transient.
+ *
+ * Note that this use of the static attached flag relies on the fact
+ * that dmapi_file_flags() is never called prior to forking the
+ * per-client server process.
+ */
+ if (dmapi_have_session() && !attached) {
+ attached++;
+ if (reattach_dmapi_session() < 0) {
+ return 0;
+ }
+ }
+
+ err = dm_path_to_handle(CONST_DISCARD(char *, path),
+ &dm_handle, &dm_handle_len);
+ if (err < 0) {
+ DEBUG(DMAPI_TRACE, ("dm_path_to_handle(%s): %s\n",
+ path, strerror(errno)));
+
+ if (errno != EPERM) {
+ return 0;
+ }
+
+ /* Linux capabilities are broken in that changing our
+ * user ID will clobber out effective capabilities irrespective
+ * of whether we have set PR_SET_KEEPCAPS. Fortunately, the
+ * capabilities are not removed from our permitted set, so we
+ * can re-acquire them if necessary.
+ */
+
+ set_effective_capability(DMAPI_ACCESS_CAPABILITY);
+
+ err = dm_path_to_handle(CONST_DISCARD(char *, path),
+ &dm_handle, &dm_handle_len);
+ if (err < 0) {
+ DEBUG(DMAPI_TRACE,
+ ("retrying dm_path_to_handle(%s): %s\n",
+ path, strerror(errno)));
+ return 0;
+ }
+ }
+
+ err = dm_get_eventlist(dmapi_session, dm_handle, dm_handle_len,
+ DM_NO_TOKEN, DM_EVENT_MAX, &events, &nevents);
+ if (err < 0) {
+ DEBUG(DMAPI_TRACE, ("dm_get_eventlist(%s): %s\n",
+ path, strerror(errno)));
+ dm_handle_free(dm_handle, dm_handle_len);
+ return 0;
+ }
+
+ /* We figure that the only reason a DMAPI application would be
+ * interested in trapping read events is that part of the file is
+ * offline.
+ */
+ DEBUG(DMAPI_TRACE, ("DMAPI event list for %s is %#llx\n",
+ path, events));
+ if (DMEV_ISSET(DM_EVENT_READ, events)) {
+ flags = FILE_ATTRIBUTE_OFFLINE;
+ }
+
+ dm_handle_free(dm_handle, dm_handle_len);
+
+ if (flags & FILE_ATTRIBUTE_OFFLINE) {
+ DEBUG(DMAPI_TRACE, ("%s is OFFLINE\n", path));
+ }
+
+ return flags;
+}
+
+#endif /* USE_DMAPI */
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 7f3bda582df..583b3f19e76 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
dos mode handling functions
Copyright (C) Andrew Tridgell 1992-1998
+ 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
@@ -31,6 +32,31 @@ 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)) {
+ return 0;
+ }
+
+ if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
+ return 0;
+ }
+
+ return dmapi_file_flags(path);
+}
+
+/****************************************************************************
Change a dos mode to a unix mode.
Base permission for files:
if creating file and inheriting
@@ -196,7 +222,7 @@ static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_S
sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
if (sizeret == -1) {
#if defined(ENOTSUP) && defined(ENOATTR)
- if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) {
+ if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES) && (errno != EPERM)) {
DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
path, strerror(errno) ));
set_store_dos_attributes(SNUM(conn), False);
@@ -325,6 +351,10 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
result |= dos_mode_from_sbuf(conn, path, sbuf);
}
+ if (S_ISREG(sbuf->st_mode)) {
+ result |= set_offline_flag(conn, path);
+ }
+
/* Optimization : Only call is_hidden_path if it's not already
hidden. */
if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index 799725a7820..1356baf1a81 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -109,7 +109,7 @@ files_struct *open_fake_file(connection_struct *conn,
files_struct *fsp = NULL;
/* access check */
- if (current_user.uid != 0) {
+ 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;
diff --git a/source/smbd/files.c b/source/smbd/files.c
index 181e17b11fb..ba4baa93b10 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -148,23 +148,23 @@ void file_close_conn(connection_struct *conn)
for (fsp=Files;fsp;fsp=next) {
next = fsp->next;
if (fsp->conn == conn) {
- close_file(fsp,False);
+ close_file(fsp,SHUTDOWN_CLOSE);
}
}
}
/****************************************************************************
- Close all open files for a pid.
+ Close all open files for a pid and a vuid.
****************************************************************************/
-void file_close_pid(uint16 smbpid)
+void file_close_pid(uint16 smbpid, int vuid)
{
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=next) {
next = fsp->next;
- if (fsp->file_pid == smbpid) {
- close_file(fsp,False);
+ if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
+ close_file(fsp,SHUTDOWN_CLOSE);
}
}
}
@@ -222,7 +222,7 @@ void file_close_user(int vuid)
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if (fsp->vuid == vuid) {
- close_file(fsp,False);
+ close_file(fsp,SHUTDOWN_CLOSE);
}
}
}
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index 86c6d056a07..1b5a5f39c72 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -355,248 +355,349 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
return 0;
}
+static NTSTATUS handle_trans(connection_struct *conn,
+ struct trans_state *state,
+ char *outbuf, int *outsize)
+{
+ char *local_machine_name;
+ int name_offset = 0;
+
+ DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
+ state->name,state->total_data,state->total_param,
+ state->setup_count));
+
+ /*
+ * WinCE wierdness....
+ */
+
+ local_machine_name = talloc_asprintf(state, "\\%s\\",
+ get_local_machine_name());
+
+ if (local_machine_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (strnequal(state->name, local_machine_name,
+ strlen(local_machine_name))) {
+ name_offset = strlen(local_machine_name)-1;
+ }
+
+ if (!strnequal(&state->name[name_offset], "\\PIPE",
+ strlen("\\PIPE"))) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ name_offset += strlen("\\PIPE");
+
+ /* Win9x weirdness. When talking to a unicode server Win9x
+ only sends \PIPE instead of \PIPE\ */
+
+ if (state->name[name_offset] == '\\')
+ name_offset++;
+
+ DEBUG(5,("calling named_pipe\n"));
+ *outsize = named_pipe(conn, state->vuid, outbuf,
+ state->name+name_offset,
+ state->setup,state->data,
+ state->param,
+ state->setup_count,state->total_data,
+ state->total_param,
+ state->max_setup_return,
+ state->max_data_return,
+ state->max_param_return);
+
+ if (*outsize == 0) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if (state->close_on_completion)
+ close_cnum(conn,state->vuid);
+
+ return NT_STATUS_OK;
+}
/****************************************************************************
Reply to a SMBtrans.
****************************************************************************/
-int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
+int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
+ int size, int bufsize)
{
- fstring name;
- int name_offset = 0;
- char *data=NULL,*params=NULL;
- uint16 *setup=NULL;
int outsize = 0;
- uint16 vuid = SVAL(inbuf,smb_uid);
- unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
- unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
- unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
- unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
- unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
- BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
- BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
- unsigned int pscnt = SVAL(inbuf,smb_vwv9);
- unsigned int psoff = SVAL(inbuf,smb_vwv10);
- unsigned int dscnt = SVAL(inbuf,smb_vwv11);
- unsigned int dsoff = SVAL(inbuf,smb_vwv12);
- unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
- fstring local_machine_name;
+ unsigned int dsoff = SVAL(inbuf, smb_dsoff);
+ unsigned int dscnt = SVAL(inbuf, smb_dscnt);
+ unsigned int psoff = SVAL(inbuf, smb_psoff);
+ unsigned int pscnt = SVAL(inbuf, smb_pscnt);
+ struct trans_state *state;
+ NTSTATUS result;
+
START_PROFILE(SMBtrans);
- memset(name, '\0',sizeof(name));
- srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE);
+ if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
+ SVAL(inbuf, smb_mid)))) {
+ DEBUG(2, ("Got invalid trans request: %s\n",
+ nt_errstr(result)));
+ END_PROFILE(SMBtrans);
+ return ERROR_NT(result);
+ }
- if (dscnt > tdscnt || pscnt > tpscnt)
+ if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ END_PROFILE(SMBtrans);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ state->cmd = SMBtrans;
+
+ state->mid = SVAL(inbuf, smb_mid);
+ state->vuid = SVAL(inbuf, smb_uid);
+ state->setup_count = CVAL(inbuf, smb_suwcnt);
+ state->total_param = SVAL(inbuf, smb_tpscnt);
+ state->param = NULL;
+ state->total_data = SVAL(inbuf, smb_tdscnt);
+ state->data = NULL;
+ state->max_param_return = SVAL(inbuf, smb_mprcnt);
+ state->max_data_return = SVAL(inbuf, smb_mdrcnt);
+ state->max_setup_return = CVAL(inbuf, smb_msrcnt);
+ state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
+ state->one_way = BITSETW(inbuf+smb_vwv5,1);
+
+ memset(state->name, '\0',sizeof(state->name));
+ srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf),
+ sizeof(state->name), STR_TERMINATE);
+
+ if ((dscnt > state->total_data) || (pscnt > state->total_param))
goto bad_param;
-
- if (tdscnt) {
- if((data = (char *)SMB_MALLOC(tdscnt)) == NULL) {
- DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
+
+ 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);
+ if (state->data == NULL) {
+ DEBUG(0,("reply_trans: data malloc fail for %u "
+ "bytes !\n", state->total_data));
+ TALLOC_FREE(state);
END_PROFILE(SMBtrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
goto bad_param;
if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
- (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
+ (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
goto bad_param;
- memcpy(data,smb_base(inbuf)+dsoff,dscnt);
+ memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
}
- if (tpscnt) {
- if((params = (char *)SMB_MALLOC(tpscnt)) == NULL) {
- DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
- SAFE_FREE(data);
+ 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);
+ if (state->param == NULL) {
+ DEBUG(0,("reply_trans: param malloc fail for %u "
+ "bytes !\n", state->total_param));
+ SAFE_FREE(state->data);
+ TALLOC_FREE(state);
END_PROFILE(SMBtrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
goto bad_param;
if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
- (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
+ (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
goto bad_param;
- memcpy(params,smb_base(inbuf)+psoff,pscnt);
+ memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
}
- if (suwcnt) {
+ state->received_data = dscnt;
+ state->received_param = pscnt;
+
+ if (state->setup_count) {
unsigned int i;
- if((setup = SMB_MALLOC_ARRAY(uint16,suwcnt)) == NULL) {
- DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
- SAFE_FREE(data);
- SAFE_FREE(params);
+ if((state->setup = TALLOC_ARRAY(
+ state, uint16, state->setup_count)) == NULL) {
+ DEBUG(0,("reply_trans: setup malloc fail for %u "
+ "bytes !\n", (unsigned int)
+ (state->setup_count * sizeof(uint16))));
+ TALLOC_FREE(state);
END_PROFILE(SMBtrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
- if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
+ if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) >
+ inbuf + size)
goto bad_param;
- if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
+ if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) ||
+ (smb_vwv14+(state->setup_count*SIZEOFWORD) <
+ (state->setup_count*SIZEOFWORD)))
goto bad_param;
- for (i=0;i<suwcnt;i++)
- setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
+ for (i=0;i<state->setup_count;i++)
+ state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
}
+ state->received_param = pscnt;
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
+ if ((state->received_param == state->total_param) &&
+ (state->received_data == state->total_data)) {
- if (pscnt < tpscnt || dscnt < tdscnt) {
- /* We need to send an interim response then receive the rest
- of the parameter/data bytes */
- outsize = set_message(outbuf,0,0,True);
- show_msg(outbuf);
- srv_signing_trans_stop();
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_trans: send_smb failed.");
- }
+ result = handle_trans(conn, state, outbuf, &outsize);
+
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
- /* receive the rest of the trans packet */
- while (pscnt < tpscnt || dscnt < tdscnt) {
- BOOL ret;
- unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
-
- ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
-
- /*
- * The sequence number for the trans reply is always
- * based on the last secondary received.
- */
-
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
-
- if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
- if(ret) {
- DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
- } else {
- DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
- }
- SAFE_FREE(params);
- SAFE_FREE(data);
- SAFE_FREE(setup);
+ if (!NT_STATUS_IS_OK(result)) {
END_PROFILE(SMBtrans);
- srv_signing_trans_stop();
- return(ERROR_DOS(ERRSRV,ERRerror));
+ return ERROR_NT(result);
}
- show_msg(inbuf);
-
- /* Revise total_params and total_data in case they have changed downwards */
- if (SVAL(inbuf,smb_vwv0) < tpscnt)
- tpscnt = SVAL(inbuf,smb_vwv0);
- if (SVAL(inbuf,smb_vwv1) < tdscnt)
- tdscnt = SVAL(inbuf,smb_vwv1);
-
- pcnt = SVAL(inbuf,smb_vwv2);
- poff = SVAL(inbuf,smb_vwv3);
- pdisp = SVAL(inbuf,smb_vwv4);
-
- dcnt = SVAL(inbuf,smb_vwv5);
- doff = SVAL(inbuf,smb_vwv6);
- ddisp = SVAL(inbuf,smb_vwv7);
-
- pscnt += pcnt;
- dscnt += dcnt;
-
- if (dscnt > tdscnt || pscnt > tpscnt)
- goto bad_param;
-
- if (pcnt) {
- if (pdisp+pcnt > tpscnt)
- goto bad_param;
- if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
- goto bad_param;
- if (pdisp > tpscnt)
- goto bad_param;
- if ((smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) ||
- (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
- goto bad_param;
- if (params + pdisp < params)
- goto bad_param;
-
- memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
+ if (outsize == 0) {
+ END_PROFILE(SMBtrans);
+ return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
}
- if (dcnt) {
- if (ddisp+dcnt > tdscnt)
- goto bad_param;
- if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
- goto bad_param;
- if (ddisp > tdscnt)
- goto bad_param;
- if ((smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) ||
- (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
- goto bad_param;
- if (data + ddisp < data)
- goto bad_param;
-
- memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
- }
+ END_PROFILE(SMBtrans);
+ return outsize;
}
- DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
- name,tdscnt,tpscnt,suwcnt));
+ DLIST_ADD(conn->pending_trans, state);
- /*
- * WinCE wierdness....
- */
+ /* We need to send an interim response then receive the rest
+ of the parameter/data bytes */
+ outsize = set_message(outbuf,0,0,True);
+ show_msg(outbuf);
+ END_PROFILE(SMBtrans);
+ return outsize;
- fstrcpy( local_machine_name, get_local_machine_name() );
+ bad_param:
- if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine_name, strlen(local_machine_name)) == 0) &&
- (name[strlen(local_machine_name)+1] == '\\'))
- name_offset = strlen(local_machine_name)+1;
+ DEBUG(0,("reply_trans: invalid trans parameters\n"));
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+}
+
+/****************************************************************************
+ Reply to a secondary SMBtrans.
+ ****************************************************************************/
- if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) {
- name_offset += strlen("\\PIPE");
+int reply_transs(connection_struct *conn, char *inbuf,char *outbuf,
+ int size, int bufsize)
+{
+ int outsize = 0;
+ unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
+ struct trans_state *state;
+ NTSTATUS result;
- /* Win9x weirdness. When talking to a unicode server Win9x
- only sends \PIPE instead of \PIPE\ */
+ START_PROFILE(SMBtranss);
- if (name[name_offset] == '\\')
- name_offset++;
+ show_msg(inbuf);
- DEBUG(5,("calling named_pipe\n"));
- outsize = named_pipe(conn,vuid,outbuf,
- name+name_offset,setup,data,params,
- suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
- } else {
- DEBUG(3,("invalid pipe name\n"));
- outsize = 0;
+ for (state = conn->pending_trans; state != NULL;
+ state = state->next) {
+ if (state->mid == SVAL(inbuf,smb_mid)) {
+ break;
+ }
}
-
- SAFE_FREE(data);
- SAFE_FREE(params);
- SAFE_FREE(setup);
-
- srv_signing_trans_stop();
+ if ((state == NULL) || (state->cmd != SMBtrans)) {
+ END_PROFILE(SMBtranss);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
- if (close_on_completion)
- close_cnum(conn,vuid);
+ /* Revise total_params and total_data in case they have changed
+ * downwards */
- if (one_way) {
- END_PROFILE(SMBtrans);
- return(-1);
+ if (SVAL(inbuf, smb_vwv0) < state->total_param)
+ state->total_param = SVAL(inbuf,smb_vwv0);
+ if (SVAL(inbuf, smb_vwv1) < state->total_data)
+ state->total_data = SVAL(inbuf,smb_vwv1);
+
+ pcnt = SVAL(inbuf, smb_spscnt);
+ poff = SVAL(inbuf, smb_spsoff);
+ pdisp = SVAL(inbuf, smb_spsdisp);
+
+ dcnt = SVAL(inbuf, smb_sdscnt);
+ doff = SVAL(inbuf, smb_sdsoff);
+ ddisp = SVAL(inbuf, smb_sdsdisp);
+
+ state->received_param += pcnt;
+ state->received_data += dcnt;
+
+ if ((state->received_data > state->total_data) ||
+ (state->received_param > state->total_param))
+ goto bad_param;
+
+ if (pcnt) {
+ if (pdisp+pcnt > state->total_param)
+ goto bad_param;
+ if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
+ goto bad_param;
+ if (pdisp > state->total_param)
+ goto bad_param;
+ if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
+ (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->param + pdisp < state->param)
+ goto bad_param;
+
+ memcpy(state->param+pdisp,smb_base(inbuf)+poff,
+ pcnt);
}
-
- if (outsize == 0) {
- END_PROFILE(SMBtrans);
+
+ if (dcnt) {
+ if (ddisp+dcnt > state->total_data)
+ goto bad_param;
+ if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
+ goto bad_param;
+ if (ddisp > state->total_data)
+ goto bad_param;
+ if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
+ (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->data + ddisp < state->data)
+ goto bad_param;
+
+ memcpy(state->data+ddisp, smb_base(inbuf)+doff,
+ dcnt);
+ }
+
+ if ((state->received_param < state->total_param) ||
+ (state->received_data < state->total_data)) {
+ END_PROFILE(SMBtranss);
+ return -1;
+ }
+
+ /* construct_reply_common has done us the favor to pre-fill the
+ * command field with SMBtranss which is wrong :-)
+ */
+ SCVAL(outbuf,smb_com,SMBtrans);
+
+ result = handle_trans(conn, state, outbuf, &outsize);
+
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+
+ if ((outsize == 0) || !NT_STATUS_IS_OK(result)) {
+ END_PROFILE(SMBtranss);
return(ERROR_DOS(ERRSRV,ERRnosupport));
}
- END_PROFILE(SMBtrans);
+ END_PROFILE(SMBtranss);
return(outsize);
-
bad_param:
- srv_signing_trans_stop();
- DEBUG(0,("reply_trans: invalid trans parameters\n"));
- SAFE_FREE(data);
- SAFE_FREE(params);
- SAFE_FREE(setup);
- END_PROFILE(SMBtrans);
+ DEBUG(0,("reply_transs: invalid trans parameters\n"));
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtranss);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index 1e2a2488515..4d4d9d22591 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -798,6 +798,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
*rdata_len = 0;
*rparam_len = 6;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
SSVALS(*rparam,0,ERRunknownlevel);
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,0);
@@ -817,6 +820,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
if (mdrcnt > 0) {
*rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
desc.base = *rdata;
desc.buflen = mdrcnt;
} else {
@@ -846,6 +852,9 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
*rdata_len = desc.usedlen;
*rparam_len = 6;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
SSVALS(*rparam,0,desc.errcode);
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,desc.neededlen);
@@ -896,6 +905,9 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
*rdata_len = 0;
*rparam_len = 6;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
SSVALS(*rparam,0,ERRunknownlevel);
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,0);
@@ -1034,107 +1046,108 @@ static int get_server_info(uint32 servertype,
struct srv_info_struct **servers,
const char *domain)
{
- int count=0;
- int alloced=0;
- char **lines;
- BOOL local_list_only;
- int i;
+ int count=0;
+ int alloced=0;
+ char **lines;
+ BOOL local_list_only;
+ int i;
- lines = file_lines_load(lock_path(SERVER_LIST), NULL);
- if (!lines) {
- DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
- return(0);
- }
+ lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
+ if (!lines) {
+ DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
+ return 0;
+ }
- /* request for everything is code for request all servers */
- if (servertype == SV_TYPE_ALL)
- servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+ /* request for everything is code for request all servers */
+ if (servertype == SV_TYPE_ALL) {
+ servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+ }
- local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
+ local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
- DEBUG(4,("Servertype search: %8x\n",servertype));
+ DEBUG(4,("Servertype search: %8x\n",servertype));
- for (i=0;lines[i];i++) {
- fstring stype;
- struct srv_info_struct *s;
- const char *ptr = lines[i];
- BOOL ok = True;
+ for (i=0;lines[i];i++) {
+ fstring stype;
+ struct srv_info_struct *s;
+ const char *ptr = lines[i];
+ BOOL ok = True;
- if (!*ptr) continue;
+ if (!*ptr) {
+ continue;
+ }
- if (count == alloced) {
- struct srv_info_struct *ts;
-
- alloced += 10;
- ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
- if (!ts) {
- DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
- return(0);
- }
- else *servers = ts;
- memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
- }
- s = &(*servers)[count];
+ if (count == alloced) {
+ alloced += 10;
+ *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
+ if (!*servers) {
+ DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
+ file_lines_free(lines);
+ return 0;
+ }
+ memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
+ }
+ s = &(*servers)[count];
- if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
- if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
- if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
- if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
- /* this allows us to cope with an old nmbd */
- fstrcpy(s->domain,lp_workgroup());
- }
+ if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
+ continue;
+ }
+ if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
+ continue;
+ }
+ if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
+ continue;
+ }
+ if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
+ /* this allows us to cope with an old nmbd */
+ fstrcpy(s->domain,lp_workgroup());
+ }
- if (sscanf(stype,"%X",&s->type) != 1) {
- DEBUG(4,("r:host file "));
- ok = False;
- }
+ if (sscanf(stype,"%X",&s->type) != 1) {
+ DEBUG(4,("r:host file "));
+ ok = False;
+ }
- /* Filter the servers/domains we return based on what was asked for. */
+ /* Filter the servers/domains we return based on what was asked for. */
- /* Check to see if we are being asked for a local list only. */
- if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
- DEBUG(4,("r: local list only"));
- ok = False;
- }
+ /* Check to see if we are being asked for a local list only. */
+ if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
+ DEBUG(4,("r: local list only"));
+ ok = False;
+ }
- /* doesn't match up: don't want it */
- if (!(servertype & s->type)) {
- DEBUG(4,("r:serv type "));
- ok = False;
- }
+ /* doesn't match up: don't want it */
+ if (!(servertype & s->type)) {
+ DEBUG(4,("r:serv type "));
+ ok = False;
+ }
- if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
- (s->type & SV_TYPE_DOMAIN_ENUM))
- {
- DEBUG(4,("s: dom mismatch "));
- ok = False;
- }
+ if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
+ (s->type & SV_TYPE_DOMAIN_ENUM)) {
+ DEBUG(4,("s: dom mismatch "));
+ ok = False;
+ }
- if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
- {
- ok = False;
- }
+ if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
+ ok = False;
+ }
- /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
- s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
+ /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
+ s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
- if (ok)
- {
- DEBUG(4,("**SV** %20s %8x %25s %15s\n",
- s->name, s->type, s->comment, s->domain));
-
- s->server_added = True;
- count++;
- }
- else
- {
- DEBUG(4,("%20s %8x %25s %15s\n",
- s->name, s->type, s->comment, s->domain));
- }
- }
+ if (ok) {
+ DEBUG(4,("**SV** %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+ s->server_added = True;
+ count++;
+ } else {
+ DEBUG(4,("%20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+ }
+ }
- file_lines_free(lines);
- return(count);
+ file_lines_free(lines);
+ return count;
}
/*******************************************************************
@@ -1145,75 +1158,79 @@ static int fill_srv_info(struct srv_info_struct *service,
int uLevel, char **buf, int *buflen,
char **stringbuf, int *stringspace, char *baseaddr)
{
- int struct_len;
- char* p;
- char* p2;
- int l2;
- int len;
+ int struct_len;
+ char* p;
+ char* p2;
+ int l2;
+ int len;
- switch (uLevel) {
- case 0: struct_len = 16; break;
- case 1: struct_len = 26; break;
- default: return -1;
- }
-
- if (!buf)
- {
- len = 0;
- switch (uLevel)
- {
- case 1:
- len = strlen(service->comment)+1;
- break;
+ switch (uLevel) {
+ case 0:
+ struct_len = 16;
+ break;
+ case 1:
+ struct_len = 26;
+ break;
+ default:
+ return -1;
}
+
+ if (!buf) {
+ len = 0;
+ switch (uLevel) {
+ case 1:
+ len = strlen(service->comment)+1;
+ break;
+ }
- if (buflen) *buflen = struct_len;
- if (stringspace) *stringspace = len;
- return struct_len + len;
- }
+ if (buflen) {
+ *buflen = struct_len;
+ }
+ if (stringspace) {
+ *stringspace = len;
+ }
+ return struct_len + len;
+ }
- len = struct_len;
- p = *buf;
- if (*buflen < struct_len) return -1;
- if (stringbuf)
- {
- p2 = *stringbuf;
- l2 = *stringspace;
- }
- else
- {
- p2 = p + struct_len;
- l2 = *buflen - struct_len;
- }
- if (!baseaddr) baseaddr = p;
+ len = struct_len;
+ p = *buf;
+ if (*buflen < struct_len) {
+ return -1;
+ }
+ if (stringbuf) {
+ p2 = *stringbuf;
+ l2 = *stringspace;
+ } else {
+ p2 = p + struct_len;
+ l2 = *buflen - struct_len;
+ }
+ if (!baseaddr) {
+ baseaddr = p;
+ }
- switch (uLevel)
- {
- case 0:
- push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
- break;
-
- case 1:
- push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
- SIVAL(p,18,service->type);
- SIVAL(p,22,PTR_DIFF(p2,baseaddr));
- len += CopyAndAdvance(&p2,service->comment,&l2);
- break;
- }
-
- if (stringbuf)
- {
- *buf = p + struct_len;
- *buflen -= struct_len;
- *stringbuf = p2;
- *stringspace = l2;
- }
- else
- {
- *buf = p2;
- *buflen -= len;
- }
- return len;
+ switch (uLevel) {
+ case 0:
+ push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
+ break;
+
+ case 1:
+ push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
+ SIVAL(p,18,service->type);
+ SIVAL(p,22,PTR_DIFF(p2,baseaddr));
+ len += CopyAndAdvance(&p2,service->comment,&l2);
+ break;
+ }
+
+ if (stringbuf) {
+ *buf = p + struct_len;
+ *buflen -= struct_len;
+ *stringbuf = p2;
+ *stringspace = l2;
+ } else {
+ *buf = p2;
+ *buflen -= len;
+ }
+ return len;
}
@@ -1231,124 +1248,143 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
int mdrcnt, int mprcnt, char **rdata,
char **rparam, int *rdata_len, int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- int buf_len = SVAL(p,2);
- uint32 servertype = IVAL(p,4);
- char *p2;
- int data_len, fixed_len, string_len;
- int f_len = 0, s_len = 0;
- struct srv_info_struct *servers=NULL;
- int counted=0,total=0;
- int i,missed;
- fstring domain;
- BOOL domain_request;
- BOOL local_request;
-
- /* If someone sets all the bits they don't really mean to set
- DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
- known servers. */
-
- if (servertype == SV_TYPE_ALL)
- servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
-
- /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
- any other bit (they may just set this bit on it's own) they
- want all the locally seen servers. However this bit can be
- set on its own so set the requested servers to be
- ALL - DOMAIN_ENUM. */
-
- if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
- servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
-
- domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
- local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
-
- p += 8;
-
- if (!prefix_ok(str1,"WrLehD")) return False;
- if (!check_server_info(uLevel,str2)) return False;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel = SVAL(p,0);
+ int buf_len = SVAL(p,2);
+ uint32 servertype = IVAL(p,4);
+ char *p2;
+ int data_len, fixed_len, string_len;
+ int f_len = 0, s_len = 0;
+ struct srv_info_struct *servers=NULL;
+ int counted=0,total=0;
+ int i,missed;
+ fstring domain;
+ BOOL domain_request;
+ BOOL local_request;
+
+ /* If someone sets all the bits they don't really mean to set
+ DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
+ known servers. */
+
+ if (servertype == SV_TYPE_ALL) {
+ servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+ }
+
+ /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
+ any other bit (they may just set this bit on it's own) they
+ want all the locally seen servers. However this bit can be
+ set on its own so set the requested servers to be
+ ALL - DOMAIN_ENUM. */
+
+ if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
+ servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
+ }
+
+ domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
+ local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
+
+ p += 8;
+
+ if (!prefix_ok(str1,"WrLehD")) {
+ return False;
+ }
+ if (!check_server_info(uLevel,str2)) {
+ return False;
+ }
- DEBUG(4, ("server request level: %s %8x ", str2, servertype));
- DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
- DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
-
- if (strcmp(str1, "WrLehDz") == 0) {
- pull_ascii_fstring(domain, p);
- } else {
- fstrcpy(domain, lp_workgroup());
- }
-
- if (lp_browse_list())
- total = get_server_info(servertype,&servers,domain);
-
- data_len = fixed_len = string_len = 0;
- missed = 0;
-
- if (total > 0)
- qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
-
- {
- char *lastname=NULL;
-
- for (i=0;i<total;i++)
- {
- struct srv_info_struct *s = &servers[i];
- if (lastname && strequal(lastname,s->name)) continue;
- lastname = s->name;
- data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
- DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
- s->name, s->type, s->comment, s->domain));
+ DEBUG(4, ("server request level: %s %8x ", str2, servertype));
+ DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
+ DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
+
+ if (strcmp(str1, "WrLehDz") == 0) {
+ pull_ascii_fstring(domain, p);
+ } else {
+ fstrcpy(domain, lp_workgroup());
+ }
+
+ if (lp_browse_list()) {
+ total = get_server_info(servertype,&servers,domain);
+ }
+
+ data_len = fixed_len = string_len = 0;
+ missed = 0;
+
+ if (total > 0) {
+ qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
+ }
+
+ {
+ char *lastname=NULL;
+
+ for (i=0;i<total;i++) {
+ struct srv_info_struct *s = &servers[i];
+
+ if (lastname && strequal(lastname,s->name)) {
+ continue;
+ }
+ lastname = s->name;
+ data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
+ DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
- if (data_len <= buf_len) {
- counted++;
- fixed_len += f_len;
- string_len += s_len;
- } else {
- missed++;
- }
- }
- }
-
- *rdata_len = fixed_len + string_len;
- *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
- memset(*rdata,'\0',*rdata_len);
+ if (data_len <= buf_len) {
+ counted++;
+ fixed_len += f_len;
+ string_len += s_len;
+ } else {
+ missed++;
+ }
+ }
+ }
+
+ *rdata_len = fixed_len + string_len;
+ *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
+ memset(*rdata,'\0',*rdata_len);
- p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
- p = *rdata;
- f_len = fixed_len;
- s_len = string_len;
-
- {
- char *lastname=NULL;
- int count2 = counted;
- for (i = 0; i < total && count2;i++)
- {
- struct srv_info_struct *s = &servers[i];
- if (lastname && strequal(lastname,s->name)) continue;
- lastname = s->name;
- fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
- DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
- s->name, s->type, s->comment, s->domain));
- count2--;
- }
- }
+ p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
+ p = *rdata;
+ f_len = fixed_len;
+ s_len = string_len;
+
+ {
+ char *lastname=NULL;
+ int count2 = counted;
+
+ for (i = 0; i < total && count2;i++) {
+ struct srv_info_struct *s = &servers[i];
+
+ if (lastname && strequal(lastname,s->name)) {
+ continue;
+ }
+ lastname = s->name;
+ fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
+ DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+ count2--;
+ }
+ }
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,counted);
- SSVAL(*rparam,6,counted+missed);
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,counted);
+ SSVAL(*rparam,6,counted+missed);
- SAFE_FREE(servers);
+ SAFE_FREE(servers);
- DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
- domain,uLevel,counted,counted+missed));
+ DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
+ domain,uLevel,counted,counted+missed));
- return(True);
+ return True;
}
/****************************************************************************
@@ -1359,30 +1395,35 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa
int mdrcnt, int mprcnt, char **rdata,
char **rparam, int *rdata_len, int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- int buf_len = SVAL(p,2);
- int counted=0;
- int missed=0;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel = SVAL(p,0);
+ int buf_len = SVAL(p,2);
+ int counted=0;
+ int missed=0;
DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
str1, str2, p, uLevel, buf_len));
- if (!prefix_ok(str1,"zWrLeh")) return False;
+ if (!prefix_ok(str1,"zWrLeh")) {
+ return False;
+ }
- *rdata_len = 0;
+ *rdata_len = 0;
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
- SSVAL(*rparam,0,0x08AC); /* informational warning message */
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,counted);
- SSVAL(*rparam,6,counted+missed);
+ SSVAL(*rparam,0,0x08AC); /* informational warning message */
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,counted);
+ SSVAL(*rparam,6,counted+missed);
- return(True);
+ return True;
}
/****************************************************************************
@@ -1391,117 +1432,146 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa
static BOOL check_share_info(int uLevel, char* id)
{
- switch( uLevel ) {
- case 0:
- if (strcmp(id,"B13") != 0) return False;
- break;
- case 1:
- if (strcmp(id,"B13BWz") != 0) return False;
- break;
- case 2:
- if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
- break;
- case 91:
- if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
- break;
- default: return False;
- }
- return True;
+ switch( uLevel ) {
+ case 0:
+ if (strcmp(id,"B13") != 0) {
+ return False;
+ }
+ break;
+ case 1:
+ if (strcmp(id,"B13BWz") != 0) {
+ return False;
+ }
+ break;
+ case 2:
+ if (strcmp(id,"B13BWzWWWzB9B") != 0) {
+ return False;
+ }
+ break;
+ case 91:
+ if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
+ return False;
+ }
+ break;
+ default:
+ return False;
+ }
+ return True;
}
static int fill_share_info(connection_struct *conn, int snum, int uLevel,
char** buf, int* buflen,
char** stringbuf, int* stringspace, char* baseaddr)
{
- int struct_len;
- char* p;
- char* p2;
- int l2;
- int len;
+ int struct_len;
+ char* p;
+ char* p2;
+ int l2;
+ int len;
- switch( uLevel ) {
- case 0: struct_len = 13; break;
- case 1: struct_len = 20; break;
- case 2: struct_len = 40; break;
- case 91: struct_len = 68; break;
- default: return -1;
- }
+ switch( uLevel ) {
+ case 0:
+ struct_len = 13;
+ break;
+ case 1:
+ struct_len = 20;
+ break;
+ case 2:
+ struct_len = 40;
+ break;
+ case 91:
+ struct_len = 68;
+ break;
+ default:
+ return -1;
+ }
- if (!buf)
- {
- len = 0;
- if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
- if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
- if (buflen) *buflen = struct_len;
- if (stringspace) *stringspace = len;
- return struct_len + len;
- }
+ if (!buf) {
+ len = 0;
+
+ if (uLevel > 0) {
+ len += StrlenExpanded(conn,snum,lp_comment(snum));
+ }
+ if (uLevel > 1) {
+ len += strlen(lp_pathname(snum)) + 1;
+ }
+ if (buflen) {
+ *buflen = struct_len;
+ }
+ if (stringspace) {
+ *stringspace = len;
+ }
+ return struct_len + len;
+ }
- len = struct_len;
- p = *buf;
- if ((*buflen) < struct_len) return -1;
- if (stringbuf)
- {
- p2 = *stringbuf;
- l2 = *stringspace;
- }
- else
- {
- p2 = p + struct_len;
- l2 = (*buflen) - struct_len;
- }
- if (!baseaddr) baseaddr = p;
+ len = struct_len;
+ p = *buf;
+ if ((*buflen) < struct_len) {
+ return -1;
+ }
+
+ if (stringbuf) {
+ p2 = *stringbuf;
+ l2 = *stringspace;
+ } else {
+ p2 = p + struct_len;
+ l2 = (*buflen) - struct_len;
+ }
+
+ if (!baseaddr) {
+ baseaddr = p;
+ }
- push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
+ push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
- if (uLevel > 0)
- {
- int type;
- SCVAL(p,13,0);
- type = STYPE_DISKTREE;
- if (lp_print_ok(snum)) type = STYPE_PRINTQ;
- if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
- SSVAL(p,14,type); /* device type */
- SIVAL(p,16,PTR_DIFF(p2,baseaddr));
- len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
- }
+ if (uLevel > 0) {
+ int type;
+
+ SCVAL(p,13,0);
+ type = STYPE_DISKTREE;
+ if (lp_print_ok(snum)) {
+ type = STYPE_PRINTQ;
+ }
+ if (strequal("IPC",lp_fstype(snum))) {
+ type = STYPE_IPC;
+ }
+ SSVAL(p,14,type); /* device type */
+ SIVAL(p,16,PTR_DIFF(p2,baseaddr));
+ len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
+ }
- if (uLevel > 1)
- {
- SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
- SSVALS(p,22,-1); /* max uses */
- SSVAL(p,24,1); /* current uses */
- SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
- len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
- memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
- }
+ if (uLevel > 1) {
+ SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
+ SSVALS(p,22,-1); /* max uses */
+ SSVAL(p,24,1); /* current uses */
+ SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
+ len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
+ memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
+ }
- if (uLevel > 2)
- {
- memset(p+40,0,SHPWLEN+2);
- SSVAL(p,50,0);
- SIVAL(p,52,0);
- SSVAL(p,56,0);
- SSVAL(p,58,0);
- SIVAL(p,60,0);
- SSVAL(p,64,0);
- SSVAL(p,66,0);
- }
+ if (uLevel > 2) {
+ memset(p+40,0,SHPWLEN+2);
+ SSVAL(p,50,0);
+ SIVAL(p,52,0);
+ SSVAL(p,56,0);
+ SSVAL(p,58,0);
+ SIVAL(p,60,0);
+ SSVAL(p,64,0);
+ SSVAL(p,66,0);
+ }
- if (stringbuf)
- {
- (*buf) = p + struct_len;
- (*buflen) -= struct_len;
- (*stringbuf) = p2;
- (*stringspace) = l2;
- }
- else
- {
- (*buf) = p2;
- (*buflen) -= len;
- }
- return len;
+ if (stringbuf) {
+ (*buf) = p + struct_len;
+ (*buflen) -= struct_len;
+ (*stringbuf) = p2;
+ (*stringspace) = l2;
+ } else {
+ (*buf) = p2;
+ (*buflen) -= len;
+ }
+
+ return len;
}
static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -1509,31 +1579,45 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *netname = skip_string(str2,1);
- char *p = skip_string(netname,1);
- int uLevel = SVAL(p,0);
- int snum = find_service(netname);
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *netname = skip_string(str2,1);
+ char *p = skip_string(netname,1);
+ int uLevel = SVAL(p,0);
+ int snum = find_service(netname);
- if (snum < 0) return False;
+ if (snum < 0) {
+ return False;
+ }
- /* check it's a supported varient */
- if (!prefix_ok(str1,"zWrLh")) return False;
- if (!check_share_info(uLevel,str2)) return False;
+ /* check it's a supported varient */
+ if (!prefix_ok(str1,"zWrLh")) {
+ return False;
+ }
+ if (!check_share_info(uLevel,str2)) {
+ return False;
+ }
- *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- p = *rdata;
- *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
- if (*rdata_len < 0) return False;
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ p = *rdata;
+ *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
+ if (*rdata_len < 0) {
+ return False;
+ }
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len);
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
+ SSVAL(*rparam,4,*rdata_len);
- return(True);
+ return True;
}
/****************************************************************************
@@ -1557,78 +1641,93 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
int *rdata_len,
int *rparam_len )
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- int buf_len = SVAL(p,2);
- char *p2;
- int count=lp_numservices();
- int total=0,counted=0;
- BOOL missed = False;
- int i;
- int data_len, fixed_len, string_len;
- int f_len = 0, s_len = 0;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel = SVAL(p,0);
+ int buf_len = SVAL(p,2);
+ char *p2;
+ int count = 0;
+ int total=0,counted=0;
+ BOOL missed = False;
+ int i;
+ int data_len, fixed_len, string_len;
+ int f_len = 0, s_len = 0;
- if (!prefix_ok(str1,"WrLeh")) return False;
- if (!check_share_info(uLevel,str2)) return False;
+ if (!prefix_ok(str1,"WrLeh")) {
+ return False;
+ }
+ if (!check_share_info(uLevel,str2)) {
+ return False;
+ }
- data_len = fixed_len = string_len = 0;
- for (i=0;i<count;i++) {
- fstring servicename_dos;
- if (!(lp_browseable(i) && lp_snum_ok(i)))
- continue;
- push_ascii_fstring(servicename_dos, lp_servicename(i));
- if( lp_browseable( i )
- && lp_snum_ok( i )
- && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
- {
- total++;
- data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
- if (data_len <= buf_len)
- {
- counted++;
- fixed_len += f_len;
- string_len += s_len;
- }
- else
- missed = True;
- }
- }
- *rdata_len = fixed_len + string_len;
- *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
- memset(*rdata,0,*rdata_len);
+ /* Ensure all the usershares are loaded. */
+ become_root();
+ count = load_usershare_shares();
+ unbecome_root();
+
+ data_len = fixed_len = string_len = 0;
+ for (i=0;i<count;i++) {
+ fstring servicename_dos;
+ if (!(lp_browseable(i) && lp_snum_ok(i))) {
+ continue;
+ }
+ push_ascii_fstring(servicename_dos, lp_servicename(i));
+ /* Maximum name length = 13. */
+ if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
+ total++;
+ data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
+ if (data_len <= buf_len) {
+ counted++;
+ fixed_len += f_len;
+ string_len += s_len;
+ } else {
+ missed = True;
+ }
+ }
+ }
+
+ *rdata_len = fixed_len + string_len;
+ *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
+ memset(*rdata,0,*rdata_len);
- p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
- p = *rdata;
- f_len = fixed_len;
- s_len = string_len;
- for( i = 0; i < count; i++ )
- {
- fstring servicename_dos;
- if (!(lp_browseable(i) && lp_snum_ok(i)))
- continue;
- push_ascii_fstring(servicename_dos, lp_servicename(i));
- if( lp_browseable( i )
- && lp_snum_ok( i )
- && (strlen(servicename_dos) < 13) )
- {
- if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
- break;
- }
- }
+ p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
+ p = *rdata;
+ f_len = fixed_len;
+ s_len = string_len;
+
+ for( i = 0; i < count; i++ ) {
+ fstring servicename_dos;
+ if (!(lp_browseable(i) && lp_snum_ok(i))) {
+ continue;
+ }
+
+ push_ascii_fstring(servicename_dos, lp_servicename(i));
+ if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
+ if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
+ break;
+ }
+ }
+ }
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,counted);
- SSVAL(*rparam,6,total);
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,counted);
+ SSVAL(*rparam,6,total);
- DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
- counted,total,uLevel,
- buf_len,*rdata_len,mdrcnt));
- return(True);
+ DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
+ counted,total,uLevel,
+ buf_len,*rdata_len,mdrcnt));
+
+ return True;
}
/****************************************************************************
@@ -1640,87 +1739,110 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- fstring sharename;
- fstring comment;
- pstring pathname;
- char *command, *cmdname;
- unsigned int offset;
- int snum;
- int res = ERRunsup;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel = SVAL(p,0);
+ fstring sharename;
+ fstring comment;
+ pstring pathname;
+ char *command, *cmdname;
+ unsigned int offset;
+ int snum;
+ int res = ERRunsup;
- /* check it's a supported varient */
- if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
- if (!check_share_info(uLevel,str2)) return False;
- if (uLevel != 2) return False;
-
- pull_ascii_fstring(sharename,data);
- snum = find_service(sharename);
- if (snum >= 0) { /* already exists */
- res = ERRfilexists;
- goto error_exit;
- }
-
- /* only support disk share adds */
- if (SVAL(data,14)!=STYPE_DISKTREE) return False;
-
- offset = IVAL(data, 16);
- if (offset >= mdrcnt) {
- res = ERRinvalidparam;
- goto error_exit;
- }
- pull_ascii_fstring(comment, offset? (data+offset) : "");
-
- offset = IVAL(data, 26);
- if (offset >= mdrcnt) {
- res = ERRinvalidparam;
- goto error_exit;
- }
- pull_ascii_pstring(pathname, offset? (data+offset) : "");
-
- string_replace(sharename, '"', ' ');
- string_replace(pathname, '"', ' ');
- string_replace(comment, '"', ' ');
-
- cmdname = lp_add_share_cmd();
-
- if (!cmdname || *cmdname == '\0') return False;
-
- asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
- lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
-
- if (command) {
- DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
- if ((res = smbrun(command, NULL)) != 0) {
- DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
- SAFE_FREE(command);
- res = ERRnoaccess;
- goto error_exit;
- } else {
- SAFE_FREE(command);
- message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
- }
- } else return False;
-
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len);
- *rdata_len = 0;
+ /* check it's a supported varient */
+ if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
+ return False;
+ }
+ if (!check_share_info(uLevel,str2)) {
+ return False;
+ }
+ if (uLevel != 2) {
+ return False;
+ }
+
+ pull_ascii_fstring(sharename,data);
+ snum = find_service(sharename);
+ if (snum >= 0) { /* already exists */
+ res = ERRfilexists;
+ goto error_exit;
+ }
+
+ /* only support disk share adds */
+ if (SVAL(data,14)!=STYPE_DISKTREE) {
+ return False;
+ }
+
+ offset = IVAL(data, 16);
+ if (offset >= mdrcnt) {
+ res = ERRinvalidparam;
+ goto error_exit;
+ }
+
+ pull_ascii_fstring(comment, offset? (data+offset) : "");
+
+ offset = IVAL(data, 26);
+
+ if (offset >= mdrcnt) {
+ res = ERRinvalidparam;
+ goto error_exit;
+ }
+
+ pull_ascii_pstring(pathname, offset? (data+offset) : "");
+
+ string_replace(sharename, '"', ' ');
+ string_replace(pathname, '"', ' ');
+ string_replace(comment, '"', ' ');
+
+ cmdname = lp_add_share_cmd();
+
+ if (!cmdname || *cmdname == '\0') {
+ return False;
+ }
+
+ asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
+ lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
+
+ if (command) {
+ DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
+
+ if ((res = smbrun(command, NULL)) != 0) {
+ DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
+ SAFE_FREE(command);
+ res = ERRnoaccess;
+ goto error_exit;
+ } else {
+ SAFE_FREE(command);
+ message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
+ }
+ } else {
+ return False;
+ }
+
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
+ SSVAL(*rparam,4,*rdata_len);
+ *rdata_len = 0;
- return True;
-
- error_exit:
- *rparam_len = 4;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- *rdata_len = 0;
- SSVAL(*rparam,0,res);
- SSVAL(*rparam,2,0);
- return True;
+ return True;
+
+ error_exit:
+
+ *rparam_len = 4;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ *rdata_len = 0;
+ SSVAL(*rparam,0,res);
+ SSVAL(*rparam,2,0);
+ return True;
}
/****************************************************************************
@@ -1744,18 +1866,21 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
int num_entries;
- if (strcmp(str1,"WrLeh") != 0)
+ if (strcmp(str1,"WrLeh") != 0) {
return False;
+ }
- /* parameters
- * W-> resume context (number of users to skip)
- * r -> return parameter pointer to receive buffer
- * L -> length of receive buffer
- * e -> return parameter number of entries
- * h -> return parameter total number of users
- */
- if (strcmp("B21",str2) != 0)
+ /* parameters
+ * W-> resume context (number of users to skip)
+ * r -> return parameter pointer to receive buffer
+ * L -> length of receive buffer
+ * e -> return parameter number of entries
+ * h -> return parameter total number of users
+ */
+
+ if (strcmp("B21",str2) != 0) {
return False;
+ }
/* get list of domain groups SID_DOMAIN_GRP=2 */
become_root();
@@ -1779,6 +1904,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
*rdata_len = cli_buf_size;
*rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
p = *rdata;
@@ -1806,7 +1934,9 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
*rparam_len = 8;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-
+ if (!*rparam) {
+ return False;
+ }
SSVAL(*rparam, 0, errflags);
SSVAL(*rparam, 2, 0); /* converter word */
SSVAL(*rparam, 4, i); /* is this right?? */
@@ -1831,20 +1961,22 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
int uLevel = SVAL(p,0);
const char *level_string;
int count=0;
- SAM_ACCOUNT *sampw = NULL;
+ struct samu *sampw = NULL;
BOOL ret = False;
DOM_SID *sids;
gid_t *gids;
size_t num_groups;
size_t i;
- fstring grp_domain;
- fstring grp_name;
- enum SID_NAME_USE grp_type;
- struct passwd *passwd;
NTSTATUS result;
+ DOM_SID user_sid;
+ enum SID_NAME_USE type;
+ TALLOC_CTX *mem_ctx;
*rparam_len = 8;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
/* check it's a supported varient */
@@ -1864,48 +1996,72 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
*rdata_len = mdrcnt + 1024;
*rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-
+ if (!*rdata) {
+ return False;
+ }
SSVAL(*rparam,0,NERR_Success);
SSVAL(*rparam,2,0); /* converter word */
p = *rdata;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
/* Lookup the user information; This should only be one of
our accounts (not remote domains) */
- passwd = getpwnam_alloc(UserName);
-
- if (passwd == NULL)
- return False;
-
- pdb_init_sam( &sampw );
-
become_root(); /* ROOT BLOCK */
- if ( !pdb_getsampwnam(sampw, UserName) )
- goto out;
+ if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
+ NULL, NULL, &user_sid, &type)) {
+ DEBUG(10, ("lookup_name(%s) failed\n", UserName));
+ goto done;
+ }
+ if (type != SID_NAME_USER) {
+ DEBUG(10, ("%s is a %s, not a user\n", UserName,
+ sid_type_lookup(type)));
+ goto done;
+ }
+
+ if ( !(sampw = samu_new(mem_ctx)) ) {
+ DEBUG(0, ("samu_new() failed!\n"));
+ goto done;
+ }
+
+ if ( !pdb_getsampwsid(sampw, &user_sid) ) {
+ DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
+ sid_string_static(&user_sid), UserName));
+ goto done;
+ }
+
+ gids = NULL;
sids = NULL;
num_groups = 0;
- result = pdb_enum_group_memberships(pdb_get_username(sampw),
- passwd->pw_gid,
+ result = pdb_enum_group_memberships(mem_ctx, sampw,
&sids, &gids, &num_groups);
- if (!NT_STATUS_IS_OK(result))
- goto out;
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
+ UserName));
+ goto done;
+ }
for (i=0; i<num_groups; i++) {
+
+ const char *grp_name;
- if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
- pstrcpy(p, grp_name);
+ if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
+ pstrcpy(p, grp_name);
p += 21;
count++;
}
}
- SAFE_FREE(sids);
-
*rdata_len = PTR_DIFF(p,*rdata);
SSVAL(*rparam,4,count); /* is this right?? */
@@ -1913,11 +2069,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
ret = True;
-out:
+done:
unbecome_root(); /* END ROOT BLOCK */
- pdb_free_sam( &sampw );
- passwd_free(&passwd);
+ TALLOC_FREE(mem_ctx);
return ret;
}
@@ -1959,6 +2114,9 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
*rparam_len = 8;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
/* check it's a supported varient */
if (strcmp("B21",str2) != 0)
@@ -1966,6 +2124,9 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
*rdata_len = cli_buf_size;
*rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
p = *rdata;
@@ -2023,43 +2184,48 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *p;
- *rparam_len = 4;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-
- *rdata_len = 21;
- *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
-
- p = *rdata;
-
- {
- struct tm *t;
- time_t unixdate = time(NULL);
-
- srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
- by NT in a "net time" operation,
- it seems to ignore the one below */
-
- /* the client expects to get localtime, not GMT, in this bit
- (I think, this needs testing) */
- t = localtime(&unixdate);
-
- SIVAL(p,4,0); /* msecs ? */
- SCVAL(p,8,t->tm_hour);
- SCVAL(p,9,t->tm_min);
- SCVAL(p,10,t->tm_sec);
- SCVAL(p,11,0); /* hundredths of seconds */
- SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
- SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
- SCVAL(p,16,t->tm_mday);
- SCVAL(p,17,t->tm_mon + 1);
- SSVAL(p,18,1900+t->tm_year);
- SCVAL(p,20,t->tm_wday);
- }
- return(True);
+ struct tm *t;
+ time_t unixdate = time(NULL);
+ char *p;
+
+ *rparam_len = 4;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+
+ *rdata_len = 21;
+ *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
+
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
+
+ p = *rdata;
+
+ srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
+ by NT in a "net time" operation,
+ it seems to ignore the one below */
+
+ /* the client expects to get localtime, not GMT, in this bit
+ (I think, this needs testing) */
+ t = localtime(&unixdate);
+
+ SIVAL(p,4,0); /* msecs ? */
+ SCVAL(p,8,t->tm_hour);
+ SCVAL(p,9,t->tm_min);
+ SCVAL(p,10,t->tm_sec);
+ SCVAL(p,11,0); /* hundredths of seconds */
+ SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
+ SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
+ SCVAL(p,16,t->tm_mday);
+ SCVAL(p,17,t->tm_mon + 1);
+ SSVAL(p,18,1900+t->tm_year);
+ SCVAL(p,20,t->tm_wday);
+
+ return True;
}
/****************************************************************************
@@ -2086,6 +2252,9 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
*rparam_len = 4;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
*rdata_len = 0;
@@ -2106,12 +2275,12 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
become_root();
- if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
+ if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
SSVAL(*rparam,0,NERR_Success);
}
unbecome_root();
- free_server_info(&server_info);
+ TALLOC_FREE(server_info);
}
data_blob_clear_free(&password);
}
@@ -2127,7 +2296,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
*/
if(SVAL(*rparam,0) != NERR_Success) {
- SAM_ACCOUNT *hnd = NULL;
+ struct samu *hnd = NULL;
if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
become_root();
@@ -2135,7 +2304,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
SSVAL(*rparam,0,NERR_Success);
}
unbecome_root();
- pdb_free_sam(&hnd);
+ TALLOC_FREE(hnd);
}
}
@@ -2158,6 +2327,9 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
char *p = param + 2;
*rparam_len = 2;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
*rdata_len = 0;
@@ -2189,7 +2361,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
(void)map_username(user);
- if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
+ if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
SSVAL(*rparam,0,NERR_Success);
}
@@ -2225,6 +2397,9 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
*rparam_len = 4;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
*rdata_len = 0;
if (!print_job_exists(sharename, jobid)) {
@@ -2288,6 +2463,9 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param
*rparam_len = 4;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
*rdata_len = 0;
snum = print_queue_snum(QueueName);
@@ -2362,6 +2540,9 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
return False;
*rparam_len = 4;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
if ( (snum = lp_servicenumber(sharename)) == -1 ) {
DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
@@ -2421,103 +2602,123 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- char *p2;
- int struct_len;
-
- DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
-
- /* check it's a supported varient */
- if (!prefix_ok(str1,"WrLh")) return False;
- switch( uLevel ) {
- case 0:
- if (strcmp(str2,"B16") != 0) return False;
- struct_len = 16;
- break;
- case 1:
- if (strcmp(str2,"B16BBDz") != 0) return False;
- struct_len = 26;
- break;
- case 2:
- if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
- != 0) return False;
- struct_len = 134;
- break;
- case 3:
- if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
- != 0) return False;
- struct_len = 144;
- break;
- case 20:
- if (strcmp(str2,"DN") != 0) return False;
- struct_len = 6;
- break;
- case 50:
- if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
- struct_len = 42;
- break;
- default: return False;
- }
-
- *rdata_len = mdrcnt;
- *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-
- p = *rdata;
- p2 = p + struct_len;
- if (uLevel != 20) {
- srvstr_push(NULL, p,get_local_machine_name(),16,
- STR_ASCII|STR_UPPER|STR_TERMINATE);
- }
- p += 16;
- if (uLevel > 0)
- {
- struct srv_info_struct *servers=NULL;
- int i,count;
- pstring comment;
- uint32 servertype= lp_default_server_announce();
-
- push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
-
- 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())) {
- servertype = servers[i].type;
- push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
- }
- }
- }
- SAFE_FREE(servers);
-
- SCVAL(p,0,lp_major_announce_version());
- SCVAL(p,1,lp_minor_announce_version());
- SIVAL(p,2,servertype);
-
- if (mdrcnt == struct_len) {
- SIVAL(p,6,0);
- } else {
- SIVAL(p,6,PTR_DIFF(p2,*rdata));
- standard_sub_conn(conn,comment,sizeof(comment));
- StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
- p2 = skip_string(p2,1);
- }
- }
- if (uLevel > 1)
- {
- return False; /* not yet implemented */
- }
-
- *rdata_len = PTR_DIFF(p2,*rdata);
-
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,*rdata_len);
-
- return(True);
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel = SVAL(p,0);
+ char *p2;
+ int struct_len;
+
+ DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
+
+ /* check it's a supported varient */
+ if (!prefix_ok(str1,"WrLh")) {
+ return False;
+ }
+
+ switch( uLevel ) {
+ case 0:
+ if (strcmp(str2,"B16") != 0) {
+ return False;
+ }
+ struct_len = 16;
+ break;
+ case 1:
+ if (strcmp(str2,"B16BBDz") != 0) {
+ return False;
+ }
+ struct_len = 26;
+ break;
+ case 2:
+ if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
+ return False;
+ }
+ struct_len = 134;
+ break;
+ case 3:
+ if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
+ return False;
+ }
+ struct_len = 144;
+ break;
+ case 20:
+ if (strcmp(str2,"DN") != 0) {
+ return False;
+ }
+ struct_len = 6;
+ break;
+ case 50:
+ if (strcmp(str2,"B16BBDzWWzzz") != 0) {
+ return False;
+ }
+ struct_len = 42;
+ break;
+ default:
+ return False;
+ }
+
+ *rdata_len = mdrcnt;
+ *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
+
+ p = *rdata;
+ p2 = p + struct_len;
+ if (uLevel != 20) {
+ srvstr_push(NULL, p,get_local_machine_name(),16,
+ STR_ASCII|STR_UPPER|STR_TERMINATE);
+ }
+ p += 16;
+ if (uLevel > 0) {
+ struct srv_info_struct *servers=NULL;
+ int i,count;
+ pstring comment;
+ uint32 servertype= lp_default_server_announce();
+
+ push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
+
+ 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())) {
+ servertype = servers[i].type;
+ push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
+ }
+ }
+ }
+
+ SAFE_FREE(servers);
+
+ SCVAL(p,0,lp_major_announce_version());
+ SCVAL(p,1,lp_minor_announce_version());
+ SIVAL(p,2,servertype);
+
+ if (mdrcnt == struct_len) {
+ SIVAL(p,6,0);
+ } else {
+ SIVAL(p,6,PTR_DIFF(p2,*rdata));
+ standard_sub_conn(conn,comment,sizeof(comment));
+ StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
+ p2 = skip_string(p2,1);
+ }
+ }
+
+ if (uLevel > 1) {
+ return False; /* not yet implemented */
+ }
+
+ *rdata_len = PTR_DIFF(p2,*rdata);
+
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
+ SSVAL(*rparam,4,*rdata_len);
+
+ return True;
}
/****************************************************************************
@@ -2529,67 +2730,73 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- char *p2;
- int level = SVAL(p,0);
-
- DEBUG(4,("NetWkstaGetInfo level %d\n",level));
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ char *p2;
+ int level = SVAL(p,0);
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ DEBUG(4,("NetWkstaGetInfo level %d\n",level));
- /* check it's a supported varient */
- if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
- return(False);
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
- *rdata_len = mdrcnt + 1024;
- *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ /* check it's a supported varient */
+ if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
+ return False;
+ }
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
+ *rdata_len = mdrcnt + 1024;
+ *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
- p = *rdata;
- p2 = p + 22;
+ SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,2,0); /* converter word */
+ p = *rdata;
+ p2 = p + 22;
- SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
- pstrcpy(p2,get_local_machine_name());
- strupper_m(p2);
- p2 = skip_string(p2,1);
- p += 4;
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
+ pstrcpy(p2,get_local_machine_name());
+ strupper_m(p2);
+ p2 = skip_string(p2,1);
+ p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
- pstrcpy(p2,current_user_info.smb_name);
- p2 = skip_string(p2,1);
- p += 4;
+ SIVAL(p,0,PTR_DIFF(p2,*rdata));
+ pstrcpy(p2,current_user_info.smb_name);
+ p2 = skip_string(p2,1);
+ p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
- pstrcpy(p2,lp_workgroup());
- strupper_m(p2);
- p2 = skip_string(p2,1);
- p += 4;
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
+ pstrcpy(p2,lp_workgroup());
+ strupper_m(p2);
+ p2 = skip_string(p2,1);
+ p += 4;
- SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
- SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
- p += 2;
+ SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
+ SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
+ p += 2;
- SIVAL(p,0,PTR_DIFF(p2,*rdata));
- pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
- p2 = skip_string(p2,1);
- p += 4;
+ SIVAL(p,0,PTR_DIFF(p2,*rdata));
+ pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
+ p2 = skip_string(p2,1);
+ p += 4;
- SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
- pstrcpy(p2,"");
- p2 = skip_string(p2,1);
- p += 4;
+ SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
+ pstrcpy(p2,"");
+ p2 = skip_string(p2,1);
+ p += 4;
- *rdata_len = PTR_DIFF(p2,*rdata);
+ *rdata_len = PTR_DIFF(p2,*rdata);
- SSVAL(*rparam,4,*rdata_len);
+ SSVAL(*rparam,4,*rdata_len);
- return(True);
+ return True;
}
/****************************************************************************
@@ -2786,6 +2993,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
*rparam_len = 6;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
@@ -2808,6 +3018,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
*rdata_len = mdrcnt + 1024;
*rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+ if (!*rdata) {
+ return False;
+ }
SSVAL(*rparam,0,NERR_Success);
SSVAL(*rparam,2,0); /* converter word */
@@ -2929,75 +3142,89 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- struct pack_desc desc;
- char* name;
- /* With share level security vuid will always be zero.
- Don't depend on vuser being non-null !!. JRA */
- user_struct *vuser = get_valid_user_struct(vuid);
- if(vuser != NULL)
- DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
- vuser->user.unix_name));
-
- uLevel = SVAL(p,0);
- name = p + 2;
-
- memset((char *)&desc,'\0',sizeof(desc));
-
- DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
-
- /* check it's a supported varient */
- if (strcmp(str1,"OOWb54WrLh") != 0) return False;
- if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- desc.subformat = NULL;
- desc.format = str2;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ struct pack_desc desc;
+ char* name;
+ /* With share level security vuid will always be zero.
+ Don't depend on vuser being non-null !!. JRA */
+ user_struct *vuser = get_valid_user_struct(vuid);
+
+ if(vuser != NULL) {
+ DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
+ vuser->user.unix_name));
+ }
+
+ uLevel = SVAL(p,0);
+ name = p + 2;
+
+ memset((char *)&desc,'\0',sizeof(desc));
+
+ DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
+
+ /* check it's a supported varient */
+ if (strcmp(str1,"OOWb54WrLh") != 0) {
+ return False;
+ }
+ if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
+ return False;
+ }
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ desc.subformat = NULL;
+ desc.format = str2;
- if (init_package(&desc,1,0))
- {
- PACKI(&desc,"W",0); /* code */
- PACKS(&desc,"B21",name); /* eff. name */
- PACKS(&desc,"B",""); /* pad */
- PACKI(&desc,"W",
- conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
- PACKI(&desc,"D",0); /* auth flags XXX */
- PACKI(&desc,"W",0); /* num logons */
- PACKI(&desc,"W",0); /* bad pw count */
- PACKI(&desc,"D",0); /* last logon */
- PACKI(&desc,"D",-1); /* last logoff */
- PACKI(&desc,"D",-1); /* logoff time */
- PACKI(&desc,"D",-1); /* kickoff time */
- PACKI(&desc,"D",0); /* password age */
- PACKI(&desc,"D",0); /* password can change */
- PACKI(&desc,"D",-1); /* password must change */
- {
- fstring mypath;
- fstrcpy(mypath,"\\\\");
- fstrcat(mypath,get_local_machine_name());
- strupper_m(mypath);
- PACKS(&desc,"z",mypath); /* computer */
- }
- PACKS(&desc,"z",lp_workgroup());/* domain */
-
- PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
-
- PACKI(&desc,"D",0x00000000); /* reserved */
- }
-
- *rdata_len = desc.usedlen;
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,desc.neededlen);
-
- DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
- return(True);
+ if (init_package(&desc,1,0)) {
+ PACKI(&desc,"W",0); /* code */
+ PACKS(&desc,"B21",name); /* eff. name */
+ PACKS(&desc,"B",""); /* pad */
+ PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+ PACKI(&desc,"D",0); /* auth flags XXX */
+ PACKI(&desc,"W",0); /* num logons */
+ PACKI(&desc,"W",0); /* bad pw count */
+ PACKI(&desc,"D",0); /* last logon */
+ PACKI(&desc,"D",-1); /* last logoff */
+ PACKI(&desc,"D",-1); /* logoff time */
+ PACKI(&desc,"D",-1); /* kickoff time */
+ PACKI(&desc,"D",0); /* password age */
+ PACKI(&desc,"D",0); /* password can change */
+ PACKI(&desc,"D",-1); /* password must change */
+
+ {
+ fstring mypath;
+ fstrcpy(mypath,"\\\\");
+ fstrcat(mypath,get_local_machine_name());
+ strupper_m(mypath);
+ PACKS(&desc,"z",mypath); /* computer */
+ }
+
+ PACKS(&desc,"z",lp_workgroup());/* domain */
+ PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
+ PACKI(&desc,"D",0x00000000); /* reserved */
+ }
+
+ *rdata_len = desc.usedlen;
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,desc.neededlen);
+
+ DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
+
+ return True;
}
/****************************************************************************
@@ -3009,24 +3236,31 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *user = skip_string(str2,1);
- char *resource = skip_string(user,1);
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *user = skip_string(str2,1);
+ char *resource = skip_string(user,1);
- DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
+ DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
- /* check it's a supported varient */
- if (strcmp(str1,"zzh") != 0) return False;
- if (strcmp(str2,"") != 0) return False;
+ /* check it's a supported varient */
+ if (strcmp(str1,"zzh") != 0) {
+ return False;
+ }
+ if (strcmp(str2,"") != 0) {
+ return False;
+ }
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,0); /* errorcode */
- SSVAL(*rparam,2,0); /* converter word */
- SSVAL(*rparam,4,0x7f); /* permission flags */
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,0); /* errorcode */
+ SSVAL(*rparam,2,0); /* converter word */
+ SSVAL(*rparam,4,0x7f); /* permission flags */
- return(True);
+ return True;
}
/****************************************************************************
@@ -3038,77 +3272,92 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- int count;
- int i;
- int snum;
- fstring sharename;
- uint32 jobid;
- struct pack_desc desc;
- print_queue_struct *queue=NULL;
- print_status_struct status;
- char *tmpdata=NULL;
-
- uLevel = SVAL(p,2);
-
- memset((char *)&desc,'\0',sizeof(desc));
- memset((char *)&status,'\0',sizeof(status));
-
- DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
-
- /* check it's a supported varient */
- if (strcmp(str1,"WWrLh") != 0) return False;
- if (!check_printjob_info(&desc,uLevel,str2)) return False;
-
- if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
- return False;
-
- snum = lp_servicenumber( sharename);
- if (snum < 0 || !VALID_SNUM(snum)) return(False);
-
- count = print_queue_status(snum,&queue,&status);
- for (i = 0; i < count; i++) {
- if (queue[i].job == jobid) break;
- }
-
- if (mdrcnt > 0) {
- *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- } else {
- /*
- * Don't return data but need to get correct length
- * init_package will return wrong size if buflen=0
- */
- desc.buflen = getlen(desc.format);
- desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
- }
-
- if (init_package(&desc,1,0)) {
- if (i < count) {
- fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
- *rdata_len = desc.usedlen;
- }
- else {
- desc.errcode = NERR_JobNotFound;
- *rdata_len = 0;
- }
- }
-
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,desc.neededlen);
-
- SAFE_FREE(queue);
- SAFE_FREE(tmpdata);
-
- DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
- return(True);
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ int count;
+ int i;
+ int snum;
+ fstring sharename;
+ uint32 jobid;
+ struct pack_desc desc;
+ print_queue_struct *queue=NULL;
+ print_status_struct status;
+ char *tmpdata=NULL;
+
+ uLevel = SVAL(p,2);
+
+ memset((char *)&desc,'\0',sizeof(desc));
+ memset((char *)&status,'\0',sizeof(status));
+
+ DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
+
+ /* check it's a supported varient */
+ if (strcmp(str1,"WWrLh") != 0) {
+ return False;
+ }
+ if (!check_printjob_info(&desc,uLevel,str2)) {
+ return False;
+ }
+
+ if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
+ return False;
+ }
+
+ snum = lp_servicenumber( sharename);
+ if (snum < 0 || !VALID_SNUM(snum)) {
+ return(False);
+ }
+
+ count = print_queue_status(snum,&queue,&status);
+ for (i = 0; i < count; i++) {
+ if (queue[i].job == jobid) {
+ break;
+ }
+ }
+
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ } else {
+ /*
+ * Don't return data but need to get correct length
+ * init_package will return wrong size if buflen=0
+ */
+ desc.buflen = getlen(desc.format);
+ desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
+ }
+
+ if (init_package(&desc,1,0)) {
+ if (i < count) {
+ fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
+ *rdata_len = desc.usedlen;
+ } else {
+ desc.errcode = NERR_JobNotFound;
+ *rdata_len = 0;
+ }
+ }
+
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,desc.neededlen);
+
+ SAFE_FREE(queue);
+ SAFE_FREE(tmpdata);
+
+ DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
+
+ return True;
}
static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3116,114 +3365,143 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- char* name = p;
- int uLevel;
- int count;
- int i, succnt=0;
- int snum;
- struct pack_desc desc;
- print_queue_struct *queue=NULL;
- print_status_struct status;
-
- memset((char *)&desc,'\0',sizeof(desc));
- memset((char *)&status,'\0',sizeof(status));
-
- p = skip_string(p,1);
- uLevel = SVAL(p,0);
-
- DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
-
- /* check it's a supported variant */
- if (strcmp(str1,"zWrLeh") != 0)
- return False;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ char* name = p;
+ int uLevel;
+ int count;
+ int i, succnt=0;
+ int snum;
+ struct pack_desc desc;
+ print_queue_struct *queue=NULL;
+ print_status_struct status;
+
+ memset((char *)&desc,'\0',sizeof(desc));
+ memset((char *)&status,'\0',sizeof(status));
+
+ p = skip_string(p,1);
+ uLevel = SVAL(p,0);
+
+ DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
+
+ /* check it's a supported variant */
+ if (strcmp(str1,"zWrLeh") != 0) {
+ return False;
+ }
- if (uLevel > 2)
- return False; /* defined only for uLevel 0,1,2 */
+ if (uLevel > 2) {
+ return False; /* defined only for uLevel 0,1,2 */
+ }
- if (!check_printjob_info(&desc,uLevel,str2))
- return False;
-
- snum = find_service(name);
- if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
- return False;
-
- count = print_queue_status(snum,&queue,&status);
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
-
- if (init_package(&desc,count,0)) {
- succnt = 0;
- for (i = 0; i < count; i++) {
- fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
- if (desc.errcode == NERR_Success) succnt = i+1;
- }
- }
-
- *rdata_len = desc.usedlen;
-
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,succnt);
- SSVAL(*rparam,6,count);
-
- SAFE_FREE(queue);
-
- DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
- return(True);
+ if (!check_printjob_info(&desc,uLevel,str2)) {
+ return False;
+ }
+
+ snum = find_service(name);
+ if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
+ return False;
+ }
+
+ count = print_queue_status(snum,&queue,&status);
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+
+ if (init_package(&desc,count,0)) {
+ succnt = 0;
+ for (i = 0; i < count; i++) {
+ fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
+ if (desc.errcode == NERR_Success) {
+ succnt = i+1;
+ }
+ }
+ }
+
+ *rdata_len = desc.usedlen;
+
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,succnt);
+ SSVAL(*rparam,6,count);
+
+ SAFE_FREE(queue);
+
+ DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
+
+ return True;
}
static int check_printdest_info(struct pack_desc* desc,
int uLevel, char* id)
{
- desc->subformat = NULL;
- switch( uLevel ) {
- case 0: desc->format = "B9"; break;
- case 1: desc->format = "B9B21WWzW"; break;
- case 2: desc->format = "z"; break;
- case 3: desc->format = "zzzWWzzzWW"; break;
- default: return False;
- }
- if (strcmp(desc->format,id) != 0) return False;
- return True;
+ desc->subformat = NULL;
+ switch( uLevel ) {
+ case 0:
+ desc->format = "B9";
+ break;
+ case 1:
+ desc->format = "B9B21WWzW";
+ break;
+ case 2:
+ desc->format = "z";
+ break;
+ case 3:
+ desc->format = "zzzWWzzzWW";
+ break;
+ default:
+ return False;
+ }
+ if (strcmp(desc->format,id) != 0) {
+ return False;
+ }
+ return True;
}
static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
struct pack_desc* desc)
{
- char buf[100];
- strncpy(buf,SERVICE(snum),sizeof(buf)-1);
- buf[sizeof(buf)-1] = 0;
- strupper_m(buf);
- if (uLevel <= 1) {
- PACKS(desc,"B9",buf); /* szName */
- if (uLevel == 1) {
- PACKS(desc,"B21",""); /* szUserName */
- PACKI(desc,"W",0); /* uJobId */
- PACKI(desc,"W",0); /* fsStatus */
- PACKS(desc,"z",""); /* pszStatus */
- PACKI(desc,"W",0); /* time */
- }
- }
- if (uLevel == 2 || uLevel == 3) {
- PACKS(desc,"z",buf); /* pszPrinterName */
- if (uLevel == 3) {
- PACKS(desc,"z",""); /* pszUserName */
- PACKS(desc,"z",""); /* pszLogAddr */
- PACKI(desc,"W",0); /* uJobId */
- PACKI(desc,"W",0); /* fsStatus */
- PACKS(desc,"z",""); /* pszStatus */
- PACKS(desc,"z",""); /* pszComment */
- PACKS(desc,"z","NULL"); /* pszDrivers */
- PACKI(desc,"W",0); /* time */
- PACKI(desc,"W",0); /* pad1 */
- }
- }
+ char buf[100];
+
+ strncpy(buf,SERVICE(snum),sizeof(buf)-1);
+ buf[sizeof(buf)-1] = 0;
+ strupper_m(buf);
+
+ if (uLevel <= 1) {
+ PACKS(desc,"B9",buf); /* szName */
+ if (uLevel == 1) {
+ PACKS(desc,"B21",""); /* szUserName */
+ PACKI(desc,"W",0); /* uJobId */
+ PACKI(desc,"W",0); /* fsStatus */
+ PACKS(desc,"z",""); /* pszStatus */
+ PACKI(desc,"W",0); /* time */
+ }
+ }
+
+ if (uLevel == 2 || uLevel == 3) {
+ PACKS(desc,"z",buf); /* pszPrinterName */
+ if (uLevel == 3) {
+ PACKS(desc,"z",""); /* pszUserName */
+ PACKS(desc,"z",""); /* pszLogAddr */
+ PACKI(desc,"W",0); /* uJobId */
+ PACKI(desc,"W",0); /* fsStatus */
+ PACKS(desc,"z",""); /* pszStatus */
+ PACKS(desc,"z",""); /* pszComment */
+ PACKS(desc,"z","NULL"); /* pszDrivers */
+ PACKI(desc,"W",0); /* time */
+ PACKI(desc,"W",0); /* pad1 */
+ }
+ }
}
static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3231,60 +3509,70 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- char* PrinterName = p;
- int uLevel;
- struct pack_desc desc;
- int snum;
- char *tmpdata=NULL;
-
- memset((char *)&desc,'\0',sizeof(desc));
-
- p = skip_string(p,1);
- uLevel = SVAL(p,0);
-
- DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
-
- /* check it's a supported varient */
- if (strcmp(str1,"zWrLh") != 0) return False;
- if (!check_printdest_info(&desc,uLevel,str2)) return False;
-
- snum = find_service(PrinterName);
- if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
- *rdata_len = 0;
- desc.errcode = NERR_DestNotFound;
- desc.neededlen = 0;
- }
- else {
- if (mdrcnt > 0) {
- *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- } else {
- /*
- * Don't return data but need to get correct length
- * init_package will return wrong size if buflen=0
- */
- desc.buflen = getlen(desc.format);
- desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
- }
- if (init_package(&desc,1,0)) {
- fill_printdest_info(conn,snum,uLevel,&desc);
- }
- *rdata_len = desc.usedlen;
- }
-
- *rparam_len = 6;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,desc.neededlen);
-
- DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
- SAFE_FREE(tmpdata);
- return(True);
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ char* PrinterName = p;
+ int uLevel;
+ struct pack_desc desc;
+ int snum;
+ char *tmpdata=NULL;
+
+ memset((char *)&desc,'\0',sizeof(desc));
+
+ p = skip_string(p,1);
+ uLevel = SVAL(p,0);
+
+ DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
+
+ /* check it's a supported varient */
+ if (strcmp(str1,"zWrLh") != 0) {
+ return False;
+ }
+ if (!check_printdest_info(&desc,uLevel,str2)) {
+ return False;
+ }
+
+ snum = find_service(PrinterName);
+ if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
+ *rdata_len = 0;
+ desc.errcode = NERR_DestNotFound;
+ desc.neededlen = 0;
+ } else {
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ } else {
+ /*
+ * Don't return data but need to get correct length
+ * init_package will return wrong size if buflen=0
+ */
+ desc.buflen = getlen(desc.format);
+ desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
+ }
+ if (init_package(&desc,1,0)) {
+ fill_printdest_info(conn,snum,uLevel,&desc);
+ }
+ *rdata_len = desc.usedlen;
+ }
+
+ *rparam_len = 6;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,desc.neededlen);
+
+ DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
+ SAFE_FREE(tmpdata);
+
+ return True;
}
static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3292,56 +3580,74 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- int queuecnt;
- int i, n, succnt=0;
- struct pack_desc desc;
- int services = lp_numservices();
-
- memset((char *)&desc,'\0',sizeof(desc));
-
- uLevel = SVAL(p,0);
-
- DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
-
- /* check it's a supported varient */
- if (strcmp(str1,"WrLeh") != 0) return False;
- if (!check_printdest_info(&desc,uLevel,str2)) return False;
-
- queuecnt = 0;
- for (i = 0; i < services; i++)
- if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
- queuecnt++;
-
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- if (init_package(&desc,queuecnt,0)) {
- succnt = 0;
- n = 0;
- for (i = 0; i < services; i++) {
- if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
- fill_printdest_info(conn,i,uLevel,&desc);
- n++;
- if (desc.errcode == NERR_Success) succnt = n;
- }
- }
- }
-
- *rdata_len = desc.usedlen;
-
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,succnt);
- SSVAL(*rparam,6,queuecnt);
-
- DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
- return(True);
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ int queuecnt;
+ int i, n, succnt=0;
+ struct pack_desc desc;
+ int services = lp_numservices();
+
+ memset((char *)&desc,'\0',sizeof(desc));
+
+ uLevel = SVAL(p,0);
+
+ DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
+
+ /* check it's a supported varient */
+ if (strcmp(str1,"WrLeh") != 0) {
+ return False;
+ }
+ if (!check_printdest_info(&desc,uLevel,str2)) {
+ return False;
+ }
+
+ queuecnt = 0;
+ for (i = 0; i < services; i++) {
+ if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
+ queuecnt++;
+ }
+ }
+
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ if (init_package(&desc,queuecnt,0)) {
+ succnt = 0;
+ n = 0;
+ for (i = 0; i < services; i++) {
+ if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
+ fill_printdest_info(conn,i,uLevel,&desc);
+ n++;
+ if (desc.errcode == NERR_Success) {
+ succnt = n;
+ }
+ }
+ }
+ }
+
+ *rdata_len = desc.usedlen;
+
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,succnt);
+ SSVAL(*rparam,6,queuecnt);
+
+ DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
+
+ return True;
}
static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3349,43 +3655,56 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- int succnt;
- struct pack_desc desc;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ int succnt;
+ struct pack_desc desc;
- memset((char *)&desc,'\0',sizeof(desc));
+ memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = SVAL(p,0);
- DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
+ DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
- /* check it's a supported varient */
- if (strcmp(str1,"WrLeh") != 0) return False;
- if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
+ /* check it's a supported varient */
+ if (strcmp(str1,"WrLeh") != 0) {
+ return False;
+ }
+ if (uLevel != 0 || strcmp(str2,"B41") != 0) {
+ return False;
+ }
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- if (init_package(&desc,1,0)) {
- PACKS(&desc,"B41","NULL");
- }
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ if (init_package(&desc,1,0)) {
+ PACKS(&desc,"B41","NULL");
+ }
- succnt = (desc.errcode == NERR_Success ? 1 : 0);
+ succnt = (desc.errcode == NERR_Success ? 1 : 0);
- *rdata_len = desc.usedlen;
+ *rdata_len = desc.usedlen;
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,succnt);
- SSVAL(*rparam,6,1);
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,succnt);
+ SSVAL(*rparam,6,1);
- DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
- return(True);
+ DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
+
+ return True;
}
static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3393,44 +3712,57 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- int succnt;
- struct pack_desc desc;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ int succnt;
+ struct pack_desc desc;
- memset((char *)&desc,'\0',sizeof(desc));
+ memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = SVAL(p,0);
- DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
+ DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
- /* check it's a supported varient */
- if (strcmp(str1,"WrLeh") != 0) return False;
- if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
+ /* check it's a supported varient */
+ if (strcmp(str1,"WrLeh") != 0) {
+ return False;
+ }
+ if (uLevel != 0 || strcmp(str2,"B13") != 0) {
+ return False;
+ }
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- desc.format = str2;
- if (init_package(&desc,1,0)) {
- PACKS(&desc,"B13","lpd");
- }
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ desc.format = str2;
+ if (init_package(&desc,1,0)) {
+ PACKS(&desc,"B13","lpd");
+ }
- succnt = (desc.errcode == NERR_Success ? 1 : 0);
+ succnt = (desc.errcode == NERR_Success ? 1 : 0);
+
+ *rdata_len = desc.usedlen;
- *rdata_len = desc.usedlen;
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,succnt);
+ SSVAL(*rparam,6,1);
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,succnt);
- SSVAL(*rparam,6,1);
+ DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
- DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
- return(True);
+ return True;
}
static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3438,45 +3770,58 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- int succnt;
- struct pack_desc desc;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ int succnt;
+ struct pack_desc desc;
- memset((char *)&desc,'\0',sizeof(desc));
+ memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = SVAL(p,0);
- DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
+ DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
- /* check it's a supported varient */
- if (strcmp(str1,"WrLeh") != 0) return False;
- if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
+ /* check it's a supported varient */
+ if (strcmp(str1,"WrLeh") != 0) {
+ return False;
+ }
+ if (uLevel != 0 || strcmp(str2,"B9") != 0) {
+ return False;
+ }
+
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+ memset((char *)&desc,'\0',sizeof(desc));
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ desc.format = str2;
+ if (init_package(&desc,1,0)) {
+ PACKS(&desc,"B13","lp0");
+ }
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- memset((char *)&desc,'\0',sizeof(desc));
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- desc.format = str2;
- if (init_package(&desc,1,0)) {
- PACKS(&desc,"B13","lp0");
- }
+ succnt = (desc.errcode == NERR_Success ? 1 : 0);
- succnt = (desc.errcode == NERR_Success ? 1 : 0);
+ *rdata_len = desc.usedlen;
- *rdata_len = desc.usedlen;
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0);
+ SSVAL(*rparam,4,succnt);
+ SSVAL(*rparam,6,1);
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0);
- SSVAL(*rparam,4,succnt);
- SSVAL(*rparam,6,1);
+ DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
- DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
- return(True);
+ return True;
}
@@ -3489,59 +3834,72 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel;
- struct pack_desc desc;
- struct sessionid *session_list;
- int i, num_sessions;
-
- memset((char *)&desc,'\0',sizeof(desc));
-
- uLevel = SVAL(p,0);
-
- DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
- DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
- DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
-
- /* check it's a supported varient */
- if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
- if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
-
- num_sessions = list_sessions(&session_list);
-
- if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
- memset((char *)&desc,'\0',sizeof(desc));
- desc.base = *rdata;
- desc.buflen = mdrcnt;
- desc.format = str2;
- if (!init_package(&desc,num_sessions,0)) {
- return False;
- }
-
- for(i=0; i<num_sessions; i++) {
- PACKS(&desc, "z", session_list[i].remote_machine);
- PACKS(&desc, "z", session_list[i].username);
- PACKI(&desc, "W", 1); /* num conns */
- PACKI(&desc, "W", 0); /* num opens */
- PACKI(&desc, "W", 1); /* num users */
- PACKI(&desc, "D", 0); /* session time */
- PACKI(&desc, "D", 0); /* idle time */
- PACKI(&desc, "D", 0); /* flags */
- PACKS(&desc, "z", "Unknown Client"); /* client type string */
- }
-
- *rdata_len = desc.usedlen;
-
- *rparam_len = 8;
- *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
- SSVALS(*rparam,0,desc.errcode);
- SSVAL(*rparam,2,0); /* converter */
- SSVAL(*rparam,4,num_sessions); /* count */
-
- DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
- return True;
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+ int uLevel;
+ struct pack_desc desc;
+ struct sessionid *session_list;
+ int i, num_sessions;
+
+ memset((char *)&desc,'\0',sizeof(desc));
+
+ uLevel = SVAL(p,0);
+
+ DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
+ DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
+ DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
+
+ /* check it's a supported varient */
+ if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
+ return False;
+ }
+ if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
+ return False;
+ }
+
+ num_sessions = list_sessions(&session_list);
+
+ if (mdrcnt > 0) {
+ *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+ if (!*rdata) {
+ return False;
+ }
+ }
+ memset((char *)&desc,'\0',sizeof(desc));
+ desc.base = *rdata;
+ desc.buflen = mdrcnt;
+ desc.format = str2;
+ if (!init_package(&desc,num_sessions,0)) {
+ return False;
+ }
+
+ for(i=0; i<num_sessions; i++) {
+ PACKS(&desc, "z", session_list[i].remote_machine);
+ PACKS(&desc, "z", session_list[i].username);
+ PACKI(&desc, "W", 1); /* num conns */
+ PACKI(&desc, "W", 0); /* num opens */
+ PACKI(&desc, "W", 1); /* num users */
+ PACKI(&desc, "D", 0); /* session time */
+ PACKI(&desc, "D", 0); /* idle time */
+ PACKI(&desc, "D", 0); /* flags */
+ PACKS(&desc, "z", "Unknown Client"); /* client type string */
+ }
+
+ *rdata_len = desc.usedlen;
+
+ *rparam_len = 8;
+ *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
+ SSVALS(*rparam,0,desc.errcode);
+ SSVAL(*rparam,2,0); /* converter */
+ SSVAL(*rparam,4,num_sessions); /* count */
+
+ DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
+
+ return True;
}
@@ -3556,6 +3914,9 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char
{
*rparam_len = MIN(*rparam_len,mprcnt);
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
*rdata_len = 0;
@@ -3577,6 +3938,9 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, c
{
*rparam_len = 4;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+ if (!*rparam) {
+ return False;
+ }
*rdata_len = 0;
@@ -3709,11 +4073,14 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
/* if we get False back then it's actually unsupported */
if (!reply) {
- api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
+ reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
}
- send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
+ /* If api_Unsupported returns false we can't return anything. */
+ if (reply) {
+ send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
+ }
SAFE_FREE(rdata);
SAFE_FREE(rparam);
diff --git a/source/smbd/map_username.c b/source/smbd/map_username.c
new file mode 100644
index 00000000000..1f523cc89f1
--- /dev/null
+++ b/source/smbd/map_username.c
@@ -0,0 +1,180 @@
+/*
+ Unix SMB/CIFS implementation.
+ Username handling
+ Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 1997-2001.
+ 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"
+
+/*******************************************************************
+ Map a username from a dos name to a unix name by looking in the username
+ map. Note that this modifies the name in place.
+ This is the main function that should be called *once* on
+ any incoming or new username - in order to canonicalize the name.
+ This is being done to de-couple the case conversions from the user mapping
+ function. Previously, the map_username was being called
+ every time Get_Pwnam was called.
+ Returns True if username was changed, false otherwise.
+********************************************************************/
+
+BOOL map_username(fstring user)
+{
+ static BOOL initialised=False;
+ static fstring last_from,last_to;
+ XFILE *f;
+ char *mapfile = lp_username_map();
+ char *s;
+ pstring buf;
+ BOOL mapped_user = False;
+ char *cmd = lp_username_map_script();
+
+ if (!*user)
+ return False;
+
+ if (strequal(user,last_to))
+ return False;
+
+ if (strequal(user,last_from)) {
+ DEBUG(3,("Mapped user %s to %s\n",user,last_to));
+ fstrcpy(user,last_to);
+ return True;
+ }
+
+ /* first try the username map script */
+
+ if ( *cmd ) {
+ char **qlines;
+ pstring command;
+ int numlines, ret, fd;
+
+ pstr_sprintf( command, "%s \"%s\"", cmd, user );
+
+ DEBUG(10,("Running [%s]\n", command));
+ ret = smbrun(command, &fd);
+ DEBUGADD(10,("returned [%d]\n", ret));
+
+ if ( ret != 0 ) {
+ if (fd != -1)
+ close(fd);
+ return False;
+ }
+
+ numlines = 0;
+ qlines = fd_lines_load(fd, &numlines,0);
+ DEBUGADD(10,("Lines returned = [%d]\n", numlines));
+ close(fd);
+
+ /* should be either no lines or a single line with the mapped username */
+
+ if (numlines) {
+ DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] ));
+ fstrcpy( user, qlines[0] );
+ }
+
+ file_lines_free(qlines);
+
+ return numlines != 0;
+ }
+
+ /* ok. let's try the mapfile */
+
+ if (!*mapfile)
+ return False;
+
+ if (!initialised) {
+ *last_from = *last_to = 0;
+ initialised = True;
+ }
+
+ f = x_fopen(mapfile,O_RDONLY, 0);
+ if (!f) {
+ DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) ));
+ return False;
+ }
+
+ DEBUG(4,("Scanning username map %s\n",mapfile));
+
+ while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
+ char *unixname = s;
+ char *dosname = strchr_m(unixname,'=');
+ char **dosuserlist;
+ BOOL return_if_mapped = False;
+
+ if (!dosname)
+ continue;
+
+ *dosname++ = 0;
+
+ while (isspace((int)*unixname))
+ unixname++;
+
+ if ('!' == *unixname) {
+ return_if_mapped = True;
+ unixname++;
+ while (*unixname && isspace((int)*unixname))
+ unixname++;
+ }
+
+ if (!*unixname || strchr_m("#;",*unixname))
+ continue;
+
+ {
+ int l = strlen(unixname);
+ while (l && isspace((int)unixname[l-1])) {
+ unixname[l-1] = 0;
+ l--;
+ }
+ }
+
+ /* skip lines like 'user = ' */
+
+ dosuserlist = str_list_make(dosname, NULL);
+ if (!dosuserlist) {
+ DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n"));
+ continue;
+ }
+
+ if (strchr_m(dosname,'*') ||
+ user_in_list(user, (const char **)dosuserlist)) {
+ DEBUG(3,("Mapped user %s to %s\n",user,unixname));
+ mapped_user = True;
+ fstrcpy( last_from,user );
+ fstrcpy( user, unixname );
+ fstrcpy( last_to,user );
+ if ( return_if_mapped ) {
+ str_list_free (&dosuserlist);
+ x_fclose(f);
+ return True;
+ }
+ }
+
+ str_list_free (&dosuserlist);
+ }
+
+ x_fclose(f);
+
+ /*
+ * Setup the last_from and last_to as an optimization so
+ * that we don't scan the file again for the same user.
+ */
+ fstrcpy(last_from,user);
+ fstrcpy(last_to,user);
+
+ return mapped_user;
+}
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index a4f371b18ff..4606441c3a9 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -146,7 +146,7 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
return False;
}
- string_set(&conn->connectpath, connpath);
+ set_conn_connectpath(conn, connpath);
if (!smbd_vfs_init(conn)) {
DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n"));
@@ -609,7 +609,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
DEBUG(10,("setting up version2 referral\nRequested path:\n"));
- requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1,
+ requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring),
STR_TERMINATE);
if (DEBUGLVL(10)) {
@@ -643,9 +643,8 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
if(pdata == NULL) {
DEBUG(0,("malloc failed for Realloc!\n"));
return -1;
- } else {
- *ppdata = pdata;
}
+ *ppdata = pdata;
/* copy in the dfs requested paths.. required for offset calculations */
memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen);
@@ -681,7 +680,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
SSVAL(pdata,offset+18,uni_reqpathoffset2-offset);
/* copy referred path into current offset */
unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path,
- -1, STR_UNICODE);
+ sizeof(pstring), STR_UNICODE);
SSVAL(pdata,offset+20,uni_curroffset-offset);
@@ -710,7 +709,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
DEBUG(10,("setting up version3 referral\n"));
- reqpathlen = rpcstr_push(uni_reqpath, pathname, -1, STR_TERMINATE);
+ reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE);
if (DEBUGLVL(10)) {
dump_data(0, (char *) uni_reqpath,reqpathlen);
@@ -729,9 +728,8 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
if(pdata == NULL) {
DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n"));
return -1;
- } else {
- *ppdata = pdata;
}
+ *ppdata = pdata;
/* create the header */
SSVAL(pdata,0,consumedcnt * 2); /* path consumed */
@@ -766,7 +764,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
SSVAL(pdata,offset+14,uni_reqpathoffset2-offset);
/* copy referred path into current offset */
unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path,
- -1, STR_UNICODE | STR_TERMINATE);
+ sizeof(pstring), STR_UNICODE | STR_TERMINATE);
SSVAL(pdata,offset+16,uni_curroffset-offset);
/* copy 0x10 bytes of 00's in the ServiceSite GUID */
memset(pdata+offset+18,'\0',16);
@@ -1094,13 +1092,19 @@ out:
int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)
{
int i=0;
+ int sharecount = 0;
int jn_count = 0;
if(!lp_host_msdfs()) {
return 0;
}
- for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) {
+ /* Ensure all the usershares are loaded. */
+ become_root();
+ sharecount = load_usershare_shares();
+ unbecome_root();
+
+ for(i=0;i < sharecount && (jn_max - jn_count) > 0;i++) {
if(lp_msdfs_root(i)) {
jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count);
}
diff --git a/source/smbd/notify.c b/source/smbd/notify.c
index bc76cfb322f..b2d0fc33262 100644
--- a/source/smbd/notify.c
+++ b/source/smbd/notify.c
@@ -206,16 +206,31 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn,
return True;
}
+int change_notify_fd(void)
+{
+ if (cnotify) {
+ return cnotify->notification_fd;
+ }
+
+ return -1;
+}
+
/****************************************************************************
Initialise the change notify subsystem.
****************************************************************************/
BOOL init_change_notify(void)
{
+ cnotify = NULL;
+
#if HAVE_KERNEL_CHANGE_NOTIFY
- if (lp_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) {
diff --git a/source/smbd/notify_fam.c b/source/smbd/notify_fam.c
new file mode 100644
index 00000000000..3b6be77acab
--- /dev/null
+++ b/source/smbd/notify_fam.c
@@ -0,0 +1,463 @@
+/*
+ * 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 %d bytes failed\n", 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
index ee7d4314eef..a98a028fae0 100644
--- a/source/smbd/notify_hash.c
+++ b/source/smbd/notify_hash.c
@@ -23,13 +23,8 @@
struct change_data {
time_t last_check_time; /* time we last checked this entry */
-#ifdef HAVE_STAT_HIRES_TIMESTAMPS
- struct timespec modify_time;
- struct timespec status_time;
-#else
- time_t modify_time; /* Info from the directory we're monitoring. */
- time_t status_time; /* Info from the directory we're monitoring. */
-#endif
+ 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;
@@ -37,13 +32,8 @@ struct change_data {
};
-#ifdef HAVE_STAT_HIRES_TIMESTAMPS
/* Compare struct timespec. */
#define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec))
-#else
-/* Compare time_t . */
-#define TIMESTAMP_NEQ(x, y) ((x) != (y))
-#endif
/****************************************************************************
Create the hash we will use to determine if the contents changed.
@@ -66,13 +56,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
if(SMB_VFS_STAT(conn,path, &st) == -1)
return False;
-#ifdef HAVE_STAT_HIRES_TIMESTAMPS
- data->modify_time = st.st_mtim;
- data->status_time = st.st_ctim;
-#else
- data->modify_time = st.st_mtime;
- data->status_time = st.st_ctime;
-#endif
+ data->modify_time = get_mtimespec(&st);
+ data->status_time = get_ctimespec(&st);
if (old_data) {
/*
@@ -245,6 +230,7 @@ struct cnotify_fns *hash_notify_init(void)
cnotify.check_notify = hash_check_notify;
cnotify.remove_notify = hash_remove_notify;
cnotify.select_time = lp_change_notify_timeout();
+ cnotify.notification_fd = -1;
return &cnotify;
}
diff --git a/source/smbd/notify_kernel.c b/source/smbd/notify_kernel.c
index 02abe0b4b60..0c20effc3d1 100644
--- a/source/smbd/notify_kernel.c
+++ b/source/smbd/notify_kernel.c
@@ -232,6 +232,7 @@ struct cnotify_fns *kernel_notify_init(void)
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);
diff --git a/source/smbd/ntquotas.c b/source/smbd/ntquotas.c
index 9bc444d2536..a824978ecea 100644
--- a/source/smbd/ntquotas.c
+++ b/source/smbd/ntquotas.c
@@ -87,7 +87,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
id.uid = -1;
- if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) {
+ if (psid && !sid_to_uid(psid, &id.uid)) {
DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
sid_string_static(psid)));
}
@@ -131,7 +131,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
D.isoftlimit = limit_blk2inodes(D.softlimit);
D.ihardlimit = limit_blk2inodes(D.hardlimit);
- if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) {
+ if (psid && !sid_to_uid(psid, &id.uid)) {
DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
sid_string_static(psid)));
}
@@ -185,10 +185,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
continue;
}
- if (!NT_STATUS_IS_OK(uid_to_sid(&sid, usr->pw_uid))) {
- DEBUG(0,("uid_to_sid failed for %ld\n",(long)usr->pw_uid));
- continue;
- }
+ uid_to_sid(&sid, usr->pw_uid);
if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) {
DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 72288e2c244..839eb7bb279 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -48,21 +48,16 @@ static const char *known_nt_pipes[] = {
static char *nttrans_realloc(char **ptr, size_t size)
{
- char *tptr = NULL;
if (ptr==NULL) {
smb_panic("nttrans_realloc() called with NULL ptr\n");
}
- tptr = SMB_REALLOC(*ptr, size);
- if(tptr == NULL) {
- *ptr = NULL;
+ *ptr = SMB_REALLOC(*ptr, size);
+ if(*ptr == NULL) {
return NULL;
}
- memset(tptr,'\0',size);
-
- *ptr = tptr;
-
- return tptr;
+ memset(*ptr,'\0',size);
+ return *ptr;
}
/****************************************************************************
@@ -798,7 +793,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
fattr = FILE_ATTRIBUTE_NORMAL;
}
if (!fsp->is_directory && (fattr & aDIR)) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBntcreateX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
@@ -812,13 +807,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (fsp->is_directory) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBntcreateX);
/* Can't set allocation size on a directory. */
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
@@ -1416,7 +1411,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(ctx);
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
@@ -1427,7 +1422,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
status = set_ea(conn, fsp, fname, ea_list);
talloc_destroy(ctx);
if (!NT_STATUS_IS_OK(status)) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
@@ -1441,7 +1436,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
fattr = FILE_ATTRIBUTE_NORMAL;
}
if (!fsp->is_directory && (fattr & aDIR)) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
@@ -1454,12 +1449,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if (allocation_size && (allocation_size > file_len)) {
fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (fsp->is_directory) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
/* Can't set allocation size on a directory. */
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
@@ -1688,7 +1683,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
status = NT_STATUS_ACCESS_DENIED;
}
set_saved_ntstatus(NT_STATUS_OK);
- close_file(fsp1,False);
+ close_file(fsp1,ERROR_CLOSE);
return status;
}
@@ -1702,12 +1697,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
* Thus we don't look at the error return from the
* close of fsp1.
*/
- close_file(fsp1,False);
+ close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
- close_ret = close_file(fsp2,False);
+ close_ret = close_file(fsp2,NORMAL_CLOSE);
/* Grrr. We have to do this as open_file_shared1 adds aARCH when it
creates the file. This isn't the correct thing to do in the copy case. JRA */
@@ -1810,26 +1805,13 @@ int reply_ntrename(connection_struct *conn,
* update after a rename..
*/
process_pending_change_notify_queue((time_t)0);
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBntrename);
return(outsize);
}
/****************************************************************************
- Reply to an unsolicited SMBNTtranss - just ignore it!
-****************************************************************************/
-
-int reply_nttranss(connection_struct *conn,
- char *inbuf,char *outbuf,int length,int bufsize)
-{
- START_PROFILE(SMBnttranss);
- DEBUG(4,("Ignoring nttranss of length %d\n",length));
- END_PROFILE(SMBnttranss);
- return(-1);
-}
-
-/****************************************************************************
Reply to a notify change - queue the request and
don't allow a directory to be opened.
****************************************************************************/
@@ -2309,7 +2291,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
sid_parse(pdata+4,sid_len,&sid);
DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid)));
- if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) {
+ if (!sid_to_uid(&sid, &uid)) {
DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
sid_string_static(&sid),(unsigned long)sid_len));
uid = (-1);
@@ -2379,7 +2361,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
ZERO_STRUCT(qt);
/* access check */
- if (current_user.uid != 0) {
+ if (current_user.ut.uid != 0) {
DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -2626,7 +2608,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
ZERO_STRUCT(qt);
/* access check */
- if (current_user.uid != 0) {
+ if (current_user.ut.uid != 0) {
DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -2724,29 +2706,120 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
}
#endif /* HAVE_SYS_QUOTAS */
+static int handle_nttrans(connection_struct *conn,
+ struct trans_state *state,
+ char *inbuf, char *outbuf, int size, int bufsize)
+{
+ int outsize;
+
+ if (Protocol >= PROTOCOL_NT1) {
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
+ }
+
+ /* Now we must call the relevant NT_TRANS function */
+ switch(state->call) {
+ case NT_TRANSACT_CREATE:
+ START_PROFILE_NESTED(NT_transact_create);
+ outsize = call_nt_transact_create(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+ case NT_TRANSACT_IOCTL:
+ START_PROFILE_NESTED(NT_transact_ioctl);
+ outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+ case NT_TRANSACT_SET_SECURITY_DESC:
+ START_PROFILE_NESTED(NT_transact_set_security_desc);
+ outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+ case NT_TRANSACT_NOTIFY_CHANGE:
+ START_PROFILE_NESTED(NT_transact_notify_change);
+ outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+ case NT_TRANSACT_RENAME:
+ START_PROFILE_NESTED(NT_transact_rename);
+ outsize = call_nt_transact_rename(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+
+ case NT_TRANSACT_QUERY_SECURITY_DESC:
+ START_PROFILE_NESTED(NT_transact_query_security_desc);
+ outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+#ifdef HAVE_SYS_QUOTAS
+ case NT_TRANSACT_GET_USER_QUOTA:
+ START_PROFILE_NESTED(NT_transact_get_user_quota);
+ outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+ case NT_TRANSACT_SET_USER_QUOTA:
+ START_PROFILE_NESTED(NT_transact_set_user_quota);
+ outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&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);
+ break;
+#endif /* HAVE_SYS_QUOTAS */
+ default:
+ /* Error in request */
+ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n",
+ state->call));
+ return ERROR_DOS(ERRSRV,ERRerror);
+ }
+ return outsize;
+}
+
/****************************************************************************
Reply to a SMBNTtrans.
****************************************************************************/
int reply_nttrans(connection_struct *conn,
- char *inbuf,char *outbuf,int length,int bufsize)
+ char *inbuf,char *outbuf,int size,int bufsize)
{
int outsize = 0;
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
-#if 0 /* Not used. */
- uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
- uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
-#endif /* Not used. */
- uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
- uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
- uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount);
- uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
- uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
- uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
- uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */
+ uint32 pscnt = IVAL(inbuf,smb_nt_ParameterCount);
+ uint32 psoff = IVAL(inbuf,smb_nt_ParameterOffset);
+ uint32 dscnt = IVAL(inbuf,smb_nt_DataCount);
+ uint32 dsoff = IVAL(inbuf,smb_nt_DataOffset);
+
uint16 function_code = SVAL( inbuf, smb_nt_Function);
- char *params = NULL, *data = NULL, *setup = NULL;
- uint32 num_params_sofar, num_data_sofar;
+ NTSTATUS result;
+ struct trans_state *state;
+
START_PROFILE(SMBnttrans);
if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
@@ -2754,319 +2827,269 @@ int reply_nttrans(connection_struct *conn,
return ERROR_DOS(ERRSRV,ERRaccess);
}
- outsize = set_message(outbuf,0,0,True);
+ if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
+ SVAL(inbuf, smb_mid)))) {
+ DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
+ END_PROFILE(SMBnttrans);
+ return ERROR_NT(result);
+ }
+
+ if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRSRV,ERRaccess);
+ }
+
+ state->cmd = SMBnttrans;
+
+ state->mid = SVAL(inbuf,smb_mid);
+ state->vuid = SVAL(inbuf,smb_uid);
+ state->total_data = IVAL(inbuf, smb_nt_TotalDataCount);
+ state->data = NULL;
+ state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount);
+ state->param = NULL;
+ state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount);
+
+ /* setup count is in *words* */
+ state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount);
+ state->call = function_code;
/*
- * All nttrans messages we handle have smb_wct == 19 + setup_count.
- * Ensure this is so as a sanity check.
+ * All nttrans messages we handle have smb_wct == 19 +
+ * state->setup_count. Ensure this is so as a sanity check.
*/
- if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) {
+ if(CVAL(inbuf, smb_wct) != 19 + (state->setup_count/2)) {
DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
- CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
+ CVAL(inbuf, smb_wct), 19 + (state->setup_count/2)));
goto bad_param;
}
/* Don't allow more than 128mb for each value. */
- if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) {
+ if ((state->total_data > (1024*1024*128)) ||
+ (state->total_param > (1024*1024*128))) {
END_PROFILE(SMBnttrans);
return ERROR_DOS(ERRDOS,ERRnomem);
}
- /* Allocate the space for the setup, the maximum needed parameters and data */
-
- if(setup_count > 0) {
- setup = (char *)SMB_MALLOC(setup_count);
- }
- if (total_parameter_count > 0) {
- params = (char *)SMB_MALLOC(total_parameter_count);
- }
- if (total_data_count > 0) {
- data = (char *)SMB_MALLOC(total_data_count);
- }
-
- if ((total_parameter_count && !params) || (total_data_count && !data) ||
- (setup_count && !setup)) {
- SAFE_FREE(setup);
- SAFE_FREE(params);
- SAFE_FREE(data);
- DEBUG(0,("reply_nttrans : Out of memory\n"));
- END_PROFILE(SMBnttrans);
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
-
- /* Copy the param and data bytes sent with this request into the params buffer */
- num_params_sofar = parameter_count;
- num_data_sofar = data_count;
-
- if (parameter_count > total_parameter_count || data_count > total_data_count)
+ if ((dscnt > state->total_data) || (pscnt > state->total_param))
goto bad_param;
- if(setup) {
- DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
- if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
- (smb_nt_SetupStart + setup_count < setup_count)) {
+ 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) {
+ DEBUG(0,("reply_nttrans: data malloc fail for %u "
+ "bytes !\n", state->total_data));
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ }
+ if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
goto bad_param;
- }
- if (smb_nt_SetupStart + setup_count > length) {
+ if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
+ (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
goto bad_param;
- }
- memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
- dump_data(10, setup, setup_count);
+ memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
}
- if(params) {
- DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
- if ((parameter_offset + parameter_count < parameter_offset) ||
- (parameter_offset + parameter_count < parameter_count)) {
+
+ 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) {
+ DEBUG(0,("reply_nttrans: param malloc fail for %u "
+ "bytes !\n", state->total_param));
+ SAFE_FREE(state->data);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ }
+ if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
goto bad_param;
- }
- if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)||
- (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
+ if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
+ (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
goto bad_param;
- }
- memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
- dump_data(10, params, parameter_count);
+ memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
}
- if(data) {
- DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
- if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) {
+
+ state->received_data = dscnt;
+ state->received_param = pscnt;
+
+ if(state->setup_count > 0) {
+ DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
+ state->setup_count));
+ state->setup = TALLOC(state, state->setup_count);
+ if (state->setup == NULL) {
+ DEBUG(0,("reply_nttrans : Out of memory\n"));
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
+
+ if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) ||
+ (smb_nt_SetupStart + state->setup_count < state->setup_count)) {
goto bad_param;
}
- if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
- (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
+ if (smb_nt_SetupStart + state->setup_count > size) {
goto bad_param;
}
- memcpy( data, smb_base(inbuf) + data_offset, data_count);
- dump_data(10, data, data_count);
+ memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count);
+ dump_data(10, (char *)state->setup, state->setup_count);
}
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
+ if ((state->received_data == state->total_data) &&
+ (state->received_param == state->total_param)) {
+ outsize = handle_nttrans(conn, state, inbuf, outbuf,
+ size, bufsize);
+ SAFE_FREE(state->param);
+ SAFE_FREE(state->data);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttrans);
+ return outsize;
+ }
- if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
- /* We need to send an interim response then receive the rest
- of the parameter/data bytes */
- outsize = set_message(outbuf,0,0,True);
- srv_signing_trans_stop();
- show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("reply_nttrans: send_smb failed.");
- }
+ DLIST_ADD(conn->pending_trans, state);
- while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
- BOOL ret;
- uint32 parameter_displacement;
- uint32 data_displacement;
+ /* We need to send an interim response then receive the rest
+ of the parameter/data bytes */
+ outsize = set_message(outbuf,0,0,False);
+ show_msg(outbuf);
+ END_PROFILE(SMBnttrans);
+ return outsize;
- ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+ bad_param:
- /* We need to re-calcuate the new length after we've read the secondary packet. */
- length = smb_len(inbuf) + 4;
+ DEBUG(0,("reply_nttrans: invalid trans parameters\n"));
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttrans);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+}
+
+/****************************************************************************
+ Reply to a SMBnttranss
+ ****************************************************************************/
- /*
- * The sequence number for the trans reply is always
- * based on the last secondary received.
- */
+int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf,
+ int size,int bufsize)
+{
+ int outsize = 0;
+ unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
+ struct trans_state *state;
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
+ START_PROFILE(SMBnttranss);
- if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
- outsize = set_message(outbuf,0,0,True);
- if(ret) {
- DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
- } else {
- DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
- }
- goto bad_param;
- }
-
- /* Revise total_params and total_data in case they have changed downwards */
- if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) {
- total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
- }
- if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) {
- total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
- }
+ show_msg(inbuf);
- parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
- parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
- parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement);
- num_params_sofar += parameter_count;
+ for (state = conn->pending_trans; state != NULL;
+ state = state->next) {
+ if (state->mid == SVAL(inbuf,smb_mid)) {
+ break;
+ }
+ }
- data_count = IVAL(inbuf, smb_nts_DataCount);
- data_displacement = IVAL(inbuf, smb_nts_DataDisplacement);
- data_offset = IVAL(inbuf, smb_nts_DataOffset);
- num_data_sofar += data_count;
+ if ((state == NULL) || (state->cmd != SMBnttrans)) {
+ END_PROFILE(SMBnttranss);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
- if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) {
- DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet"));
- goto bad_param;
- }
+ /* Revise state->total_param and state->total_data in case they have
+ changed downwards */
+ if (IVAL(inbuf, smb_nts_TotalParameterCount) < state->total_param) {
+ state->total_param = IVAL(inbuf, smb_nts_TotalParameterCount);
+ }
+ if (IVAL(inbuf, smb_nts_TotalDataCount) < state->total_data) {
+ state->total_data = IVAL(inbuf, smb_nts_TotalDataCount);
+ }
- if (parameter_count) {
- if (parameter_displacement + parameter_count > total_parameter_count) {
- goto bad_param;
- }
- if ((parameter_displacement + parameter_count < parameter_displacement) ||
- (parameter_displacement + parameter_count < parameter_count)) {
- goto bad_param;
- }
- if (parameter_displacement > total_parameter_count) {
- goto bad_param;
- }
- if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) ||
- (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
- goto bad_param;
- }
- if (parameter_displacement + params < params) {
- goto bad_param;
- }
+ pcnt = IVAL(inbuf,smb_nts_ParameterCount);
+ poff = IVAL(inbuf, smb_nts_ParameterOffset);
+ pdisp = IVAL(inbuf, smb_nts_ParameterDisplacement);
- memcpy( &params[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
- }
+ dcnt = IVAL(inbuf, smb_nts_DataCount);
+ ddisp = IVAL(inbuf, smb_nts_DataDisplacement);
+ doff = IVAL(inbuf, smb_nts_DataOffset);
- if (data_count) {
- if (data_displacement + data_count > total_data_count) {
- goto bad_param;
- }
- if ((data_displacement + data_count < data_displacement) ||
- (data_displacement + data_count < data_count)) {
- goto bad_param;
- }
- if (data_displacement > total_data_count) {
- goto bad_param;
- }
- if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
- (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
- goto bad_param;
- }
- if (data_displacement + data < data) {
- goto bad_param;
- }
+ state->received_param += pcnt;
+ state->received_data += dcnt;
+
+ if ((state->received_data > state->total_data) ||
+ (state->received_param > state->total_param))
+ goto bad_param;
- memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
- }
- }
- }
+ if (pcnt) {
+ if (pdisp+pcnt > state->total_param)
+ goto bad_param;
+ if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
+ goto bad_param;
+ if (pdisp > state->total_param)
+ goto bad_param;
+ if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
+ (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->param + pdisp < state->param)
+ goto bad_param;
- if (Protocol >= PROTOCOL_NT1) {
- SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
+ memcpy(state->param+pdisp,smb_base(inbuf)+poff,
+ pcnt);
}
- /* Now we must call the relevant NT_TRANS function */
- switch(function_code) {
- case NT_TRANSACT_CREATE:
- START_PROFILE_NESTED(NT_transact_create);
- outsize = call_nt_transact_create(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_create);
- break;
- case NT_TRANSACT_IOCTL:
- START_PROFILE_NESTED(NT_transact_ioctl);
- outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_ioctl);
- break;
- case NT_TRANSACT_SET_SECURITY_DESC:
- START_PROFILE_NESTED(NT_transact_set_security_desc);
- outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_set_security_desc);
- break;
- case NT_TRANSACT_NOTIFY_CHANGE:
- START_PROFILE_NESTED(NT_transact_notify_change);
- outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_notify_change);
- break;
- case NT_TRANSACT_RENAME:
- START_PROFILE_NESTED(NT_transact_rename);
- outsize = call_nt_transact_rename(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_rename);
- break;
+ if (dcnt) {
+ if (ddisp+dcnt > state->total_data)
+ goto bad_param;
+ if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
+ goto bad_param;
+ if (ddisp > state->total_data)
+ goto bad_param;
+ if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
+ (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->data + ddisp < state->data)
+ goto bad_param;
- case NT_TRANSACT_QUERY_SECURITY_DESC:
- START_PROFILE_NESTED(NT_transact_query_security_desc);
- outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_query_security_desc);
- break;
-#ifdef HAVE_SYS_QUOTAS
- case NT_TRANSACT_GET_USER_QUOTA:
- START_PROFILE_NESTED(NT_transact_get_user_quota);
- outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_get_user_quota);
- break;
- case NT_TRANSACT_SET_USER_QUOTA:
- START_PROFILE_NESTED(NT_transact_set_user_quota);
- outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_set_user_quota);
- break;
-#endif /* HAVE_SYS_QUOTAS */
- default:
- /* Error in request */
- DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code));
- SAFE_FREE(setup);
- SAFE_FREE(params);
- SAFE_FREE(data);
- END_PROFILE(SMBnttrans);
- srv_signing_trans_stop();
- return ERROR_DOS(ERRSRV,ERRerror);
+ memcpy(state->data+ddisp, smb_base(inbuf)+doff,
+ dcnt);
}
- /* As we do not know how many data packets will need to be
- returned here the various call_nt_transact_xxxx calls
- must send their own. Thus a call_nt_transact_xxxx routine only
- returns a value other than -1 when it wants to send
- an error packet.
- */
+ if ((state->received_param < state->total_param) ||
+ (state->received_data < state->total_data)) {
+ END_PROFILE(SMBnttranss);
+ return -1;
+ }
- srv_signing_trans_stop();
+ /* construct_reply_common has done us the favor to pre-fill the
+ * command field with SMBnttranss which is wrong :-)
+ */
+ SCVAL(outbuf,smb_com,SMBnttrans);
- SAFE_FREE(setup);
- SAFE_FREE(params);
- SAFE_FREE(data);
- END_PROFILE(SMBnttrans);
- return outsize; /* If a correct response was needed the call_nt_transact_xxxx
- calls have already sent it. If outsize != -1 then it is
- returning an error packet. */
+ outsize = handle_nttrans(conn, state, inbuf, outbuf,
+ size, bufsize);
- bad_param:
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
- srv_signing_trans_stop();
- SAFE_FREE(params);
- SAFE_FREE(data);
- SAFE_FREE(setup);
- END_PROFILE(SMBnttrans);
+ if (outsize == 0) {
+ END_PROFILE(SMBnttranss);
+ return(ERROR_DOS(ERRSRV,ERRnosupport));
+ }
+
+ END_PROFILE(SMBnttranss);
+ return(outsize);
+
+ bad_param:
+
+ DEBUG(0,("reply_nttranss: invalid trans parameters\n"));
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttranss);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
diff --git a/source/smbd/open.c b/source/smbd/open.c
index dca8581874e..99a7894762c 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -22,6 +22,7 @@
#include "includes.h"
+extern struct generic_mapping file_generic_mapping;
extern struct current_user current_user;
extern userdom_struct current_user_info;
extern uint16 global_smbpid;
@@ -611,6 +612,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
{
int i;
struct share_mode_entry *exclusive = NULL;
+ BOOL valid_entry = False;
BOOL delay_it = False;
BOOL have_level2 = False;
@@ -619,33 +621,36 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
return False;
}
- if (lck->num_share_modes == 0) {
- /* No files open at all: Directly grant whatever the client
- * wants. */
-
- if (fsp->oplock_type == NO_OPLOCK) {
- /* Store a level2 oplock, but don't tell the client */
- fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
- }
- return False;
- }
-
for (i=0; i<lck->num_share_modes; i++) {
if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
continue;
}
+ /* At least one entry is not an invalid or deferred entry. */
+ valid_entry = True;
+
if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
SMB_ASSERT(exclusive == NULL);
exclusive = &lck->share_modes[i];
}
if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) {
+ SMB_ASSERT(exclusive == NULL);
have_level2 = True;
}
}
+ if (!valid_entry) {
+ /* All entries are placeholders or deferred.
+ * Directly grant whatever the client wants. */
+ if (fsp->oplock_type == NO_OPLOCK) {
+ /* Store a level2 oplock, but don't tell the client */
+ fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+ }
+ return False;
+ }
+
if (exclusive != NULL) { /* Found an exclusive oplock */
SMB_ASSERT(!have_level2);
delay_it = is_delete_request(fsp) ?
@@ -653,7 +658,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
}
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- /* We can at most grant level2 */
+ /* We can at most grant level2 as there are other
+ * level2 or NO_OPLOCK entries. */
fsp->oplock_type = LEVEL_II_OPLOCK;
}
@@ -718,7 +724,7 @@ static void defer_open(struct share_mode_lock *lck,
if (procid_is_me(&e->pid) && (e->op_mid == mid)) {
DEBUG(0, ("Trying to defer an already deferred "
"request: mid=%d, exiting\n", mid));
- exit_server("exiting");
+ exit_server("attempt to defer a deferred request");
}
}
@@ -732,7 +738,7 @@ static void defer_open(struct share_mode_lock *lck,
if (!push_deferred_smb_message(mid, request_time, timeout,
(char *)state, sizeof(*state))) {
- exit_server("push_deferred_smb_message failed\n");
+ exit_server("push_deferred_smb_message failed");
}
add_deferred_open(lck, mid, request_time, state->dev, state->inode);
@@ -1018,15 +1024,6 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func
}
-/* Map generic permissions to file object specific permissions */
-
-struct generic_mapping file_generic_mapping = {
- FILE_GENERIC_READ,
- FILE_GENERIC_WRITE,
- FILE_GENERIC_EXECUTE,
- FILE_GENERIC_ALL
-};
-
/****************************************************************************
Open a file with a share mode.
****************************************************************************/
@@ -1099,26 +1096,20 @@ files_struct *open_file_ntcreate(connection_struct *conn,
struct deferred_open_record *state =
(struct deferred_open_record *)pml->private_data.data;
+ /* Remember the absolute time of the original
+ request with this mid. We'll use it later to
+ see if this has timed out. */
+
request_time = pml->request_time;
delayed_for_oplocks = state->delayed_for_oplocks;
- /* There could be a race condition where the dev/inode pair
- has changed since we deferred the message. If so, just
- remove the deferred open entry and return sharing
- violation. */
-
- /* If the timeout value is non-zero, we need to just return
- sharing violation. Don't retry the open as we were not
- notified of a close and we don't want to trigger another
- spurious oplock break. */
-
- /* Now remove the deferred open entry under lock. */
+ /* Remove the deferred open entry under lock. */
lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("could not get share mode lock\n"));
} else {
del_deferred_open_entry(lck, mid);
- talloc_destroy(lck);
+ TALLOC_FREE(lck);
}
/* Ensure we don't reprocess this message. */
@@ -1335,15 +1326,16 @@ files_struct *open_file_ntcreate(connection_struct *conn,
if (delay_for_oplocks(lck, fsp)) {
struct deferred_open_record state;
- struct timeval timeout;
- if (delayed_for_oplocks) {
- DEBUG(0, ("Trying to delay for oplocks "
- "twice\n"));
- exit_server("exiting");
- }
+ /* This is a relative time, added to the absolute
+ request_time value to get the absolute timeout time.
+ Note that if this is the second or greater time we enter
+ this codepath for this particular request mid then
+ request_time is left as the absolute time of the *first*
+ time this request mid was processed. This is what allows
+ the request to eventually time out. */
- timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
+ struct timeval timeout;
/* Normally the smbd we asked should respond within
* OPLOCK_BREAK_TIMEOUT seconds regardless of whether
@@ -1351,6 +1343,13 @@ files_struct *open_file_ntcreate(connection_struct *conn,
* measure here in case the other smbd is stuck
* somewhere else. */
+ timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
+
+ /* Nothing actually uses state.delayed_for_oplocks
+ but it's handy to differentiate in debug messages
+ between a 30 second delay due to oplock break, and
+ a 1 second delay for share mode conflicts. */
+
state.delayed_for_oplocks = True;
state.dev = dev;
state.inode = inode;
@@ -1360,7 +1359,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
&state);
}
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
@@ -1371,7 +1370,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
/* DELETE_PENDING is not deferred for a second */
set_saved_ntstatus(status);
- talloc_free(lck);
+ TALLOC_FREE(lck);
file_free(fsp);
return NULL;
}
@@ -1392,7 +1391,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
create_options);
if (fsp_dup) {
- talloc_free(lck);
+ TALLOC_FREE(lck);
file_free(fsp);
if (pinfo) {
*pinfo = FILE_WAS_OPENED;
@@ -1441,8 +1440,28 @@ files_struct *open_file_ntcreate(connection_struct *conn,
lp_defer_sharing_violations()) {
struct timeval timeout;
struct deferred_open_record state;
+ int timeout_usecs;
- timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT);
+ /* this is a hack to speed up torture tests
+ in 'make test' */
+ timeout_usecs = lp_parm_int(conn->service,
+ "smbd","sharedelay",
+ SHARING_VIOLATION_USEC_WAIT);
+
+ /* This is a relative time, added to the absolute
+ request_time value to get the absolute timeout time.
+ Note that if this is the second or greater time we enter
+ this codepath for this particular request mid then
+ request_time is left as the absolute time of the *first*
+ time this request mid was processed. This is what allows
+ the request to eventually time out. */
+
+ timeout = timeval_set(0, timeout_usecs);
+
+ /* Nothing actually uses state.delayed_for_oplocks
+ but it's handy to differentiate in debug messages
+ between a 30 second delay due to oplock break, and
+ a 1 second delay for share mode conflicts. */
state.delayed_for_oplocks = False;
state.dev = dev;
@@ -1455,7 +1474,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
}
}
- talloc_free(lck);
+ TALLOC_FREE(lck);
if (fsp_open) {
fd_close(conn, fsp);
/*
@@ -1498,7 +1517,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
if (!fsp_open) {
if (lck != NULL) {
- talloc_free(lck);
+ TALLOC_FREE(lck);
}
file_free(fsp);
return NULL;
@@ -1559,7 +1578,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
defer_open(lck, request_time, timeval_zero(),
&state);
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
@@ -1596,7 +1615,7 @@ 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)) {
- talloc_free(lck);
+ TALLOC_FREE(lck);
fd_close(conn,fsp);
file_free(fsp);
return NULL;
@@ -1641,32 +1660,29 @@ files_struct *open_file_ntcreate(connection_struct *conn,
}
set_share_mode(lck, fsp, 0, fsp->oplock_type);
- if (create_options & FILE_DELETE_ON_CLOSE) {
- uint32 dosattr= existing_dos_attributes;
- NTSTATUS result;
-
- if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
+ if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
info == FILE_WAS_SUPERSEDED) {
- dosattr = new_dos_attributes;
- }
- result = can_set_delete_on_close(fsp, True, dosattr);
-
- if (!NT_STATUS_IS_OK(result)) {
- /* 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;
+ /* 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);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ /* 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;
+ }
+ /* 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;
}
- lck->delete_on_close = True;
- lck->modified = True;
- }
- if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
- info == FILE_WAS_SUPERSEDED) {
/* Files should be initially set as archive */
if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn))) {
@@ -1723,7 +1739,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
/* If this is a successful open, we must remove any deferred open
* records. */
del_deferred_open_entry(lck, mid);
- talloc_free(lck);
+ TALLOC_FREE(lck);
conn->num_files_open++;
@@ -1944,27 +1960,30 @@ files_struct *open_directory(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)) {
set_saved_ntstatus(status);
- talloc_free(lck);
+ TALLOC_FREE(lck);
file_free(fsp);
return NULL;
}
set_share_mode(lck, fsp, 0, NO_OPLOCK);
+ /* For directories the delete on close bit at open time seems
+ 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);
- talloc_free(lck);
+ TALLOC_FREE(lck);
file_free(fsp);
return NULL;
}
- lck->delete_on_close = True;
+ set_delete_on_close_token(lck, &current_user.ut);
+ lck->initial_delete_on_close = True;
lck->modified = True;
}
- talloc_free(lck);
+ TALLOC_FREE(lck);
/* Change the owner if required. */
if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) {
@@ -2026,3 +2045,55 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
return fsp;
}
+
+/****************************************************************************
+ Receive notification that one of our open files has been renamed by another
+ smbd process.
+****************************************************************************/
+
+void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len)
+{
+ files_struct *fsp;
+ char *frm = (char *)buf;
+ SMB_DEV_T dev;
+ SMB_INO_T inode;
+ const char *sharepath;
+ const char *newname;
+ size_t sp_len;
+
+ if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) {
+ DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len));
+ return;
+ }
+
+ /* Unpack the message. */
+ dev = DEV_T_VAL(frm,0);
+ inode = INO_T_VAL(frm,8);
+ sharepath = &frm[16];
+ newname = sharepath + strlen(sharepath) + 1;
+ sp_len = strlen(sharepath);
+
+ DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, "
+ "dev %x, inode %.0f\n",
+ sharepath, newname, (unsigned int)dev, (double)inode ));
+
+ for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
+ if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) {
+ DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
+ fsp->fnum, fsp->fsp_name, newname ));
+ string_set(&fsp->fsp_name, newname);
+ } else {
+ /* TODO. JRA. */
+ /* Now we have the complete path we can work out if this is
+ actually within this share and adjust newname accordingly. */
+ DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s "
+ "not sharepath %s) "
+ "fnum %d from %s -> %s\n",
+ fsp->conn->connectpath,
+ sharepath,
+ fsp->fnum,
+ fsp->fsp_name,
+ newname ));
+ }
+ }
+}
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index 5cc027fcc98..70e5bf4d727 100644
--- a/source/smbd/oplock.c
+++ b/source/smbd/oplock.c
@@ -27,7 +27,6 @@ static int32 exclusive_oplocks_open = 0;
static int32 level_II_oplocks_open = 0;
BOOL global_client_failed_oplock_break = False;
-extern struct timeval smb_last_time;
extern uint32 global_client_caps;
extern int smb_read_error;
@@ -197,7 +196,7 @@ BOOL remove_oplock(files_struct *fsp)
(double)inode));
}
release_file_oplock(fsp);
- talloc_free(lck);
+ TALLOC_FREE(lck);
return ret;
}
@@ -226,26 +225,21 @@ BOOL downgrade_oplock(files_struct *fsp)
}
downgrade_file_oplock(fsp);
- talloc_free(lck);
+ TALLOC_FREE(lck);
return ret;
}
/****************************************************************************
- Setup the listening set of file descriptors for an oplock break
- message either from the UDP socket or from the kernel. Returns the maximum
- fd used.
+ Return the fd (if any) used for receiving oplock notifications.
****************************************************************************/
-int setup_oplock_select_set( fd_set *fds)
+int oplock_notify_fd(void)
{
- int maxfd = 0;
-
- if (koplocks && koplocks->notification_fd != -1) {
- FD_SET(koplocks->notification_fd, fds);
- maxfd = MAX(maxfd, koplocks->notification_fd);
+ if (koplocks) {
+ return koplocks->notification_fd;
}
- return maxfd;
+ return -1;
}
/****************************************************************************
@@ -282,21 +276,10 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx,
static void wait_before_sending_break(void)
{
- struct timeval cur_tv;
- long wait_left = (long)lp_oplock_break_wait_time();
-
- if (wait_left == 0) {
- return;
- }
-
- GetTimeOfDay(&cur_tv);
+ long wait_time = (long)lp_oplock_break_wait_time();
- wait_left -= ((cur_tv.tv_sec - smb_last_time.tv_sec)*1000) +
- ((cur_tv.tv_usec - smb_last_time.tv_usec)/1000);
-
- if(wait_left > 0) {
- wait_left = MIN(wait_left, 1000);
- sys_usleep(wait_left * 1000);
+ if (wait_time) {
+ smb_msleep(wait_time);
}
}
@@ -475,7 +458,7 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce
/* Restore the sign state to what it was. */
srv_oplock_set_signing(sign_state);
- talloc_free(break_msg);
+ TALLOC_FREE(break_msg);
/* Async level2 request, don't send a reply, just remove the oplock. */
remove_oplock(fsp);
@@ -583,7 +566,7 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
/* Restore the sign state to what it was. */
srv_oplock_set_signing(sign_state);
- talloc_free(break_msg);
+ TALLOC_FREE(break_msg);
fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
@@ -659,7 +642,7 @@ static void process_kernel_oplock_break(int msg_type, struct process_id src,
/* Restore the sign state to what it was. */
srv_oplock_set_signing(sign_state);
- talloc_free(break_msg);
+ TALLOC_FREE(break_msg);
fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
@@ -686,7 +669,7 @@ void reply_to_oplock_break_requests(files_struct *fsp)
fsp->num_pending_break_messages = 0;
if (fsp->oplock_timeout != NULL) {
/* Remove the timed event handler. */
- talloc_free(fsp->oplock_timeout);
+ TALLOC_FREE(fsp->oplock_timeout);
fsp->oplock_timeout = NULL;
}
return;
@@ -769,6 +752,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
if (lck == NULL) {
DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
"share mode entry for file %s.\n", fsp->fsp_name ));
+ return;
}
DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n",
@@ -806,7 +790,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
DEBUG(0,("release_level_2_oplocks_on_change: PANIC. "
"share mode entry %d is an exlusive "
"oplock !\n", i ));
- talloc_free(lck);
+ TALLOC_FREE(lck);
abort();
}
@@ -821,7 +805,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
/* We let the message receivers handle removing the oplock state
in the share mode lock db. */
- talloc_free(lck);
+ TALLOC_FREE(lck);
}
/****************************************************************************
diff --git a/source/smbd/oplock_irix.c b/source/smbd/oplock_irix.c
index fa86211c7f6..83883444a7b 100644
--- a/source/smbd/oplock_irix.c
+++ b/source/smbd/oplock_irix.c
@@ -35,7 +35,7 @@ static BOOL irix_oplocks_available(void)
int pfd[2];
pstring tmpname;
- oplock_set_capability(True, False);
+ set_effective_capability(KERNEL_OPLOCK_CAPABILITY);
slprintf(tmpname,sizeof(tmpname)-1, "%s/koplock.%d", lp_lockdir(), (int)sys_getpid());
@@ -206,13 +206,13 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
}
/****************************************************************************
- Set *maxfd to include oplock read pipe.
+ See if there is a message waiting in this fd set.
Note that fds MAY BE NULL ! If so we must do our own select.
****************************************************************************/
static BOOL irix_oplock_msg_waiting(fd_set *fds)
{
- int maxfd, selrtn;
+ int selrtn;
fd_set myfds;
struct timeval to;
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 764fbe8a2e9..8d33c1deed1 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -100,7 +100,7 @@ void invalidate_vuid(uint16 vuid)
session_yield(vuser);
SAFE_FREE(vuser->session_keystr);
- free_server_info(&vuser->server_info);
+ TALLOC_FREE(vuser->server_info);
data_blob_free(&vuser->session_key);
@@ -111,7 +111,7 @@ void invalidate_vuid(uint16 vuid)
conn_clear_vuid_cache(vuid);
SAFE_FREE(vuser->groups);
- delete_nt_token(&vuser->nt_user_token);
+ TALLOC_FREE(vuser->nt_user_token);
SAFE_FREE(vuser);
num_validated_vuids--;
}
@@ -136,9 +136,11 @@ void invalidate_all_vuids(void)
* @param server_info The token returned from the authentication process.
* (now 'owned' by register_vuid)
*
- * @param session_key The User session key for the login session (now also 'owned' by register_vuid)
+ * @param session_key The User session key for the login session (now also
+ * 'owned' by register_vuid)
*
- * @param respose_blob The NT challenge-response, if available. (May be freed after this call)
+ * @param respose_blob The NT challenge-response, if available. (May be
+ * freed after this call)
*
* @param smb_name The untranslated name of the user
*
@@ -147,7 +149,9 @@ void invalidate_all_vuids(void)
*
*/
-int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name)
+int register_vuid(auth_serversupplied_info *server_info,
+ DATA_BLOB session_key, DATA_BLOB response_blob,
+ const char *smb_name)
{
user_struct *vuser = NULL;
@@ -179,7 +183,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
next_vuid = VUID_OFFSET;
}
- DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));
+ DEBUG(10,("register_vuid: allocated vuid = %u\n",
+ (unsigned int)next_vuid ));
vuser->vuid = next_vuid;
@@ -203,11 +208,14 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
vuser->n_groups = server_info->n_groups;
if (vuser->n_groups) {
- if (!(vuser->groups = (gid_t *)memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
- DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
+ if (!(vuser->groups = (gid_t *)memdup(server_info->groups,
+ sizeof(gid_t) *
+ vuser->n_groups))) {
+ DEBUG(0,("register_vuid: failed to memdup "
+ "vuser->groups\n"));
data_blob_free(&session_key);
free(vuser);
- free_server_info(&server_info);
+ TALLOC_FREE(server_info);
return UID_FIELD_INVALID;
}
}
@@ -216,26 +224,35 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
fstrcpy(vuser->user.unix_name, server_info->unix_name);
/* This is a potentially untrusted username */
- alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name));
+ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
+ sizeof(vuser->user.smb_name));
fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
- fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));
+ fstrcpy(vuser->user.full_name,
+ pdb_get_fullname(server_info->sam_account));
{
/* Keep the homedir handy */
- const char *homedir = pdb_get_homedir(server_info->sam_account);
- const char *logon_script = pdb_get_logon_script(server_info->sam_account);
-
- if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) {
- const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
+ const char *homedir =
+ pdb_get_homedir(server_info->sam_account);
+ const char *logon_script =
+ pdb_get_logon_script(server_info->sam_account);
+
+ if (!IS_SAM_DEFAULT(server_info->sam_account,
+ PDB_UNIXHOMEDIR)) {
+ const char *unix_homedir =
+ pdb_get_unix_homedir(server_info->sam_account);
if (unix_homedir) {
- vuser->unix_homedir = smb_xstrdup(unix_homedir);
+ vuser->unix_homedir =
+ smb_xstrdup(unix_homedir);
}
} else {
- struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name);
+ struct passwd *passwd =
+ getpwnam_alloc(NULL, vuser->user.unix_name);
if (passwd) {
- vuser->unix_homedir = smb_xstrdup(passwd->pw_dir);
- passwd_free(&passwd);
+ vuser->unix_homedir =
+ smb_xstrdup(passwd->pw_dir);
+ TALLOC_FREE(passwd);
}
}
@@ -252,15 +269,18 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n",
(unsigned int)vuser->uid,
(unsigned int)vuser->gid,
- vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest ));
+ vuser->user.unix_name, vuser->user.smb_name,
+ vuser->user.domain, vuser->guest ));
- DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));
+ DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name,
+ vuser->user.full_name));
if (server_info->ptok) {
- vuser->nt_user_token = dup_nt_token(server_info->ptok);
+ vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok);
} else {
- DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
- free_server_info(&server_info);
+ DEBUG(1, ("server_info does not contain a user_token - "
+ "cannot continue\n"));
+ TALLOC_FREE(server_info);
data_blob_free(&session_key);
SAFE_FREE(vuser->homedir);
SAFE_FREE(vuser->unix_homedir);
@@ -273,7 +293,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
/* use this to keep tabs on all our info from the authentication */
vuser->server_info = server_info;
- DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
+ DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",
+ (int)vuser->uid,vuser->user.unix_name, vuser->vuid));
next_vuid++;
num_validated_vuids++;
@@ -281,9 +302,10 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
DLIST_ADD(validated_users, vuser);
if (!session_claim(vuser)) {
- DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid));
+ DEBUG(1, ("Failed to claim session for vuid=%d\n",
+ vuser->vuid));
invalidate_vuid(vuser->vuid);
- return -1;
+ return UID_FIELD_INVALID;
}
/* Register a home dir service for this user iff
@@ -301,19 +323,26 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
int servicenumber = lp_servicenumber(vuser->user.unix_name);
if ( servicenumber == -1 ) {
- DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n",
+ DEBUG(3, ("Adding homes service for user '%s' using "
+ "home directory: '%s'\n",
vuser->user.unix_name, vuser->unix_homedir));
- vuser->homes_snum = add_home_service(vuser->user.unix_name,
- vuser->user.unix_name, vuser->unix_homedir);
+ vuser->homes_snum =
+ add_home_service(vuser->user.unix_name,
+ vuser->user.unix_name,
+ vuser->unix_homedir);
} else {
- DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n",
- vuser->user.unix_name, lp_pathname(servicenumber) ));
+ DEBUG(3, ("Using static (or previously created) "
+ "service for user '%s'; path = '%s'\n",
+ vuser->user.unix_name,
+ lp_pathname(servicenumber) ));
vuser->homes_snum = servicenumber;
}
}
- if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) {
- /* Try and turn on server signing on the first non-guest sessionsetup. */
+ if (srv_is_signing_negotiated() && !vuser->guest &&
+ !srv_signing_started()) {
+ /* Try and turn on server signing on the first non-guest
+ * sessionsetup. */
srv_set_signing(vuser->session_key, response_blob);
}
@@ -344,14 +373,19 @@ void add_session_user(const char *user)
if( session_userlist && in_list(suser,session_userlist,False) )
return;
- if( !session_userlist || (strlen(suser) + strlen(session_userlist) + 2 >= len_session_userlist) ) {
+ if( !session_userlist ||
+ (strlen(suser) + strlen(session_userlist) + 2 >=
+ len_session_userlist) ) {
char *newlist;
if (len_session_userlist > 128 * PSTRING_LEN) {
- DEBUG(3,("add_session_user: session userlist already too large.\n"));
+ DEBUG(3,("add_session_user: session userlist already "
+ "too large.\n"));
return;
}
- newlist = (char *)SMB_REALLOC( session_userlist, len_session_userlist + PSTRING_LEN );
+ newlist = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR(
+ session_userlist,
+ len_session_userlist + PSTRING_LEN );
if( newlist == NULL ) {
DEBUG(1,("Unable to resize session_userlist\n"));
return;
@@ -368,10 +402,139 @@ void add_session_user(const char *user)
}
/****************************************************************************
+ Check if a user is in a netgroup user list. If at first we don't succeed,
+ try lower case.
+****************************************************************************/
+
+BOOL user_in_netgroup(const char *user, const char *ngname)
+{
+#ifdef HAVE_NETGROUP
+ static char *mydomain = NULL;
+ fstring lowercase_user;
+
+ if (mydomain == NULL)
+ yp_get_default_domain(&mydomain);
+
+ if(mydomain == NULL) {
+ DEBUG(5,("Unable to get default yp domain\n"));
+ return False;
+ }
+
+ DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+ user, mydomain, ngname));
+
+ if (innetgr(ngname, NULL, user, mydomain)) {
+ DEBUG(5,("user_in_netgroup: Found\n"));
+ return (True);
+ } else {
+
+ /*
+ * Ok, innetgr is case sensitive. Try once more with lowercase
+ * just in case. Attempt to fix #703. JRA.
+ */
+
+ fstrcpy(lowercase_user, user);
+ strlower_m(lowercase_user);
+
+ DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+ lowercase_user, mydomain, ngname));
+
+ if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
+ DEBUG(5,("user_in_netgroup: Found\n"));
+ return (True);
+ }
+ }
+#endif /* HAVE_NETGROUP */
+ return False;
+}
+
+/****************************************************************************
+ Check if a user is in a user list - can check combinations of UNIX
+ and netgroup lists.
+****************************************************************************/
+
+BOOL user_in_list(const char *user,const char **list)
+{
+ if (!list || !*list)
+ return False;
+
+ DEBUG(10,("user_in_list: checking user %s in list\n", user));
+
+ while (*list) {
+
+ DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
+ user, *list));
+
+ /*
+ * Check raw username.
+ */
+ if (strequal(user, *list))
+ return(True);
+
+ /*
+ * Now check to see if any combination
+ * of UNIX and netgroups has been specified.
+ */
+
+ if(**list == '@') {
+ /*
+ * Old behaviour. Check netgroup list
+ * followed by UNIX list.
+ */
+ if(user_in_netgroup(user, *list +1))
+ return True;
+ if(user_in_group(user, *list +1))
+ return True;
+ } else if (**list == '+') {
+
+ if((*(*list +1)) == '&') {
+ /*
+ * Search UNIX list followed by netgroup.
+ */
+ if(user_in_group(user, *list +2))
+ return True;
+ if(user_in_netgroup(user, *list +2))
+ return True;
+
+ } else {
+
+ /*
+ * Just search UNIX list.
+ */
+
+ if(user_in_group(user, *list +1))
+ return True;
+ }
+
+ } else if (**list == '&') {
+
+ if(*(*list +1) == '+') {
+ /*
+ * Search netgroup list followed by UNIX list.
+ */
+ if(user_in_netgroup(user, *list +2))
+ return True;
+ if(user_in_group(user, *list +2))
+ return True;
+ } else {
+ /*
+ * Just search netgroup list.
+ */
+ if(user_in_netgroup(user, *list +1))
+ return True;
+ }
+ }
+
+ list++;
+ }
+ return(False);
+}
+
+/****************************************************************************
Check if a username is valid.
****************************************************************************/
-BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
+static BOOL user_ok(const char *user, int snum)
{
char **valid, **invalid;
BOOL ret;
@@ -387,8 +550,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
str_list_sub_basic(invalid,
current_user_info.smb_name) ) {
ret = !user_in_list(user,
- (const char **)invalid,
- groups, n_groups);
+ (const char **)invalid);
}
}
}
@@ -402,8 +564,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
if ( valid &&
str_list_sub_basic(valid,
current_user_info.smb_name) ) {
- ret = user_in_list(user, (const char **)valid,
- groups, n_groups);
+ ret = user_in_list(user, (const char **)valid);
}
}
}
@@ -415,8 +576,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
if (user_list &&
str_list_substitute(user_list, "%S",
lp_servicename(snum))) {
- ret = user_in_list(user, (const char **)user_list,
- groups, n_groups);
+ ret = user_in_list(user, (const char **)user_list);
}
if (user_list) str_list_free (&user_list);
}
@@ -436,7 +596,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
setnetgrent(group);
while (getnetgrent(&host, &user, &domain)) {
if (user) {
- if (user_ok(user, snum, NULL, 0) &&
+ if (user_ok(user, snum) &&
password_ok(user,password)) {
endnetgrent();
return(user);
@@ -472,12 +632,15 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
member = member_list;
for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
- size_t member_len = strlen(gptr->gr_mem[i]) + 1;
- if( copied_len + member_len < sizeof(pstring)) {
+ size_t member_len = strlen(gptr->gr_mem[i])+1;
+ if(copied_len+member_len < sizeof(pstring)) {
- DEBUG(10,("validate_group: = gr_mem = %s\n", gptr->gr_mem[i]));
+ DEBUG(10,("validate_group: = gr_mem = "
+ "%s\n", gptr->gr_mem[i]));
- safe_strcpy(member, gptr->gr_mem[i], sizeof(pstring) - copied_len - 1);
+ safe_strcpy(member, gptr->gr_mem[i],
+ sizeof(pstring) -
+ copied_len - 1);
copied_len += member_len;
member += copied_len;
} else {
@@ -491,13 +654,14 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
while (*member) {
static fstring name;
fstrcpy(name,member);
- if (user_ok(name,snum, NULL, 0) &&
+ if (user_ok(name,snum) &&
password_ok(name,password)) {
endgrent();
return(&name[0]);
}
- DEBUG(10,("validate_group = member = %s\n", member));
+ DEBUG(10,("validate_group = member = %s\n",
+ member));
member += strlen(member) + 1;
}
@@ -558,7 +722,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
auser = strtok(NULL,LIST_SEP)) {
fstring user2;
fstrcpy(user2,auser);
- if (!user_ok(user2,snum, NULL, 0))
+ if (!user_ok(user2,snum))
continue;
if (password_ok(user2,password)) {
@@ -595,7 +759,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
} else {
fstring user2;
fstrcpy(user2,auser);
- if (user_ok(user2,snum, NULL, 0) &&
+ if (user_ok(user2,snum) &&
password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
@@ -624,7 +788,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
*guest = True;
}
- if (ok && !user_ok(user, snum, NULL, 0)) {
+ if (ok && !user_ok(user, snum)) {
DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
ok = False;
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 610fce866a3..40cb6698a02 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -516,10 +516,12 @@ static size_t count_canon_ace_list( canon_ace *list_head )
static void free_canon_ace_list( canon_ace *list_head )
{
- while (list_head) {
- canon_ace *old_head = list_head;
- DLIST_REMOVE(list_head, list_head);
- SAFE_FREE(old_head);
+ canon_ace *list, *next;
+
+ for (list = list_head; list; list = next) {
+ next = list->next;
+ DLIST_REMOVE(list_head, list);
+ SAFE_FREE(list);
}
}
@@ -783,15 +785,15 @@ static void merge_aces( canon_ace **pp_list_head )
static BOOL nt4_compatible_acls(void)
{
- const char *compat = lp_acl_compatibility();
+ int compat = lp_acl_compatibility();
- if (*compat == '\0') {
+ if (compat == ACL_COMPAT_AUTO) {
enum remote_arch_types ra_type = get_remote_arch();
/* Automatically adapt to client */
return (ra_type <= RA_WINNT);
} else
- return (strequal(compat, "winnt"));
+ return (compat == ACL_COMPAT_WINNT);
}
@@ -925,11 +927,11 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid
if (security_info_sent & OWNER_SECURITY_INFORMATION) {
sid_copy(&owner_sid, psd->owner_sid);
- if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) {
+ if (!sid_to_uid(&owner_sid, puser)) {
if (lp_force_unknown_acl_user(snum)) {
/* this allows take ownership to work
* reasonably */
- *puser = current_user.uid;
+ *puser = current_user.ut.uid;
} else {
DEBUG(3,("unpack_nt_owners: unable to validate"
" owner sid for %s\n",
@@ -946,11 +948,11 @@ 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);
- if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) {
+ if (!sid_to_gid( &grp_sid, pgrp)) {
if (lp_force_unknown_acl_user(snum)) {
/* this allows take group ownership to work
* reasonably */
- *pgrp = current_user.gid;
+ *pgrp = current_user.ut.gid;
} else {
DEBUG(3,("unpack_nt_owners: unable to validate"
" group sid.\n"));
@@ -1015,7 +1017,6 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
{
fstring u_name;
- fstring g_name;
/* "Everyone" always matches every uid. */
@@ -1024,18 +1025,11 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
/* Assume that the current user is in the current group (force group) */
- if (uid_ace->unix_ug.uid == current_user.uid && group_ace->unix_ug.gid == current_user.gid)
+ if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid)
return True;
fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
- fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
-
- /*
- * Due to the winbind interfaces we need to do this via names,
- * not uids/gids.
- */
-
- return user_in_group_list(u_name, g_name, NULL, 0);
+ return user_in_group_sid(u_name, &group_ace->trustee);
}
/****************************************************************************
@@ -1390,10 +1384,10 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
if (nt4_compatible_acls())
psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
- } else if (NT_STATUS_IS_OK(sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid))) {
+ } else if (sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid)) {
current_ace->owner_type = UID_ACE;
current_ace->type = SMB_ACL_USER;
- } else if (NT_STATUS_IS_OK(sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid))) {
+ } else if (sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid)) {
current_ace->owner_type = GID_ACE;
current_ace->type = SMB_ACL_GROUP;
} else {
@@ -2246,8 +2240,8 @@ static BOOL current_user_in_group(gid_t gid)
{
int i;
- for (i = 0; i < current_user.ngroups; i++) {
- if (current_user.groups[i] == gid) {
+ for (i = 0; i < current_user.ut.ngroups; i++) {
+ if (current_user.ut.groups[i] == gid) {
return True;
}
}
@@ -2256,18 +2250,20 @@ static BOOL current_user_in_group(gid_t gid)
}
/****************************************************************************
- Should we override a deny ?
+ Should we override a deny ? Check deprecated 'acl group control'
+ and 'dos filemode'
****************************************************************************/
static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid)
{
- if ((errno == EACCES || errno == EPERM) &&
- lp_acl_group_control(SNUM(conn)) &&
- current_user_in_group(prim_gid)) {
+ if ( (errno == EACCES || errno == EPERM)
+ && (lp_acl_group_control(SNUM(conn) || lp_dos_filemode(SNUM(conn))))
+ && current_user_in_group(prim_gid) )
+ {
return True;
- } else {
- return False;
- }
+ }
+
+ return False;
}
/****************************************************************************
@@ -3026,7 +3022,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_
&se_restore);
/* Case (2) */
- if ( ( has_take_ownership_priv && ( uid == current_user.uid ) ) ||
+ if ( ( has_take_ownership_priv && ( uid == current_user.ut.uid ) ) ||
/* Case (3) */
( has_restore_priv ) ) {
@@ -3056,7 +3052,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_
and also copes with the case where the SID in a take ownership ACL is
a local SID on the users workstation
*/
- uid = current_user.uid;
+ uid = current_user.ut.uid;
become_root();
/* Keep the current file gid the same. */
@@ -3136,7 +3132,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
* the file.
*/
- if (need_chown && (user == (uid_t)-1 || user == current_user.uid)) {
+ if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) {
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
@@ -3842,6 +3838,21 @@ static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const c
}
}
+ /* Set the new empty file ACL. */
+ if (fsp && fsp->fh->fd != -1) {
+ if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, new_file_acl) == -1) {
+ DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
+ fname, strerror(errno) ));
+ goto done;
+ }
+ } else {
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) {
+ DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
+ fname, strerror(errno) ));
+ goto done;
+ }
+ }
+
ret = True;
done:
@@ -3960,12 +3971,12 @@ refusing write due to mask.\n", fname));
break;
case SMB_ACL_USER:
{
- /* Check against current_user.uid. */
+ /* Check against current_user.ut.uid. */
uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
if (puid == NULL) {
goto check_stat;
}
- if (current_user.uid == *puid) {
+ if (current_user.ut.uid == *puid) {
/* We have a uid match but we must ensure we have seen the acl mask. */
ret = have_write;
DEBUG(10,("check_posix_acl_group_write: file %s \
@@ -4130,13 +4141,13 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
if (!S_ISDIR(sbuf.st_mode)) {
return False;
}
- if (current_user.uid == 0 || conn->admin_user) {
+ if (current_user.ut.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
/* Check primary owner write access. */
- if (current_user.uid == sbuf.st_uid) {
+ if (current_user.ut.uid == sbuf.st_uid) {
return (sbuf.st_mode & S_IWUSR) ? True : False;
}
@@ -4152,7 +4163,7 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
* for bug #3348. Don't assume owning sticky bit
* directory means write access allowed.
*/
- if (current_user.uid != sbuf_file.st_uid) {
+ if (current_user.ut.uid != sbuf_file.st_uid) {
return False;
}
}
@@ -4178,7 +4189,7 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST
{
int ret;
- if (current_user.uid == 0 || conn->admin_user) {
+ if (current_user.ut.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
@@ -4191,7 +4202,7 @@ BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_ST
}
/* Check primary owner write access. */
- if (current_user.uid == psbuf->st_uid) {
+ if (current_user.ut.uid == psbuf->st_uid) {
return (psbuf->st_mode & S_IWUSR) ? True : False;
}
@@ -4221,7 +4232,7 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
connection_struct conn;
files_struct finfo;
struct fd_handle fh;
- fstring path;
+ pstring path;
pstring filename;
ZERO_STRUCT( conn );
@@ -4232,8 +4243,8 @@ SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
return NULL;
}
- fstrcpy( path, "/" );
- string_set(&conn.connectpath, path);
+ pstrcpy( path, "/" );
+ set_conn_connectpath(&conn, path);
if (!smbd_vfs_init(&conn)) {
DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 38d6e4d7cf1..aaf98203a25 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -26,8 +26,6 @@ extern int keepalive;
extern struct auth_context *negprot_global_auth_context;
extern int smb_echo_count;
-struct timeval smb_last_time;
-
static char *InBuffer = NULL;
static char *OutBuffer = NULL;
static char *current_inbuf = NULL;
@@ -91,7 +89,7 @@ static BOOL push_queued_message(char *buf, int msg_len,
msg->buf = data_blob_talloc(msg, buf, msg_len);
if(msg->buf.data == NULL) {
DEBUG(0,("push_message: malloc fail (2)\n"));
- talloc_free(msg);
+ TALLOC_FREE(msg);
return False;
}
@@ -103,7 +101,7 @@ static BOOL push_queued_message(char *buf, int msg_len,
private_len);
if (msg->private_data.data == NULL) {
DEBUG(0,("push_message: malloc fail (3)\n"));
- talloc_free(msg);
+ TALLOC_FREE(msg);
return False;
}
}
@@ -131,7 +129,7 @@ void remove_deferred_open_smb_message(uint16 mid)
(unsigned int)mid,
(unsigned int)pml->buf.length ));
DLIST_REMOVE(deferred_open_queue, pml);
- talloc_free(pml);
+ TALLOC_FREE(pml);
return;
}
}
@@ -223,115 +221,6 @@ BOOL push_deferred_smb_message(uint16 mid,
private_data, priv_len);
}
-static struct timed_event *timed_events;
-
-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;
-};
-
-static int timed_event_destructor(void *p)
-{
- 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);
- return 0;
-}
-
-/****************************************************************************
- 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 timeval when,
- const char *event_name,
- void (*handler)(struct timed_event *te,
- const struct timeval *now,
- void *private_data),
- void *private_data)
-{
- struct timed_event *te, *last_te, *cur_te;
-
- te = TALLOC_P(mem_ctx, struct timed_event);
- if (te == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return NULL;
- }
-
- 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;
- }
-
- 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,
- (unsigned long)te));
- return te;
-}
-
-static void run_events(void)
-{
- struct timeval now;
-
- if (timed_events == NULL) {
- /* No syscall if there are no events */
- DEBUG(10, ("run_events: No events\n"));
- return;
- }
-
- GetTimeOfDay(&now);
-
- if (timeval_compare(&now, &timed_events->when) < 0) {
- /* Nothing to do yet */
- DEBUG(10, ("run_events: Nothing to do\n"));
- return;
- }
-
- DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
- (unsigned long)timed_events));
-
- timed_events->handler(timed_events, &now, timed_events->private_data);
- return;
-}
-
-struct timeval timed_events_timeout(void)
-{
- struct timeval now, timeout;
-
- if (timed_events == NULL) {
- return timeval_set(SMBD_SELECT_TIMEOUT, 0);
- }
-
- now = timeval_current();
- timeout = timeval_until(&now, &timed_events->when);
-
- DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec,
- (int)timeout.tv_usec));
-
- return timeout;
-}
-
struct idle_event {
struct timed_event *te;
struct timeval interval;
@@ -346,11 +235,11 @@ static void idle_event_handler(struct timed_event *te,
struct idle_event *event =
talloc_get_type_abort(private_data, struct idle_event);
- talloc_free(event->te);
+ TALLOC_FREE(event->te);
if (!event->handler(now, event->private_data)) {
/* Don't repeat, delete ourselves */
- talloc_free(event);
+ TALLOC_FREE(event);
return;
}
@@ -386,13 +275,13 @@ struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
idle_event_handler, result);
if (result->te == NULL) {
DEBUG(0, ("add_timed_event failed\n"));
- talloc_free(result);
+ TALLOC_FREE(result);
return NULL;
}
return result;
}
-
+
/****************************************************************************
Do all async processing in here. This includes kernel oplock messages, change
notify events etc.
@@ -412,7 +301,7 @@ static void async_processing(fd_set *pfds)
process_aio_queue();
if (got_sig_term) {
- exit_server("Caught TERM signal");
+ exit_server_cleanly("termination signal");
}
/* check for async change notify events */
@@ -428,6 +317,20 @@ static void async_processing(fd_set *pfds)
}
/****************************************************************************
+ Add a fd to the set we will be select(2)ing on.
+****************************************************************************/
+
+static int select_on_fd(int fd, int maxfd, fd_set *fds)
+{
+ if (fd != -1) {
+ FD_SET(fd, fds);
+ maxfd = MAX(maxfd, fd);
+ }
+
+ return maxfd;
+}
+
+/****************************************************************************
Do a select on an two fd's - with timeout.
If a local udp message has been pushed onto the
@@ -452,8 +355,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
{
fd_set fds;
int selrtn;
- struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0);
- int maxfd;
+ struct timeval to;
+ int maxfd = 0;
smb_read_error = 0;
@@ -462,6 +365,9 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
if (timeout >= 0) {
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
+ } else {
+ to.tv_sec = SMBD_SELECT_TIMEOUT;
+ to.tv_usec = 0;
}
/*
@@ -536,18 +442,29 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
goto again;
}
+ /*
+ * Are there any timed events waiting ? If so, ensure we don't
+ * select for longer than it would take to wait for them.
+ */
+
{
- struct timeval tmp = timed_events_timeout();
- to = timeval_min(&to, &tmp);
- if (timeval_is_zero(&to)) {
- return True;
+ 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();
+ }
}
}
- FD_SET(smbd_server_fd(),&fds);
- maxfd = setup_oplock_select_set(&fds);
+ 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);
- selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to);
+ selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to);
/* if we get EINTR then maybe we have received an oplock
signal - treat this as select returning 1. This is ugly, but
@@ -595,22 +512,27 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
return receive_smb(smbd_server_fd(), buffer, 0);
}
-/****************************************************************************
-Get the next SMB packet, doing the local message processing automatically.
-****************************************************************************/
+/*
+ * Only allow 5 outstanding trans requests. We're allocating memory, so
+ * prevent a DoS.
+ */
-BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
+NTSTATUS allow_new_trans(struct trans_state *list, int mid)
{
- BOOL got_keepalive;
- BOOL ret;
+ int count = 0;
+ for (; list != NULL; list = list->next) {
- do {
- ret = receive_message_or_smb(inbuf,bufsize,timeout);
-
- got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
- } while (ret && got_keepalive);
+ if (list->mid == mid) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ count += 1;
+ }
+ if (count > 5) {
+ return NT_STATUS_INSUFFICIENT_RESOURCES;
+ }
- return ret;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -701,7 +623,7 @@ static const struct smb_message_struct {
/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
-/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
+/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
/* 0x27 */ { "SMBioctl",reply_ioctl,0},
/* 0x28 */ { "SMBioctls",NULL,AS_USER},
/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
@@ -971,7 +893,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
/* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
- exit_server("Non-SMB packet");
+ exit_server_cleanly("Non-SMB packet");
return(-1);
}
@@ -1087,8 +1009,6 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
int outsize = 0;
int msg_type = CVAL(inbuf,0);
- GetTimeOfDay(&smb_last_time);
-
chain_size = 0;
file_chain_reset();
reset_chain_p();
@@ -1162,11 +1082,10 @@ set. Ignoring max smbd restriction.\n"));
}
/****************************************************************************
- Process an smb from the client - split out from the smbd_process() code so
- it can be used by the oplock break code.
+ Process an smb from the client
****************************************************************************/
-void process_smb(char *inbuf, char *outbuf)
+static void process_smb(char *inbuf, char *outbuf)
{
static int trans_num;
int msg_type = CVAL(inbuf,0);
@@ -1186,7 +1105,7 @@ void process_smb(char *inbuf, char *outbuf)
static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
(void)send_smb(smbd_server_fd(),(char *)buf);
- exit_server("connection denied");
+ exit_server_cleanly("connection denied");
}
}
@@ -1208,7 +1127,7 @@ void process_smb(char *inbuf, char *outbuf)
DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
nread, smb_len(outbuf)));
} else if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("process_smb: send_smb failed.");
+ exit_server_cleanly("process_smb: send_smb failed.");
}
}
trans_num++;
@@ -1246,20 +1165,16 @@ void remove_from_common_flags2(uint32 v)
void construct_reply_common(char *inbuf,char *outbuf)
{
- memset(outbuf,'\0',smb_size);
-
- set_message(outbuf,0,0,True);
- SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
+ set_message(outbuf,0,0,False);
- memcpy(outbuf+4,inbuf+4,4);
- SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
- SCVAL(outbuf,smb_reh,0);
+ SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
+ SIVAL(outbuf,smb_rcls,0);
SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
SSVAL(outbuf,smb_flg2,
(SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
common_flags2);
+ memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
- SSVAL(outbuf,smb_err,SMB_SUCCESS);
SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
@@ -1715,8 +1630,8 @@ void smbd_process(void)
errno = 0;
/* free up temporary memory */
- lp_talloc_free();
- main_loop_talloc_free();
+ lp_TALLOC_FREE();
+ main_loop_TALLOC_FREE();
/* Did someone ask for immediate checks on things like blocking locks ? */
if (select_timeout == 0) {
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index fc31abecd2a..0524078310f 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -269,10 +269,13 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
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;
@@ -374,10 +377,13 @@ NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
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;
@@ -842,7 +848,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return(UNIXERROR(ERRDOS,ERRbadpath));
}
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
END_PROFILE(SMBchkpth);
@@ -988,7 +994,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
@@ -1386,7 +1392,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
if (fattr & aDIR) {
DEBUG(3,("attempt to open a directory %s\n",fname));
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBopen);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
@@ -1510,13 +1516,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
if (retval < 0) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBwrite);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
@@ -1526,7 +1532,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
fattr = dos_mode(conn,fname,&sbuf);
mtime = sbuf.st_mtime;
if (fattr & aDIR) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
END_PROFILE(SMBopenX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
@@ -1845,7 +1851,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
set_saved_ntstatus(NT_STATUS_OK);
return NT_STATUS_ACCESS_DENIED;
}
- close_file(fsp,False);
+ close_file(fsp,NORMAL_CLOSE);
return NT_STATUS_OK;
}
@@ -1888,7 +1894,19 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
return NT_STATUS_OBJECT_NAME_INVALID;
#endif /* JRATEST */
- if (!lp_delete_readonly(SNUM(conn))) {
+ /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
+
+ On a Windows share, a file with read-only dosmode can be opened with
+ DELETE_ACCESS. But on a Samba share (delete readonly = no), it
+ fails with NT_STATUS_CANNOT_DELETE error.
+
+ This semantic causes a problem that a user can not
+ rename a file with read-only dosmode on a Samba share
+ from a Windows command prompt (i.e. cmd.exe, but can rename
+ from Windows Explorer).
+ */
+
+ if (!check_is_at_open && !lp_delete_readonly(SNUM(conn))) {
if (fattr & aRONLY) {
return NT_STATUS_CANNOT_DELETE;
}
@@ -1926,7 +1944,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
set_saved_ntstatus(NT_STATUS_OK);
return NT_STATUS_ACCESS_DENIED;
}
- close_file(fsp,False);
+ close_file(fsp,NORMAL_CLOSE);
}
return NT_STATUS_OK;
}
@@ -2095,7 +2113,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
*/
process_pending_change_notify_queue((time_t)0);
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBunlink);
return outsize;
@@ -2164,7 +2182,8 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
* reply_readbraw has already checked the length.
*/
- if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
+ if ( (chain_size == 0) && (nread > 0) &&
+ (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
DATA_BLOB header;
_smb_setlen(outbuf,nread);
@@ -2306,7 +2325,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,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (!is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
SMB_STRUCT_STAT st;
SMB_OFF_T size = 0;
@@ -2377,8 +2396,13 @@ 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, conn, SVAL(inbuf,smb_pid),
- (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
+ status = do_lock_spin(fsp,
+ SVAL(inbuf,smb_pid),
+ (SMB_BIG_UINT)numtoread,
+ (SMB_BIG_UINT)startpos,
+ WRITE_LOCK,
+ WINDOWS_LOCK,
+ &my_lock_ctx);
if (NT_STATUS_V(status)) {
#if 0
@@ -2394,8 +2418,15 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
- (SMB_BIG_UINT)numtoread)) {
+ 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;
}
@@ -2473,7 +2504,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
data = smb_buf(outbuf) + 3;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBread);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -2517,8 +2548,8 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
* on a train in Germany :-). JRA.
*/
- if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
- (lp_write_cache_size(SNUM(conn)) == 0) ) {
+ if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
+ lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
SMB_STRUCT_STAT sbuf;
DATA_BLOB header;
@@ -2681,7 +2712,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
- if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBreadX);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -2744,7 +2775,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,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwritebraw);
return(ERROR_DOS(ERRDOS,ERRlock));
}
@@ -2865,7 +2896,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,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteunlock);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -2887,8 +2918,12 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
}
if (numtowrite) {
- status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
- (SMB_BIG_UINT)startpos);
+ status = do_unlock(fsp,
+ SVAL(inbuf,smb_pid),
+ (SMB_BIG_UINT)numtowrite,
+ (SMB_BIG_UINT)startpos,
+ WINDOWS_LOCK);
+
if (NT_STATUS_V(status)) {
END_PROFILE(SMBwriteunlock);
return ERROR_NT(status);
@@ -2938,7 +2973,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,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwrite);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -3053,7 +3088,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
#endif /* LARGE_SMB_OFF_T */
}
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteX);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -3179,7 +3214,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,False);
uint16 fnum = SVAL(inbuf,smb_vwv0);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBflush);
@@ -3208,9 +3243,9 @@ int reply_exit(connection_struct *conn,
int outsize;
START_PROFILE(SMBexit);
- file_close_pid(SVAL(inbuf,smb_pid));
+ file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("exit\n"));
@@ -3231,7 +3266,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
/* If it's an IPC, pass off to the pipe handler. */
if (IS_IPC(conn)) {
@@ -3255,7 +3290,7 @@ 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,True);
+ close_file(fsp,NORMAL_CLOSE);
} else {
/*
* Close ordinary file.
@@ -3283,7 +3318,7 @@ 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,True)) != 0) {
+ if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
errno = close_err;
END_PROFILE(SMBclose);
return (UNIXERROR(ERRHRD,ERRgeneral));
@@ -3327,7 +3362,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,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (numtowrite && is_locked(fsp,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteclose);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -3344,7 +3379,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,True);
+ close_err = close_file(fsp,NORMAL_CLOSE);
}
DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
@@ -3379,7 +3414,7 @@ int reply_writeclose(connection_struct *conn,
int reply_lock(connection_struct *conn,
char *inbuf,char *outbuf, int length, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,False);
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3397,7 +3432,13 @@ 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, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
+ status = do_lock_spin(fsp,
+ SVAL(inbuf,smb_pid),
+ count,
+ offset,
+ WRITE_LOCK,
+ WINDOWS_LOCK,
+ &my_lock_ctx);
if (NT_STATUS_V(status)) {
#if 0
/* Tests using Samba4 against W2K show this call never creates a blocking lock. */
@@ -3407,7 +3448,14 @@ int reply_lock(connection_struct *conn,
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
+ 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;
}
@@ -3428,7 +3476,7 @@ int reply_lock(connection_struct *conn,
int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,False);
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3439,7 +3487,12 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
- status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
+ status = do_unlock(fsp,
+ SVAL(inbuf,smb_pid),
+ count,
+ offset,
+ WINDOWS_LOCK);
+
if (NT_STATUS_V(status)) {
END_PROFILE(SMBunlock);
return ERROR_NT(status);
@@ -3462,7 +3515,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
int reply_tdis(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,False);
uint16 vuid;
START_PROFILE(SMBtdis);
@@ -3569,7 +3622,7 @@ int reply_printopen(connection_struct *conn,
int reply_printclose(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,False);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
int close_err = 0;
START_PROFILE(SMBsplclose);
@@ -3584,7 +3637,7 @@ int reply_printclose(connection_struct *conn,
DEBUG(3,("printclose fd=%d fnum=%d\n",
fsp->fh->fd,fsp->fnum));
- close_err = close_file(fsp,True);
+ close_err = close_file(fsp,NORMAL_CLOSE);
if(close_err != 0) {
errno = close_err;
@@ -3674,7 +3727,7 @@ int reply_printqueue(connection_struct *conn,
int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int numtowrite;
- int outsize = set_message(outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,False);
char *data;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3799,7 +3852,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
change_owner_to_parent(conn, NULL, directory, &sbuf);
}
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
@@ -3987,7 +4040,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
}
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "rmdir %s\n", directory ) );
@@ -4086,12 +4139,20 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
asynchronously.
****************************************************************************/
-static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
+static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
+ SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
{
files_struct *fsp;
BOOL did_rename = False;
for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
+ /* fsp_name is a relative path under the fsp. To change this for other
+ sharepaths we need to manipulate relative paths. */
+ /* TODO - create the absolute path and manipulate the newname
+ relative to the sharepath. */
+ if (fsp->conn != conn) {
+ continue;
+ }
DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
fsp->fsp_name, newname ));
@@ -4099,9 +4160,13 @@ static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T
did_rename = True;
}
- if (!did_rename)
+ if (!did_rename) {
DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
(unsigned int)dev, (double)inode, newname ));
+ }
+
+ /* Send messages to all smbd's (not ourself) that the name has changed. */
+ rename_share_filename(lck, conn->connectpath, newname);
}
/****************************************************************************
@@ -4145,6 +4210,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
NTSTATUS error = 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);
@@ -4232,17 +4298,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
return NT_STATUS_ACCESS_DENIED;
}
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+
if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
fsp->fsp_name,newname));
- rename_open_files(conn, fsp->dev, fsp->inode, newname);
+ rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
+ TALLOC_FREE(lck);
return NT_STATUS_OK;
}
- if (errno == ENOTDIR || errno == EISDIR)
+ TALLOC_FREE(lck);
+
+ if (errno == ENOTDIR || errno == EISDIR) {
error = NT_STATUS_OBJECT_NAME_COLLISION;
- else
+ } else {
error = map_nt_error_from_unix(errno);
+ }
DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
nt_errstr(error), fsp->fsp_name,newname));
@@ -4269,6 +4341,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, ui
BOOL rc = True;
BOOL rcdest = True;
SMB_STRUCT_STAT sbuf1, sbuf2;
+ struct share_mode_lock *lck = NULL;
*directory = *mask = 0;
@@ -4439,7 +4512,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
*/
if (strcsequal(directory, newname)) {
- rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, 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));
return NT_STATUS_OK;
}
@@ -4454,13 +4527,17 @@ 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);
+
if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
directory,newname));
- rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+ rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
+ TALLOC_FREE(lck);
return NT_STATUS_OK;
}
+ TALLOC_FREE(lck);
if (errno == ENOTDIR || errno == EISDIR)
error = NT_STATUS_OBJECT_NAME_COLLISION;
else
@@ -4538,7 +4615,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
}
if (strcsequal(fname,destname)) {
- rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+ 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;
@@ -4556,11 +4633,14 @@ 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);
+
if (!SMB_VFS_RENAME(conn,fname,destname)) {
- rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+ 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));
}
CloseDir(dir_hnd);
@@ -4632,7 +4712,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
* update after a rename..
*/
process_pending_change_notify_queue((time_t)0);
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBmv);
return(outsize);
@@ -4707,7 +4787,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
NULL);
if (!fsp2) {
- close_file(fsp1,False);
+ close_file(fsp1,ERROR_CLOSE);
return(False);
}
@@ -4726,7 +4806,7 @@ BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
}
- close_file(fsp1,False);
+ close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
@@ -4737,7 +4817,7 @@ 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,False);
+ *err_ret = close_file(fsp2,NORMAL_CLOSE);
return(ret == (SMB_OFF_T)src_sbuf.st_size);
}
@@ -4955,7 +5035,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
} else {
ok = vfs_directory_exist(conn,newdir,NULL);
if (ok)
- string_set(&conn->connectpath,newdir);
+ set_conn_connectpath(conn,newdir);
}
if (!ok) {
@@ -4963,7 +5043,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_DOS(ERRDOS,ERRbadpath);
}
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
DEBUG(3,("setdir %s\n", newdir));
@@ -5141,7 +5221,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_DOS(ERRDOS, ERRnoatomiclocks);
+ return ERROR_FORCE_DOS(ERRDOS, ERRnoatomiclocks);
}
if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
@@ -5167,7 +5247,14 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
*/
if (fsp->oplock_type == 0) {
- DEBUG(0,("reply_lockingX: Error : oplock break from "
+
+ /* The Samba4 nbench simulator doesn't understand
+ the difference between break to level2 and break
+ to none from level2 - it sends oplock break
+ replies in both cases. Don't keep logging an error
+ message here - just ignore it. JRA. */
+
+ DEBUG(5,("reply_lockingX: Error : oplock break from "
"client for fnum = %d (oplock=%d) and no "
"oplock granted on this file (%s).\n",
fsp->fnum, fsp->oplock_type, fsp->fsp_name));
@@ -5239,7 +5326,12 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
"pid %u, file %s\n", (double)offset, (double)count,
(unsigned int)lock_pid, fsp->fsp_name ));
- status = do_unlock(fsp,conn,lock_pid,count,offset);
+ status = do_unlock(fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
+
if (NT_STATUS_V(status)) {
END_PROFILE(SMBlockingX);
return ERROR_NT(status);
@@ -5257,6 +5349,7 @@ 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);
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);
@@ -5274,9 +5367,14 @@ 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,conn,lock_pid, count,offset,
- ((locktype & 1) ? READ_LOCK:WRITE_LOCK),
- &my_lock_ctx);
+ status = do_lock_spin(fsp,
+ lock_pid,
+ count,
+ offset,
+ lock_type,
+ WINDOWS_LOCK,
+ &my_lock_ctx);
+
if (NT_STATUS_V(status)) {
/*
* Interesting fact found by IFSTEST /t
@@ -5294,8 +5392,13 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
* onto the blocking lock queue.
*/
if(push_blocking_lock_request(inbuf, length,
- lock_timeout, i,
- lock_pid, offset,
+ fsp,
+ lock_timeout,
+ i,
+ lock_pid,
+ lock_type,
+ WINDOWS_LOCK,
+ offset,
count)) {
END_PROFILE(SMBlockingX);
return -1;
@@ -5328,7 +5431,11 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- do_unlock(fsp,conn,lock_pid,count,offset);
+ do_unlock(fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
}
END_PROFILE(SMBlockingX);
return ERROR_NT(status);
@@ -5390,7 +5497,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
tcount = maxcount;
total_read = 0;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBreadBmpx);
return ERROR_DOS(ERRDOS,ERRlock);
}
@@ -5435,7 +5542,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBsetattrE);
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
if(!fsp || (fsp->conn != conn)) {
END_PROFILE(SMBsetattrE);
@@ -5522,7 +5629,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,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
+ if (is_locked(fsp,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
END_PROFILE(SMBwriteBmpx);
return(ERROR_DOS(ERRDOS,ERRlock));
}
diff --git a/source/smbd/sec_ctx.c b/source/smbd/sec_ctx.c
index a5411b94a17..a30123bfa79 100644
--- a/source/smbd/sec_ctx.c
+++ b/source/smbd/sec_ctx.c
@@ -23,10 +23,7 @@
extern struct current_user current_user;
struct sec_ctx {
- uid_t uid;
- uid_t gid;
- int ngroups;
- gid_t *groups;
+ UNIX_USER_TOKEN ut;
NT_USER_TOKEN *token;
};
@@ -132,7 +129,7 @@ static void gain_root(void)
Get the list of current groups.
****************************************************************************/
-int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
+static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
{
int i;
gid_t grp;
@@ -183,51 +180,6 @@ fail:
}
/****************************************************************************
- Initialize the groups a user belongs to.
-****************************************************************************/
-
-BOOL initialise_groups(char *user, uid_t uid, gid_t gid)
-{
- struct sec_ctx *prev_ctx_p;
- BOOL result = True;
-
- if (non_root_mode()) {
- return True;
- }
-
- become_root();
-
- /* Call initgroups() to get user groups */
-
- if (winbind_initgroups(user,gid) == -1) {
- DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) ));
- if (getuid() == 0) {
- if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) {
- DEBUG(0,("This is probably a problem with the account %s\n", user));
- }
- }
- result = False;
- goto done;
- }
-
- /* Store groups in previous user's security context. This will
- always work as the become_root() call increments the stack
- pointer. */
-
- prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx - 1];
-
- SAFE_FREE(prev_ctx_p->groups);
- prev_ctx_p->ngroups = 0;
-
- get_current_groups(gid, &prev_ctx_p->ngroups, &prev_ctx_p->groups);
-
- done:
- unbecome_root();
-
- return result;
-}
-
-/****************************************************************************
Create a new security context on the stack. It is the same as the old
one. User changes are done using the set_sec_ctx() function.
****************************************************************************/
@@ -249,26 +201,27 @@ BOOL push_sec_ctx(void)
ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
- ctx_p->uid = geteuid();
- ctx_p->gid = getegid();
+ ctx_p->ut.uid = geteuid();
+ ctx_p->ut.gid = getegid();
DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n",
- (unsigned int)ctx_p->uid, (unsigned int)ctx_p->gid, sec_ctx_stack_ndx ));
+ (unsigned int)ctx_p->ut.uid, (unsigned int)ctx_p->ut.gid, sec_ctx_stack_ndx ));
- ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token);
+ ctx_p->token = dup_nt_token(NULL,
+ sec_ctx_stack[sec_ctx_stack_ndx-1].token);
- ctx_p->ngroups = sys_getgroups(0, NULL);
+ ctx_p->ut.ngroups = sys_getgroups(0, NULL);
- if (ctx_p->ngroups != 0) {
- if (!(ctx_p->groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ngroups))) {
+ if (ctx_p->ut.ngroups != 0) {
+ if (!(ctx_p->ut.groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ut.ngroups))) {
DEBUG(0, ("Out of memory in push_sec_ctx()\n"));
- delete_nt_token(&ctx_p->token);
+ TALLOC_FREE(ctx_p->token);
return False;
}
- sys_getgroups(ctx_p->ngroups, ctx_p->groups);
+ sys_getgroups(ctx_p->ut.ngroups, ctx_p->ut.groups);
} else {
- ctx_p->groups = NULL;
+ ctx_p->ut.groups = NULL;
}
return True;
@@ -296,28 +249,28 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
sys_setgroups(ngroups, groups);
#endif
- ctx_p->ngroups = ngroups;
+ ctx_p->ut.ngroups = ngroups;
- SAFE_FREE(ctx_p->groups);
+ SAFE_FREE(ctx_p->ut.groups);
if (token && (token == ctx_p->token))
smb_panic("DUPLICATE_TOKEN");
- delete_nt_token(&ctx_p->token);
+ TALLOC_FREE(ctx_p->token);
- ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups);
- ctx_p->token = dup_nt_token(token);
+ ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups);
+ ctx_p->token = dup_nt_token(NULL, token);
become_id(uid, gid);
- ctx_p->uid = uid;
- ctx_p->gid = gid;
+ ctx_p->ut.uid = uid;
+ ctx_p->ut.gid = gid;
/* Update current_user stuff */
- current_user.uid = uid;
- current_user.gid = gid;
- current_user.ngroups = ngroups;
- current_user.groups = groups;
+ current_user.ut.uid = uid;
+ current_user.ut.gid = gid;
+ current_user.ut.ngroups = ngroups;
+ current_user.ut.groups = groups;
current_user.nt_user_token = ctx_p->token;
}
@@ -352,13 +305,13 @@ BOOL pop_sec_ctx(void)
/* Clear previous user info */
- ctx_p->uid = (uid_t)-1;
- ctx_p->gid = (gid_t)-1;
+ ctx_p->ut.uid = (uid_t)-1;
+ ctx_p->ut.gid = (gid_t)-1;
- SAFE_FREE(ctx_p->groups);
- ctx_p->ngroups = 0;
+ SAFE_FREE(ctx_p->ut.groups);
+ ctx_p->ut.ngroups = 0;
- delete_nt_token(&ctx_p->token);
+ TALLOC_FREE(ctx_p->token);
/* Pop back previous user */
@@ -369,17 +322,17 @@ BOOL pop_sec_ctx(void)
prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
#ifdef HAVE_SETGROUPS
- sys_setgroups(prev_ctx_p->ngroups, prev_ctx_p->groups);
+ sys_setgroups(prev_ctx_p->ut.ngroups, prev_ctx_p->ut.groups);
#endif
- become_id(prev_ctx_p->uid, prev_ctx_p->gid);
+ become_id(prev_ctx_p->ut.uid, prev_ctx_p->ut.gid);
/* Update current_user stuff */
- current_user.uid = prev_ctx_p->uid;
- current_user.gid = prev_ctx_p->gid;
- current_user.ngroups = prev_ctx_p->ngroups;
- current_user.groups = prev_ctx_p->groups;
+ current_user.ut.uid = prev_ctx_p->ut.uid;
+ current_user.ut.gid = prev_ctx_p->ut.gid;
+ current_user.ut.ngroups = prev_ctx_p->ut.ngroups;
+ current_user.ut.groups = prev_ctx_p->ut.groups;
current_user.nt_user_token = prev_ctx_p->token;
DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
@@ -400,26 +353,26 @@ void init_sec_ctx(void)
memset(sec_ctx_stack, 0, sizeof(struct sec_ctx) * MAX_SEC_CTX_DEPTH);
for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) {
- sec_ctx_stack[i].uid = (uid_t)-1;
- sec_ctx_stack[i].gid = (gid_t)-1;
+ sec_ctx_stack[i].ut.uid = (uid_t)-1;
+ sec_ctx_stack[i].ut.gid = (gid_t)-1;
}
/* Initialise first level of stack. It is the current context */
ctx_p = &sec_ctx_stack[0];
- ctx_p->uid = geteuid();
- ctx_p->gid = getegid();
+ ctx_p->ut.uid = geteuid();
+ ctx_p->ut.gid = getegid();
- get_current_groups(ctx_p->gid, &ctx_p->ngroups, &ctx_p->groups);
+ get_current_groups(ctx_p->ut.gid, &ctx_p->ut.ngroups, &ctx_p->ut.groups);
ctx_p->token = NULL; /* Maps to guest user. */
/* Initialise current_user global */
- current_user.uid = ctx_p->uid;
- current_user.gid = ctx_p->gid;
- current_user.ngroups = ctx_p->ngroups;
- current_user.groups = ctx_p->groups;
+ current_user.ut.uid = ctx_p->ut.uid;
+ current_user.ut.gid = ctx_p->ut.gid;
+ current_user.ut.ngroups = ctx_p->ut.ngroups;
+ current_user.ut.groups = ctx_p->ut.groups;
/* The conn and vuid are usually taken care of by other modules.
We initialise them here. */
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 4b52b8eae0d..a1466c408d2 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -22,10 +22,6 @@
#include "includes.h"
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
-
static int am_parent = 1;
/* the last message the was processed */
@@ -62,6 +58,18 @@ static void smbd_set_server_fd(int fd)
client_setfd(fd);
}
+/*******************************************************************
+ 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)
+{
+ DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
+ reload_services(False);
+}
+
+
/****************************************************************************
Terminate signal.
****************************************************************************/
@@ -144,9 +152,41 @@ static BOOL open_sockets_inetd(void)
static void msg_exit_server(int msg_type, struct process_id src,
void *buf, size_t len)
{
- exit_server("Got a SHUTDOWN message");
+ DEBUG(3, ("got a SHUTDOWN message\n"));
+ exit_server_cleanly(NULL);
}
+#ifdef DEVELOPER
+static void msg_inject_fault(int msg_type, struct process_id src,
+ void *buf, size_t len)
+{
+ int sig;
+
+ if (len != sizeof(int)) {
+
+ DEBUG(0, ("Process %llu sent bogus signal injection request\n",
+ (unsigned long long)src.pid));
+ return;
+ }
+
+ sig = *(int *)buf;
+ if (sig == -1) {
+ exit_server("internal error injected");
+ return;
+ }
+
+#if HAVE_STRSIGNAL
+ DEBUG(0, ("Process %llu requested injection of signal %d (%s)\n",
+ (unsigned long long)src.pid, sig, strsignal(sig)));
+#else
+ DEBUG(0, ("Process %llu requested injection of signal %d\n",
+ (unsigned long long)src.pid, sig));
+#endif
+
+ kill(sys_getpid(), sig);
+}
+#endif /* DEVELOPER */
+
/****************************************************************************
Have we reached the process limit ?
@@ -330,6 +370,12 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
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);
+
+#ifdef DEVELOPER
+ message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault);
+#endif
/* now accept incoming connections - forking a new process
for each incoming connection */
@@ -339,7 +385,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
int num;
/* Free up temporary memory from the main smbd. */
- lp_talloc_free();
+ lp_TALLOC_FREE();
/* Ensure we respond to PING and DEBUG messages from the main smbd. */
message_dispatch();
@@ -351,7 +397,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
if (num == -1 && errno == EINTR) {
if (got_sig_term) {
- exit_server("Caught TERM signal");
+ exit_server_cleanly(NULL);
}
/* check for sighup processing */
@@ -428,7 +474,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
set_need_random_reseed();
/* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */
- if (tdb_reopen_all() == -1) {
+ if (tdb_reopen_all(1) == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
smb_panic("tdb_reopen_all failed.");
}
@@ -528,7 +574,7 @@ BOOL reload_services(BOOL test)
lp_killunused(conn_snum_used);
- ret = lp_load(dyn_CONFIGFILE, False, False, True);
+ ret = lp_load(dyn_CONFIGFILE, False, False, True, True);
reload_printers();
@@ -554,55 +600,18 @@ BOOL reload_services(BOOL test)
return(ret);
}
-
-#if DUMP_CORE
-/*******************************************************************
-prepare to dump a core file - carefully!
-********************************************************************/
-static BOOL dump_core(void)
-{
- char *p;
- pstring dname;
-
- pstrcpy(dname,lp_logfile());
- if ((p=strrchr_m(dname,'/'))) *p=0;
- pstrcat(dname,"/corefiles");
- mkdir(dname,0700);
- sys_chown(dname,getuid(),getgid());
- chmod(dname,0700);
- if (chdir(dname)) return(False);
- umask(~(0700));
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
- {
- struct rlimit rlp;
- getrlimit(RLIMIT_CORE, &rlp);
- rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
- setrlimit(RLIMIT_CORE, &rlp);
- getrlimit(RLIMIT_CORE, &rlp);
- DEBUG(3,("Core limits now %d %d\n",
- (int)rlp.rlim_cur,(int)rlp.rlim_max));
- }
-#endif
-#endif
-
-
- DEBUG(0,("Dumping core in %s\n", dname));
- /* Ensure we don't have a signal handler for abort. */
-#ifdef SIGABRT
- CatchSignal(SIGABRT,SIGNAL_CAST SIG_DFL);
-#endif
- abort();
- return(True);
-}
-#endif
-
/****************************************************************************
Exit the server.
****************************************************************************/
-void exit_server(const char *reason)
+/* Reasons for shutting down a server process. */
+enum server_exit_reason { SERVER_EXIT_NORMAL, SERVER_EXIT_ABNORMAL };
+
+static void exit_server_common(enum server_exit_reason how,
+ const char *const reason) NORETURN_ATTRIBUTE;
+
+static void exit_server_common(enum server_exit_reason how,
+ const char *const reason)
{
static int firsttime=1;
@@ -611,7 +620,6 @@ void exit_server(const char *reason)
firsttime = 0;
change_to_root_user();
- DEBUG(2,("Closing connections\n"));
if (negprot_global_auth_context) {
(negprot_global_auth_context->free)(&negprot_global_auth_context);
@@ -635,27 +643,54 @@ void exit_server(const char *reason)
}
#endif
- if (!reason) {
+ locking_end();
+ printing_end();
+
+ if (how != SERVER_EXIT_NORMAL) {
int oldlevel = DEBUGLEVEL;
char *last_inbuf = get_InBuffer();
+
DEBUGLEVEL = 10;
- DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
- if (last_inbuf)
+
+ DEBUGSEP(0);
+ DEBUG(0,("Abnormal server exit: %s\n",
+ reason ? reason : "no explanation provided"));
+ DEBUGSEP(0);
+
+ log_stack_trace();
+ if (last_inbuf) {
+ DEBUG(0,("Last message was %s\n", LAST_MESSAGE()));
show_msg(last_inbuf);
+ }
+
DEBUGLEVEL = oldlevel;
- DEBUG(0,("===============================================================\n"));
#if DUMP_CORE
- if (dump_core()) return;
+ dump_core();
#endif
- }
- locking_end();
- printing_end();
+ } else {
+ DEBUG(3,("Server exit (%s)\n",
+ (reason ? reason : "normal exit")));
+ }
- DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
exit(0);
}
+void exit_server(const char *const explanation)
+{
+ exit_server_common(SERVER_EXIT_ABNORMAL, explanation);
+}
+
+void exit_server_cleanly(const char *const explanation)
+{
+ exit_server_common(SERVER_EXIT_NORMAL, explanation);
+}
+
+void exit_server_fault(void)
+{
+ exit_server("critical server fault");
+}
+
/****************************************************************************
Initialise connect, service and file structs.
****************************************************************************/
@@ -696,10 +731,12 @@ void build_options(BOOL screen);
int main(int argc,const char *argv[])
{
+ extern BOOL in_server;
/* shall I run as a daemon */
static BOOL is_daemon = False;
static BOOL interactive = False;
static BOOL Fork = True;
+ static BOOL no_process_group = False;
static BOOL log_stdout = False;
static char *ports = NULL;
int opt;
@@ -710,6 +747,7 @@ void build_options(BOOL screen);
{"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" },
{"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"},
{"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
+ {"no-process-group", 0, POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
{"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" },
{"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"},
@@ -717,6 +755,8 @@ void build_options(BOOL screen);
{ NULL }
};
+ in_server = True;
+
load_case_tables();
#ifdef HAVE_SET_AUTH_PARAMETERS
@@ -771,7 +811,9 @@ void build_options(BOOL screen);
gain_root_privilege();
gain_root_group_privilege();
- fault_setup((void (*)(void *))exit_server);
+ fault_setup((void (*)(void *))exit_server_fault);
+ dump_core_setup("smbd");
+
CatchSignal(SIGTERM , SIGNAL_CAST sig_term);
CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
@@ -825,11 +867,6 @@ void build_options(BOOL screen);
init_structs();
- if (!init_guest_info()) {
- DEBUG(0,("ERROR: failed to setup guest info.\n"));
- return -1;
- }
-
#ifdef WITH_PROFILE
if (!profile_setup(False)) {
DEBUG(0,("ERROR: failed to setup profiling\n"));
@@ -853,7 +890,7 @@ void build_options(BOOL screen);
if (is_daemon && !interactive) {
DEBUG( 3, ( "Becoming a daemon.\n" ) );
- become_daemon(Fork);
+ become_daemon(Fork, no_process_group);
}
#if HAVE_SETPGID
@@ -861,7 +898,7 @@ void build_options(BOOL screen);
* If we're interactive we want to set our own process group for
* signal management.
*/
- if (interactive)
+ if (interactive && !no_process_group)
setpgid( (pid_t)0, (pid_t)0);
#endif
@@ -875,6 +912,28 @@ 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);
+ }
+
+ if(!get_global_sam_sid()) {
+ DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
+ exit(1);
+ }
+
if (!session_init())
exit(1);
@@ -884,9 +943,6 @@ void build_options(BOOL screen);
if (!locking_init(0))
exit(1);
- if (!share_info_db_init())
- exit(1);
-
namecache_enable();
if (!init_registry())
@@ -900,6 +956,11 @@ void build_options(BOOL screen);
if (!print_backend_init())
exit(1);
+ if (!init_guest_info()) {
+ DEBUG(0,("ERROR: failed to setup guest info.\n"));
+ return -1;
+ }
+
/* Setup the main smbd so that we can get messages. */
/* don't worry about general printing messages here */
@@ -913,6 +974,12 @@ void build_options(BOOL screen);
if ( is_daemon && !interactive )
start_background_queue();
+ /* Always attempt to initialize DMAPI. We will only use it later if
+ * lp_dmapi_support is set on the share, but we need a single global
+ * session to work with.
+ */
+ dmapi_init_session();
+
if (!open_sockets_smbd(is_daemon, interactive, ports))
exit(1);
@@ -920,25 +987,6 @@ void build_options(BOOL screen);
* everything after this point is run after the fork()
*/
-#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
- /* On Linux we lose the ability to dump core when we change our user
- * ID. We know how to dump core safely, so let's make sure we have our
- * dumpable flag set.
- */
- prctl(PR_SET_DUMPABLE, 1);
-#endif
-
- /* 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);
-
- if(!get_global_sam_sid()) {
- DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
- exit(1);
- }
-
static_init_rpc;
init_modules();
@@ -974,9 +1022,9 @@ void build_options(BOOL screen);
message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
smbd_process();
-
+
namecache_shutdown();
- exit_server("normal exit");
+ exit_server_cleanly(NULL);
return(0);
}
diff --git a/source/smbd/service.c b/source/smbd/service.c
index a7e6a1b6281..ba87d0743da 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -20,10 +20,111 @@
#include "includes.h"
-extern struct timeval smb_last_time;
extern userdom_struct current_user_info;
/****************************************************************************
+ Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
+ absolute path stating in / and not ending in /.
+ Observent people will notice a similarity between this and check_path_syntax :-).
+****************************************************************************/
+
+void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
+{
+ pstring destname;
+ char *d = destname;
+ const char *s = connectpath;
+ BOOL start_of_name_component = True;
+
+ *d++ = '/'; /* Always start with root. */
+
+ while (*s) {
+ if (*s == '/') {
+ /* Eat multiple '/' */
+ while (*s == '/') {
+ s++;
+ }
+ if ((d > destname + 1) && (*s != '\0')) {
+ *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" ! */
+
+ /* Go past the ../ or .. */
+ if (s[2] == '/') {
+ s += 3;
+ } else {
+ s += 2; /* Go past the .. */
+ }
+
+ /* 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) {
+ *d++ = '/'; /* Can't delete root */
+ continue;
+ }
+ /* Go back one level... */
+ /* Decrement d first as d points to the *next* char to write into. */
+ for (d--; d > destname; d--) {
+ if (*d == '/') {
+ break;
+ }
+ }
+ /* We're still at the start of a name component, just the previous one. */
+ continue;
+ } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
+ /* Component of pathname can't be "." only - skip the '.' . */
+ if (s[1] == '/') {
+ s += 2;
+ } else {
+ s++;
+ }
+ continue;
+ }
+ }
+
+ if (!(*s & 0x80)) {
+ *d++ = *s++;
+ } 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:
+ break;
+ }
+ }
+ start_of_name_component = False;
+ }
+ *d = '\0';
+
+ /* And must not end in '/' */
+ if (d > destname + 1 && (*(d-1) == '/')) {
+ *(d-1) = '\0';
+ }
+
+ DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
+ lp_servicename(SNUM(conn)), destname ));
+
+ string_set(&conn->connectpath, destname);
+}
+
+/****************************************************************************
Load parameters specific to a connection/service.
****************************************************************************/
@@ -38,7 +139,7 @@ BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
return(False);
}
- conn->lastused = smb_last_time.tv_sec;
+ conn->lastused_count++;
snum = SNUM(conn);
@@ -197,6 +298,13 @@ 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));
@@ -257,6 +365,131 @@ 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)
+{
+ TALLOC_CTX *mem_ctx;
+ char *fuser, *found_username;
+ NTSTATUS result;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ 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);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ talloc_steal(NULL, *token);
+ fstrcpy(username, found_username);
+
+ result = NT_STATUS_OK;
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
+}
+
+/*
+ * Go through lookup_name etc to find the force'd group.
+ *
+ * Create a new token from src_token, replacing the primary group sid with the
+ * one found.
+ */
+
+static NTSTATUS find_forced_group(BOOL force_user,
+ int snum, const char *username,
+ DOM_SID *pgroup_sid,
+ gid_t *pgid)
+{
+ NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
+ TALLOC_CTX *mem_ctx;
+ DOM_SID group_sid;
+ enum SID_NAME_USE type;
+ char *groupname;
+ BOOL user_must_be_member = False;
+ gid_t gid;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
+ if (groupname == NULL) {
+ DEBUG(1, ("talloc_strdup failed\n"));
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if (groupname[0] == '+') {
+ user_must_be_member = True;
+ groupname += 1;
+ }
+
+ groupname = talloc_string_sub(mem_ctx, groupname,
+ "%S", lp_servicename(snum));
+
+ if (!lookup_name(mem_ctx, groupname,
+ LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
+ NULL, NULL, &group_sid, &type)) {
+ DEBUG(10, ("lookup_name(%s) failed\n",
+ groupname));
+ goto done;
+ }
+
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP)) {
+ DEBUG(10, ("%s is a %s, not a group\n", groupname,
+ sid_type_lookup(type)));
+ goto done;
+ }
+
+ if (!sid_to_gid(&group_sid, &gid)) {
+ DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
+ sid_string_static(&group_sid), groupname));
+ goto done;
+ }
+
+ /*
+ * If the user has been forced and the forced group starts with a '+',
+ * then we only set the group to be the forced group if the forced
+ * user is a member of that group. Otherwise, the meaning of the '+'
+ * would be ignored.
+ */
+
+ if (force_user && user_must_be_member) {
+ if (user_in_group_sid(username, &group_sid)) {
+ sid_copy(pgroup_sid, &group_sid);
+ *pgid = gid;
+ DEBUG(3,("Forced group %s for member %s\n",
+ groupname, username));
+ }
+ } else {
+ sid_copy(pgroup_sid, &group_sid);
+ *pgid = gid;
+ DEBUG(3,("Forced group %s\n", groupname));
+ }
+
+ result = NT_STATUS_OK;
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
+}
+
/****************************************************************************
Make a connection, given the snum to connect to, and the vuser of the
connecting user if appropriate.
@@ -293,7 +526,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if (lp_guest_only(snum)) {
const char *guestname = lp_guestaccount();
guest = True;
- pass = getpwnam_alloc(guestname);
+ pass = getpwnam_alloc(NULL, guestname);
if (!pass) {
DEBUG(0,("make_connection_snum: Invalid guest "
"account %s??\n",guestname));
@@ -306,7 +539,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->uid = pass->pw_uid;
conn->gid = pass->pw_gid;
string_set(&conn->user,pass->pw_name);
- passwd_free(&pass);
+ TALLOC_FREE(pass);
DEBUG(3,("Guest only user %s\n",user));
} else if (vuser) {
if (vuser->guest) {
@@ -319,8 +552,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
return NULL;
}
} else {
- if (!user_ok(vuser->user.unix_name, snum,
- vuser->groups, vuser->n_groups)) {
+ if (!user_ok_token(vuser->user.unix_name,
+ vuser->nt_user_token, snum)) {
DEBUG(2, ("user '%s' (from session setup) not "
"permitted to access this share "
"(%s)\n", vuser->user.unix_name,
@@ -367,7 +600,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
safe_strcpy(conn->client_address, client_addr(),
sizeof(conn->client_address)-1);
conn->num_files_open = 0;
- conn->lastused = time(NULL);
+ conn->lastused = conn->lastused_count = time(NULL);
conn->service = snum;
conn->used = True;
conn->printer = (strncmp(dev,"LPT",3) == 0);
@@ -399,109 +632,106 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->admin_user = False;
/*
- * If force user is true, then store the
- * given userid and also the groups
- * of the user we're forcing.
+ * If force user is true, then store the given userid and the gid of
+ * the user we're forcing.
+ * For auxiliary groups see below.
*/
if (*lp_force_user(snum)) {
- struct passwd *pass2;
- pstring fuser;
- pstrcpy(fuser,lp_force_user(snum));
-
- /* Allow %S to be used by force user. */
- pstring_sub(fuser,"%S",lp_servicename(snum));
-
- pass2 = (struct passwd *)Get_Pwnam(fuser);
- if (pass2) {
- conn->uid = pass2->pw_uid;
- conn->gid = pass2->pw_gid;
- string_set(&conn->user,pass2->pw_name);
- fstrcpy(user,pass2->pw_name);
- conn->force_user = True;
- DEBUG(3,("Forced user %s\n",user));
- } else {
- DEBUG(1,("Couldn't find user %s\n",fuser));
+ NTSTATUS status2;
+
+ status2 = find_forced_user(snum,
+ (vuser != NULL) && vuser->guest,
+ &conn->uid, &conn->gid, user,
+ &conn->nt_user_token);
+ if (!NT_STATUS_IS_OK(status2)) {
conn_free(conn);
- *status = NT_STATUS_NO_SUCH_USER;
+ *status = status2;
return NULL;
}
+ string_set(&conn->user,user);
+ conn->force_user = True;
+ DEBUG(3,("Forced user %s\n",user));
}
-#ifdef HAVE_GETGRNAM
/*
* If force group is true, then override
* any groupid stored for the connecting user.
*/
if (*lp_force_group(snum)) {
- gid_t gid;
- pstring gname;
- pstring tmp_gname;
- BOOL user_must_be_member = False;
-
- pstrcpy(tmp_gname,lp_force_group(snum));
-
- if (tmp_gname[0] == '+') {
- user_must_be_member = True;
- /* even now, tmp_gname is null terminated */
- pstrcpy(gname,&tmp_gname[1]);
- } else {
- pstrcpy(gname,tmp_gname);
- }
- /* default service may be a group name */
- pstring_sub(gname,"%S",lp_servicename(snum));
- gid = nametogid(gname);
-
- if (gid == (gid_t)-1) {
- DEBUG(1,("Couldn't find group %s\n",gname));
+ NTSTATUS status2;
+ DOM_SID group_sid;
+
+ status2 = find_forced_group(conn->force_user,
+ snum, user,
+ &group_sid, &conn->gid);
+ if (!NT_STATUS_IS_OK(status2)) {
conn_free(conn);
- *status = NT_STATUS_NO_SUCH_GROUP;
+ *status = status2;
return NULL;
}
- /*
- * If the user has been forced and the forced group starts
- * with a '+', then we only set the group to be the forced
- * group if the forced user is a member of that group.
- * Otherwise, the meaning of the '+' would be ignored.
- */
- if (conn->force_user && user_must_be_member) {
- if (user_in_group_list( user, gname, NULL, 0)) {
- conn->gid = gid;
- DEBUG(3,("Forced group %s for member %s\n",
- gname,user));
- }
- } else {
- conn->gid = gid;
- DEBUG(3,("Forced group %s\n",gname));
+ if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
+
+ /* Not force user and not security=share, but force
+ * group. vuser has a token to copy */
+
+ conn->nt_user_token = dup_nt_token(
+ NULL, vuser->nt_user_token);
+ if (conn->nt_user_token == NULL) {
+ DEBUG(0, ("dup_nt_token failed\n"));
+ conn_free(conn);
+ *status = NT_STATUS_NO_MEMORY;
+ return NULL;
}
- conn->force_group = True;
- }
-#endif /* HAVE_GETGRNAM */
+ }
- {
- pstring s;
- pstrcpy(s,lp_pathname(snum));
- standard_sub_conn(conn,s,sizeof(s));
- string_set(&conn->connectpath,s);
- DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
+ /* If conn->nt_user_token is still NULL, we have
+ * security=share. This means ignore the SID, as we had no
+ * vuser to copy from */
+
+ if (conn->nt_user_token != NULL) {
+ /* Overwrite the primary group sid */
+ sid_copy(&conn->nt_user_token->user_sids[1],
+ &group_sid);
+
+ }
+ conn->force_group = True;
}
- if (conn->force_user || conn->force_group) {
+ if (conn->nt_user_token != NULL) {
+ size_t i;
+
+ /* We have a share-specific token from force [user|group].
+ * This means we have to create the list of unix groups from
+ * the list of sids. */
- /* groups stuff added by ih */
conn->ngroups = 0;
conn->groups = NULL;
-
- /* Find all the groups this uid is in and
- store them. Used by change_to_user() */
- initialise_groups(conn->user, conn->uid, conn->gid);
- get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
-
- conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
- conn->ngroups, conn->groups,
- guest);
+
+ for (i=0; i<conn->nt_user_token->num_sids; i++) {
+ gid_t gid;
+ DOM_SID *sid = &conn->nt_user_token->user_sids[i];
+
+ if (!sid_to_gid(sid, &gid)) {
+ DEBUG(10, ("Could not convert SID %s to gid, "
+ "ignoring it\n",
+ sid_string_static(sid)));
+ continue;
+ }
+ add_gid_to_array_unique(NULL, gid, &conn->groups,
+ &conn->ngroups);
+ }
+ }
+
+ {
+ pstring s;
+ pstrcpy(s,lp_pathname(snum));
+ standard_sub_conn(conn,s,sizeof(s));
+ set_conn_connectpath(conn,s);
+ DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
+ lp_servicename(snum)));
}
/*
@@ -552,7 +782,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
pstring s;
pstrcpy(s,conn->connectpath);
canonicalize_path(conn, s);
- string_set(&conn->connectpath,s);
+ set_conn_connectpath(conn,s);
}
/* ROOT Activities: */
@@ -601,7 +831,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
/* Preexecs are done here as they might make the dir we are to ChDir
* to below */
-
+
/* execute any "preexec = " line */
if (*lp_preexec(snum)) {
pstring cmd;
@@ -679,7 +909,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
pstring s;
pstrcpy(s,conn->connectpath);
vfs_GetWd(conn,s);
- string_set(&conn->connectpath,s);
+ set_conn_connectpath(conn,s);
vfs_ChDir(conn,conn->connectpath);
}
#endif
diff --git a/source/smbd/session.c b/source/smbd/session.c
index 27f760a088e..41f8fd0ed43 100644
--- a/source/smbd/session.c
+++ b/source/smbd/session.c
@@ -224,6 +224,10 @@ static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf,
sesslist->count += 1;
sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid,
sesslist->count);
+ if (!sesslist->sessions) {
+ sesslist->count = 0;
+ return -1;
+ }
memcpy(&sesslist->sessions[sesslist->count - 1], current,
sizeof(struct sessionid));
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index fb6402b469c..7c90263a5b0 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -95,21 +95,25 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
{
char *p;
- set_message(outbuf,4,0,True);
+ if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ ERROR_NT(nt_status);
+ } else {
+ set_message(outbuf,4,0,True);
- nt_status = nt_status_squash(nt_status);
- SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
- SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
- SSVAL(outbuf, smb_vwv3, blob.length);
- p = smb_buf(outbuf);
+ nt_status = nt_status_squash(nt_status);
+ SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
+ SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
+ SSVAL(outbuf, smb_vwv3, blob.length);
+ p = smb_buf(outbuf);
- /* should we cap this? */
- memcpy(p, blob.data, blob.length);
- p += blob.length;
+ /* should we cap this? */
+ memcpy(p, blob.data, blob.length);
+ p += blob.length;
- p += add_signature( outbuf, p );
+ p += add_signature( outbuf, p );
- set_message_end(outbuf,p);
+ set_message_end(outbuf,p);
+ }
show_msg(outbuf);
return send_smb(smbd_server_fd(),outbuf);
@@ -217,7 +221,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (pac_data) {
logon_info = get_logon_info_from_pac(pac_data);
- netsamlogon_cache_store( client, &logon_info->info3 );
+ if (logon_info) {
+ netsamlogon_cache_store( client, &logon_info->info3 );
+ }
}
if (!strequal(p+1, lp_realm())) {
@@ -284,7 +290,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
map_username( user );
- pw = smb_getpwnam( user, real_username, True );
+ pw = smb_getpwnam( mem_ctx, user, real_username, True );
if (!pw) {
/* this was originally the behavior of Samba 2.2, if a user
@@ -294,7 +300,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
map_domainuser_to_guest = True;
fstrcpy(user,lp_guestaccount());
- pw = smb_getpwnam( user, real_username, True );
+ pw = smb_getpwnam( mem_ctx, user, real_username, True );
}
/* extra sanity check that the guest account is valid */
@@ -316,14 +322,14 @@ static int reply_spnego_kerberos(connection_struct *conn,
if ( map_domainuser_to_guest ) {
make_server_info_guest(&server_info);
} else if (logon_info) {
- ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
-
+ ret = make_server_info_info3(mem_ctx, real_username, real_username, domain,
+ &server_info, &logon_info->info3);
if ( !NT_STATUS_IS_OK(ret) ) {
- DEBUG(1,("make_server_info_pac failed!\n"));
+ DEBUG(1,("make_server_info_info3 failed: %s!\n",
+ nt_errstr(ret)));
SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- passwd_free(&pw);
talloc_destroy(mem_ctx);
return ERROR_NT(ret);
}
@@ -332,25 +338,38 @@ static int reply_spnego_kerberos(connection_struct *conn,
ret = make_server_info_pw(&server_info, real_username, pw);
if ( !NT_STATUS_IS_OK(ret) ) {
- DEBUG(1,("make_server_info_from_pw failed!\n"));
+ DEBUG(1,("make_server_info_pw failed: %s!\n",
+ nt_errstr(ret)));
SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- passwd_free(&pw);
talloc_destroy(mem_ctx);
return ERROR_NT(ret);
}
- /* make_server_info_pw does not set the domain. Without this we end up
- * with the local netbios name in substitutions for %D. */
+ /* make_server_info_pw does not set the domain. Without this
+ * we end up with the local netbios name in substitutions for
+ * %D. */
if (server_info->sam_account != NULL) {
pdb_set_domain(server_info->sam_account, domain, PDB_SET);
}
}
-
-
- passwd_free(&pw);
+
+ /* we need to build the token for the user. make_server_info_guest()
+ already does this */
+
+ if ( !server_info->ptok ) {
+ ret = create_local_token( server_info );
+ if ( !NT_STATUS_IS_OK(ret) ) {
+ SAFE_FREE(client);
+ data_blob_free(&ap_rep);
+ data_blob_free(&session_key);
+ TALLOC_FREE( mem_ctx );
+ TALLOC_FREE( server_info );
+ return ERROR_NT(ret);
+ }
+ }
/* register_vuid keeps the server info */
/* register_vuid takes ownership of session_key, no need to free after this.
@@ -359,7 +378,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
SAFE_FREE(client);
- if (sess_vuid == -1) {
+ if (sess_vuid == UID_FIELD_INVALID ) {
ret = NT_STATUS_LOGON_FAILURE;
} else {
/* current_user_info is changed on new vuid */
@@ -431,7 +450,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
(*auth_ntlmssp_state)->server_info = NULL;
- if (sess_vuid == -1) {
+ if (sess_vuid == UID_FIELD_INVALID ) {
nt_status = NT_STATUS_LOGON_FAILURE;
} else {
@@ -676,7 +695,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
vuser = get_partial_auth_user_struct(vuid);
if (!vuser) {
vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
- if (vuid == -1) {
+ if (vuid == UID_FIELD_INVALID ) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -1031,7 +1050,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
} else {
struct auth_context *plaintext_auth_context = NULL;
const uint8 *chal;
- if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
+
+ nt_status = make_auth_context_subsystem(&plaintext_auth_context);
+
+ if (NT_STATUS_IS_OK(nt_status)) {
chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
if (!make_user_info_for_reply(&user_info,
@@ -1063,6 +1085,21 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
return ERROR_NT(nt_status_squash(nt_status));
}
+ /* Ensure we can't possible take a code path leading to a null defref. */
+ if (!server_info) {
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
+ nt_status = create_local_token(server_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(10, ("create_local_token failed: %s\n",
+ nt_errstr(nt_status)));
+ data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
+ data_blob_clear_free(&plaintext_password);
+ return ERROR_NT(nt_status_squash(nt_status));
+ }
+
if (server_info->user_session_key.data) {
session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
} else {
@@ -1092,7 +1129,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
- if (sess_vuid == -1) {
+ if (sess_vuid == UID_FIELD_INVALID) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c
new file mode 100644
index 00000000000..df5f445587f
--- /dev/null
+++ b/source/smbd/share_access.c
@@ -0,0 +1,269 @@
+/*
+ Unix SMB/CIFS implementation.
+ Check access based on valid users, read list and friends
+ 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"
+
+/*
+ * No prefix means direct username
+ * @name means netgroup first, then unix group
+ * &name means netgroup
+ * +name means unix group
+ * + and & may be combined
+ */
+
+static BOOL do_group_checks(const char **name, const char **pattern)
+{
+ if ((*name)[0] == '@') {
+ *pattern = "&+";
+ *name += 1;
+ return True;
+ }
+
+ if (((*name)[0] == '+') && ((*name)[1] == '&')) {
+ *pattern = "+&";
+ *name += 2;
+ return True;
+ }
+
+ if ((*name)[0] == '+') {
+ *pattern = "+";
+ *name += 1;
+ return True;
+ }
+
+ if (((*name)[0] == '&') && ((*name)[1] == '+')) {
+ *pattern = "&+";
+ *name += 2;
+ return True;
+ }
+
+ if ((*name)[0] == '&') {
+ *pattern = "&";
+ *name += 1;
+ return True;
+ }
+
+ return False;
+}
+
+static BOOL token_contains_name(TALLOC_CTX *mem_ctx,
+ const char *username,
+ const char *sharename,
+ const struct nt_user_token *token,
+ const char *name)
+{
+ const char *prefix;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+
+ if (username != NULL) {
+ name = talloc_sub_basic(mem_ctx, username, name);
+ }
+ if (sharename != NULL) {
+ name = talloc_string_sub(mem_ctx, name, "%S", sharename);
+ }
+
+ if (name == NULL) {
+ /* This is too security sensitive, better panic than return a
+ * result that might be interpreted in a wrong way. */
+ smb_panic("substitutions failed\n");
+ }
+
+ /* check to see is we already have a SID */
+
+ if ( string_to_sid( &sid, name ) ) {
+ DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name));
+ return nt_token_check_sid( &sid, token );
+ }
+
+ if (!do_group_checks(&name, &prefix)) {
+ if (!lookup_name(mem_ctx, name, LOOKUP_NAME_ALL,
+ NULL, NULL, &sid, &type)) {
+ DEBUG(5, ("lookup_name %s failed\n", name));
+ return False;
+ }
+ if (type != SID_NAME_USER) {
+ DEBUG(5, ("%s is a %s, expected a user\n",
+ name, sid_type_lookup(type)));
+ return False;
+ }
+ return nt_token_check_sid(&sid, token);
+ }
+
+ for (/* initialized above */ ; *prefix != '\0'; prefix++) {
+ if (*prefix == '+') {
+ if (!lookup_name(mem_ctx, name,
+ LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
+ NULL, NULL, &sid, &type)) {
+ DEBUG(5, ("lookup_name %s failed\n", name));
+ return False;
+ }
+ if ((type != SID_NAME_DOM_GRP) &&
+ (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP)) {
+ DEBUG(5, ("%s is a %s, expected a group\n",
+ name, sid_type_lookup(type)));
+ return False;
+ }
+ if (nt_token_check_sid(&sid, token)) {
+ return True;
+ }
+ continue;
+ }
+ if (*prefix == '&') {
+ if (user_in_netgroup(username, name)) {
+ return True;
+ }
+ continue;
+ }
+ smb_panic("got invalid prefix from do_groups_check\n");
+ }
+ return False;
+}
+
+/*
+ * Check whether a user is contained in the list provided.
+ *
+ * Please note that the user name and share names passed in here mainly for
+ * the substitution routines that expand the parameter values, the decision
+ * whether a user is in the list is done after a lookup_name on the expanded
+ * parameter value, solely based on comparing the SIDs in token.
+ *
+ * The other use is the netgroup check when using @group or &group.
+ */
+
+BOOL token_contains_name_in_list(const char *username,
+ const char *sharename,
+ const struct nt_user_token *token,
+ const char **list)
+{
+ TALLOC_CTX *mem_ctx;
+
+ if (list == NULL) {
+ return False;
+ }
+
+ if ( (mem_ctx = talloc_new(NULL)) == NULL ) {
+ smb_panic("talloc_new failed\n");
+ }
+
+ while (*list != NULL) {
+ if (token_contains_name(mem_ctx, username, sharename,token, *list)) {
+ TALLOC_FREE(mem_ctx);
+ return True;
+ }
+ list += 1;
+ }
+
+ TALLOC_FREE(mem_ctx);
+ return False;
+}
+
+/*
+ * Check whether the user described by "token" has access to share snum.
+ *
+ * This looks at "invalid users", "valid users" and "only user/username"
+ *
+ * Please note that the user name and share names passed in here mainly for
+ * the substitution routines that expand the parameter values, the decision
+ * whether a user is in the list is done after a lookup_name on the expanded
+ * parameter value, solely based on comparing the SIDs in token.
+ *
+ * The other use is the netgroup check when using @group or &group.
+ */
+
+BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum)
+{
+ if (lp_invalid_users(snum) != NULL) {
+ if (token_contains_name_in_list(username, lp_servicename(snum),
+ token,
+ lp_invalid_users(snum))) {
+ DEBUG(10, ("User %s in 'invalid users'\n", username));
+ return False;
+ }
+ }
+
+ if (lp_valid_users(snum) != NULL) {
+ if (!token_contains_name_in_list(username,
+ lp_servicename(snum), token,
+ lp_valid_users(snum))) {
+ DEBUG(10, ("User %s no in 'valid users'\n", username));
+ return False;
+ }
+ }
+
+ if (lp_onlyuser(snum)) {
+ const char *list[2];
+ list[0] = lp_username(snum);
+ list[1] = NULL;
+ if (!token_contains_name_in_list(NULL, lp_servicename(snum),
+ token, list)) {
+ DEBUG(10, ("%s != 'username'\n", username));
+ return False;
+ }
+ }
+
+ DEBUG(10, ("user_ok_token: share %s is ok for unix user %s\n",
+ lp_servicename(snum), username));
+
+ return True;
+}
+
+/*
+ * Check whether the user described by "token" is restricted to read-only
+ * access on share snum.
+ *
+ * This looks at "invalid users", "valid users" and "only user/username"
+ *
+ * Please note that the user name and share names passed in here mainly for
+ * the substitution routines that expand the parameter values, the decision
+ * whether a user is in the list is done after a lookup_name on the expanded
+ * parameter value, solely based on comparing the SIDs in token.
+ *
+ * The other use is the netgroup check when using @group or &group.
+ */
+
+BOOL is_share_read_only_for_token(const char *username,
+ struct nt_user_token *token, int snum)
+{
+ BOOL result = lp_readonly(snum);
+
+ if (lp_readlist(snum) != NULL) {
+ if (token_contains_name_in_list(username,
+ lp_servicename(snum), token,
+ lp_readlist(snum))) {
+ result = True;
+ }
+ }
+
+ if (lp_writelist(snum) != NULL) {
+ if (token_contains_name_in_list(username,
+ lp_servicename(snum), token,
+ lp_writelist(snum))) {
+ result = False;
+ }
+ }
+
+ DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
+ "%s\n", lp_servicename(snum),
+ result ? "read-only" : "read-write", username));
+
+ return result;
+}
diff --git a/source/smbd/tdbutil.c b/source/smbd/tdbutil.c
deleted file mode 100644
index cafcde20374..00000000000
--- a/source/smbd/tdbutil.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Main SMB server routines
- Copyright (C) Jeremy Allison 2003
- Copyright (C) Gerald (Jerry) Carter 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"
-
-
-/**********************************************************************
- logging function used by smbd to detect and remove corrupted tdb's
-**********************************************************************/
-
-void smbd_tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
-{
- va_list ap;
- char *ptr = NULL;
- BOOL decrement_smbd_count;
-
- va_start(ap, format);
- vasprintf(&ptr, format, ap);
- va_end(ap);
-
- if (!ptr || !*ptr)
- return;
-
- DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr));
-
- if (tdb->ecode == TDB_ERR_CORRUPT) {
- int ret;
-
- DEBUG(0,("tdb_log: TDB %s is corrupt. Removing file and stopping this process.\n",
- tdb->name ));
-
- become_root();
- ret = unlink(tdb->name);
- if ( ret ) {
- DEBUG(0,("ERROR: %s\n", strerror(errno)));
- }
- unbecome_root();
-
-
- /* if its not connections.tdb, then make sure we decrement the
- smbd count. If connections.tdb is bad, there's nothing we
- can do and everything will eventually shut down or clean
- up anyways */
-
- if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 )
- decrement_smbd_count = False;
- else
- decrement_smbd_count = True;
-
- /* now die */
-
- smb_panic2("corrupt tdb\n", decrement_smbd_count );
- }
-
- if (tdb->ecode == TDB_ERR_IO)
- {
- if ( strcmp(tdb->name, lock_path("connections.tdb")) == 0 )
- decrement_smbd_count = False;
- else
- decrement_smbd_count = True;
-
- smb_panic2( "i/o error on tdb.\n", decrement_smbd_count );
- }
-
- SAFE_FREE(ptr);
-}
-
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 6830644d8d1..b229807bfdc 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -563,7 +563,7 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-static int send_trans2_replies(char *outbuf,
+int send_trans2_replies(char *outbuf,
int bufsize,
char *params,
int paramsize,
@@ -856,7 +856,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
inode = sbuf.st_ino;
if (fattr & aDIR) {
talloc_destroy(ctx);
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
return(ERROR_DOS(ERRDOS,ERRnoaccess));
}
@@ -864,17 +864,17 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
status = set_ea(conn, fsp, fname, ea_list);
talloc_destroy(ctx);
if (!NT_STATUS_IS_OK(status)) {
- close_file(fsp,False);
+ close_file(fsp,ERROR_CLOSE);
return ERROR_NT(status);
}
}
/* Realloc the size of parameters and data we will return */
- params = SMB_REALLOC(*pparams, 30);
- if( params == NULL ) {
+ *pparams = SMB_REALLOC(*pparams, 30);
+ if(*pparams == NULL ) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
SSVAL(params,0,fsp->fnum);
SSVAL(params,2,open_attr);
@@ -1146,7 +1146,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
continue;
}
- file_size = get_file_size(sbuf);
+ 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;
@@ -1158,17 +1159,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
adate &= ~1;
}
- if(mode & aDIR) {
- /* This is necessary, as otherwise the
- * desktop.ini file in this folder is
- * ignored */
- mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
- file_size = 0;
- }
DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
found = True;
+
+ dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
}
}
@@ -1648,11 +1644,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
break;
case SMB_FIND_FILE_UNIX:
- if (!lp_unix_extensions())
- return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+ if (!lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
break;
default:
- return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
@@ -1717,21 +1714,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
}
- pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
- if( pdata == NULL ) {
+ *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+ if(*ppdata == NULL ) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
-
- *ppdata = pdata;
+ pdata = *ppdata;
/* Realloc the params space */
- params = SMB_REALLOC(*pparams, 10);
- if (params == NULL) {
+ *pparams = SMB_REALLOC(*pparams, 10);
+ if (*pparams == NULL) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
/* Save the wildcard match and attribs we are using on this directory -
needed as lanman2 assumes these are being saved between calls */
@@ -1931,11 +1927,12 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
break;
case SMB_FIND_FILE_UNIX:
- if (!lp_unix_extensions())
- return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+ if (!lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
break;
default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
if (info_level == SMB_FIND_EA_LIST) {
@@ -1968,22 +1965,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
}
- pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
- if(pdata == NULL) {
+ *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+ if(*ppdata == NULL) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *ppdata = pdata;
+ pdata = *ppdata;
/* Realloc the params space */
- params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
- if( params == NULL ) {
+ *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
+ if(*pparams == NULL ) {
talloc_destroy(ea_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
/* Check that the dptr is valid */
if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
@@ -2140,12 +2137,12 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
return ERROR_DOS(ERRSRV,ERRinvdevice);
}
- pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
- if ( pdata == NULL ) {
+ *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
+ if (*ppdata == NULL ) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *ppdata = pdata;
+ pdata = *ppdata;
memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
switch (info_level) {
@@ -2357,7 +2354,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
fsp.fnum = -1;
/* access check */
- if (current_user.uid != 0) {
+ if (current_user.ut.uid != 0) {
DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -2403,13 +2400,24 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
*/
case SMB_QUERY_CIFS_UNIX_INFO:
- if (!lp_unix_extensions())
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ if (!lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
data_len = 12;
SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
- SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
- CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
+ /* 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
break;
case SMB_QUERY_POSIX_FS_INFO:
@@ -2417,9 +2425,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
int rc;
vfs_statvfs_struct svfs;
- if (!lp_unix_extensions())
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
-
+ if (!lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
rc = SMB_VFS_STATVFS(conn, ".", &svfs);
if (!rc) {
@@ -2435,7 +2444,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
#ifdef EOPNOTSUPP
} else if (rc == EOPNOTSUPP) {
- return ERROR_DOS(ERRDOS, ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
#endif /* EOPNOTSUPP */
} else {
DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
@@ -2456,7 +2465,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
/* drop through */
default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
@@ -2500,7 +2509,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb
uint32 client_unix_cap_high;
if (!lp_unix_extensions()) {
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
/* There should be 12 bytes of capabilities set. */
@@ -2520,8 +2529,15 @@ cap_low = 0x%x, cap_high = 0x%x\n",
(unsigned int)client_unix_cap_high ));
/* Here is where we must switch to posix pathname processing... */
- lp_set_posix_pathnames();
- mangle_change_to_posix();
+ if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ 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);
+ }
+#endif
break;
}
case SMB_FS_QUOTA_INFORMATION:
@@ -2532,7 +2548,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
ZERO_STRUCT(quotas);
/* access check */
- if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
+ if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRSRV,ERRaccess);
@@ -2598,7 +2614,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
default:
DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
info_level));
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
break;
}
@@ -2773,13 +2789,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
char *fullpathname;
char *base_name;
char *p;
+ char *lock_data = NULL;
SMB_OFF_T pos = 0;
BOOL bad_path = False;
BOOL delete_pending = False;
int len;
time_t c_time;
files_struct *fsp = NULL;
- TALLOC_CTX *ea_ctx = NULL;
+ TALLOC_CTX *data_ctx = NULL;
struct ea_list *ea_list = NULL;
uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
@@ -2826,10 +2843,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- delete_pending =
- get_delete_on_close_flag(sbuf.st_dev,
- sbuf.st_ino,
- fname);
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
} else {
/*
* Original code - this is an open file.
@@ -2842,10 +2856,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return(UNIXERROR(ERRDOS,ERRbadfid));
}
pos = fsp->fh->position_information;
- delete_pending =
- get_delete_on_close_flag(sbuf.st_dev,
- sbuf.st_ino,
- fname);
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
access_mask = fsp->access_mask;
}
} else {
@@ -2887,9 +2898,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- delete_pending = get_delete_on_close_flag(sbuf.st_dev,
- sbuf.st_ino,
- fname);
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
if (delete_pending) {
return ERROR_NT(NT_STATUS_DELETE_PENDING);
}
@@ -2906,8 +2915,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
nlink -= 1;
}
- if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
@@ -2923,59 +2933,84 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
mode = FILE_ATTRIBUTE_NORMAL;
fullpathname = fname;
- file_size = get_file_size(sbuf);
- if (mode & aDIR) {
- /* This is necessary, as otherwise the desktop.ini file in
- * this folder is ignored */
- mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
- file_size = 0;
- }
+ if (!(mode & aDIR))
+ file_size = get_file_size(sbuf);
- /* Pull any EA list from the data portion. */
- if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
- uint32 ea_size;
+ /* Pull out any data sent here before we realloc. */
+ switch (info_level) {
+ case SMB_INFO_QUERY_EAS_FROM_LIST:
+ {
+ /* Pull any EA list from the data portion. */
+ uint32 ea_size;
- if (total_data < 4) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
- ea_size = IVAL(pdata,0);
+ if (total_data < 4) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ ea_size = IVAL(pdata,0);
- if (total_data > 0 && ea_size != total_data) {
- DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
+ if (total_data > 0 && ea_size != total_data) {
+ DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
- if (!lp_ea_support(SNUM(conn))) {
- return ERROR_DOS(ERRDOS,ERReasnotsupported);
- }
+ if (!lp_ea_support(SNUM(conn))) {
+ return ERROR_DOS(ERRDOS,ERReasnotsupported);
+ }
- if ((ea_ctx = talloc_init("ea_list")) == NULL) {
- return ERROR_NT(NT_STATUS_NO_MEMORY);
+ if ((data_ctx = talloc_init("ea_list")) == NULL) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ /* Pull out the list of names. */
+ ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
+ if (!ea_list) {
+ talloc_destroy(data_ctx);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ break;
}
+#if defined(DEVELOPER)
+ case SMB_QUERY_POSIX_LOCK:
+ {
+ if (fsp == NULL || fsp->fh->fd == -1) {
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+ }
- /* Pull out the list of names. */
- ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
- if (!ea_list) {
- talloc_destroy(ea_ctx);
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ if (total_data != POSIX_LOCK_DATA_SIZE) {
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if ((data_ctx = talloc_init("lock_request")) == NULL) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ /* Copy the lock range data. */
+ lock_data = talloc_memdup(data_ctx, pdata, total_data);
+ if (!lock_data) {
+ talloc_destroy(data_ctx);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
}
+#endif
+ default:
+ break;
}
- params = SMB_REALLOC(*pparams,2);
- if (params == NULL) {
- talloc_destroy(ea_ctx);
+ *pparams = SMB_REALLOC(*pparams,2);
+ if (*pparams == NULL) {
+ talloc_destroy(data_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
SSVAL(params,0,0);
data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
- pdata = SMB_REALLOC(*ppdata, data_size);
- if ( pdata == NULL ) {
- talloc_destroy(ea_ctx);
+ *ppdata = SMB_REALLOC(*ppdata, data_size);
+ if (*ppdata == NULL ) {
+ talloc_destroy(data_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *ppdata = pdata;
+ pdata = *ppdata;
c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
@@ -3058,18 +3093,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
- ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
+ ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
if (!ea_list || (total_ea_len > data_size)) {
- talloc_destroy(ea_ctx);
+ talloc_destroy(data_ctx);
data_size = 4;
SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
break;
}
- data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
- talloc_destroy(ea_ctx);
+ data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
+ talloc_destroy(data_ctx);
break;
}
@@ -3080,21 +3115,21 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
- ea_ctx = talloc_init("ea_ctx");
- if (!ea_ctx) {
+ data_ctx = talloc_init("ea_ctx");
+ if (!data_ctx) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
+ ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
if (!ea_list || (total_ea_len > data_size)) {
- talloc_destroy(ea_ctx);
+ talloc_destroy(data_ctx);
data_size = 4;
SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
break;
}
- data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
- talloc_destroy(ea_ctx);
+ data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
+ talloc_destroy(data_ctx);
break;
}
@@ -3241,7 +3276,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
/* Pathname with leading '\'. */
{
size_t byte_len;
- byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
+ byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
SIVAL(pdata,0,byte_len);
data_size = 4 + byte_len;
@@ -3285,7 +3320,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
if (mode & aDIR) {
data_size = 0;
} else {
- size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
+ size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
SIVAL(pdata,0,0); /* ??? */
SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
SOFF_T(pdata,8,file_size);
@@ -3487,8 +3522,84 @@ 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;
+ enum brl_type lock_type;
+
+ if (total_data != POSIX_LOCK_DATA_SIZE) {
+ return ERROR_NT(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:
+ lock_type = WRITE_LOCK;
+ break;
+ case POSIX_LOCK_TYPE_UNLOCK:
+ default:
+ /* There's no point in asking for an unlock... */
+ talloc_destroy(data_ctx);
+ 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 */
+
+ status = query_lock(fsp,
+ &lock_pid,
+ &count,
+ &offset,
+ &lock_type,
+ POSIX_LOCK);
+
+ if (ERROR_WAS_LOCK_DENIED(status)) {
+ /* Here we need to report who has it locked... */
+ data_size = POSIX_LOCK_DATA_SIZE;
+
+ SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
+ SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
+ SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
+#if defined(HAVE_LONGLONG)
+ SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
+ SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
+ SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
+ SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
+#else /* HAVE_LONGLONG */
+ SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
+ SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
+#endif /* HAVE_LONGLONG */
+
+ } else if (NT_STATUS_IS_OK(status)) {
+ /* For success we just return a copy of what we sent
+ with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
+ data_size = POSIX_LOCK_DATA_SIZE;
+ memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
+ SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
+ } else {
+ return ERROR_NT(status);
+ }
+ break;
+ }
+#endif
+
default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
@@ -3692,8 +3803,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
if (!CAN_WRITE(conn))
return ERROR_DOS(ERRSRV,ERRaccess);
- if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
if (VALID_STAT(sbuf))
unixmode = sbuf.st_mode;
@@ -3702,11 +3814,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
/* Realloc the parameter size */
- params = SMB_REALLOC(*pparams,2);
- if(params == NULL) {
+ *pparams = SMB_REALLOC(*pparams,2);
+ if (*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
SSVAL(params,0,0);
@@ -3861,8 +3973,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
#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_DOS(ERRDOS,ERRunknownlevel);
+ 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 ));
@@ -3898,7 +4012,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
new_fsp->fnum, strerror(errno)));
ret = -1;
}
- close_file(new_fsp,True);
+ close_file(new_fsp,NORMAL_CLOSE);
} else {
ret = vfs_allocate_file_space(fsp, allocation_size);
if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
@@ -3928,8 +4042,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
#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_DOS(ERRDOS,ERRunknownlevel);
+ 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 end of file info for file %s to %.0f\n", fname, (double)size ));
break;
@@ -3961,7 +4077,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
}
/* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, delete_on_close)) {
+ if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
@@ -3982,8 +4098,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
#ifdef LARGE_SMB_OFF_T
position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) /* more than 32 bits? */
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ 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 position information for file %s to %.0f\n",
fname, (double)position_information ));
@@ -4039,8 +4157,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
#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_DOS(ERRDOS,ERRunknownlevel);
+ if (IVAL(pdata,4) != 0) {
+ /* more than 32 bits? */
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
#endif /* LARGE_SMB_OFF_T */
}
pdata+=24; /* ctime & st_blocks are not changed */
@@ -4347,8 +4467,109 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
}
#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;
+
+ if (fsp == NULL || fsp->fh->fd == -1) {
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+ }
+
+ if (total_data != POSIX_LOCK_DATA_SIZE) {
+ return ERROR_NT(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 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);
+ }
+
+ 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);
+ }
+
+ 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 */
+
+ 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);
+
+ /* TODO: Deal with rescheduling blocking lock fail here... */
+ 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;
+ }
+ }
+ }
+
+ 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);
+ }
+#endif
+
default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
/* get some defaults (no modifications) if any info is zero or -1. */
@@ -4426,7 +4647,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
return(UNIXERROR(ERRDOS,ERRbadpath));
}
ret = vfs_set_filelen(new_fsp, size);
- close_file(new_fsp,True);
+ close_file(new_fsp,NORMAL_CLOSE);
} else {
ret = vfs_set_filelen(fsp, size);
}
@@ -4562,11 +4783,11 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
}
/* Realloc the parameter and data sizes */
- params = SMB_REALLOC(*pparams,2);
- if(params == NULL) {
+ *pparams = SMB_REALLOC(*pparams,2);
+ if(*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
SSVAL(params,0,0);
@@ -4600,15 +4821,15 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
case 2:
break;
default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
/* Realloc the parameter and data sizes */
- params = SMB_REALLOC(*pparams,6);
- if(params == NULL) {
+ *pparams = SMB_REALLOC(*pparams,6);
+ if (*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
SSVAL(params,0,fnf_handle);
SSVAL(params,2,0); /* No changes */
@@ -4638,11 +4859,11 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char
DEBUG(3,("call_trans2findnotifynext\n"));
/* Realloc the parameter and data sizes */
- params = SMB_REALLOC(*pparams,4);
- if(params == NULL) {
+ *pparams = SMB_REALLOC(*pparams,4);
+ if (*pparams == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *pparams = params;
+ params = *pparams;
SSVAL(params,0,0); /* No changes */
SSVAL(params,2,0); /* No EA errors */
@@ -4707,11 +4928,11 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf,
if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
(SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
- pdata = SMB_REALLOC(*ppdata, 32);
- if(pdata == NULL) {
+ *ppdata = SMB_REALLOC(*ppdata, 32);
+ if (*ppdata == NULL) {
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- *ppdata = pdata;
+ pdata = *ppdata;
/* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
CAN ACCEPT THIS IN UNICODE. JRA. */
@@ -4742,7 +4963,7 @@ int reply_findclose(connection_struct *conn,
dptr_close(&dptr_num);
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
@@ -4769,7 +4990,7 @@ int reply_findnclose(connection_struct *conn,
findnotifyfirst - so any dptr_num is ok here.
Just ignore it. */
- outsize = set_message(outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
@@ -4777,331 +4998,418 @@ int reply_findnclose(connection_struct *conn,
return(outsize);
}
-/****************************************************************************
- Reply to a SMBtranss2 - just ignore it!
-****************************************************************************/
-
-int reply_transs2(connection_struct *conn,
- char *inbuf,char *outbuf,int length,int bufsize)
+int handle_trans2(connection_struct *conn,
+ struct trans_state *state,
+ char *inbuf, char *outbuf, int size, int bufsize)
{
- START_PROFILE(SMBtranss2);
- DEBUG(4,("Ignoring transs2 of length %d\n",length));
- END_PROFILE(SMBtranss2);
- return(-1);
-}
-
-/****************************************************************************
- Reply to a SMBtrans2.
-****************************************************************************/
-
-int reply_trans2(connection_struct *conn,
- char *inbuf,char *outbuf,int length,int bufsize)
-{
- int outsize = 0;
- unsigned int total_params = SVAL(inbuf, smb_tpscnt);
- unsigned int total_data =SVAL(inbuf, smb_tdscnt);
- unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
-#if 0
- unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
- unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
- BOOL close_tid = BITSETW(inbuf+smb_flags,0);
- BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
- int32 timeout = IVALS(inbuf,smb_timeout);
-#endif
- unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
- unsigned int tran_call = SVAL(inbuf, smb_setup0);
- char *params = NULL, *data = NULL;
- unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
- START_PROFILE(SMBtrans2);
-
- if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
- && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
- END_PROFILE(SMBtrans2);
- return ERROR_DOS(ERRSRV,ERRaccess);
- }
-
- outsize = set_message(outbuf,0,0,True);
-
- /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
- is so as a sanity check */
- if (suwcnt != 1) {
- /*
- * Need to have rc=0 for ioctl to get job id for OS/2.
- * Network printing will fail if function is not successful.
- * Similar function in reply.c will be used if protocol
- * is LANMAN1.0 instead of LM1.2X002.
- * Until DosPrintSetJobInfo with PRJINFO3 is supported,
- * outbuf doesn't have to be set(only job id is used).
- */
- if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
- (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
- (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
- DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
- } else {
- DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
- DEBUG(2,("Transaction is %d\n",tran_call));
- END_PROFILE(SMBtrans2);
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
- }
-
- /* Allocate the space for the maximum needed parameters and data */
- if (total_params > 0)
- params = (char *)SMB_MALLOC(total_params);
- if (total_data > 0)
- data = (char *)SMB_MALLOC(total_data);
-
- if ((total_params && !params) || (total_data && !data)) {
- DEBUG(2,("Out of memory in reply_trans2\n"));
- SAFE_FREE(params);
- SAFE_FREE(data);
- END_PROFILE(SMBtrans2);
- return ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
- /* Copy the param and data bytes sent with this request into
- the params buffer */
- num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
- num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
-
- if (num_params > total_params || num_data > total_data)
- exit_server("invalid params in reply_trans2");
-
- if(params) {
- unsigned int psoff = SVAL(inbuf, smb_psoff);
- if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
- goto bad_param;
- if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
- (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
- goto bad_param;
- memcpy( params, smb_base(inbuf) + psoff, num_params);
- }
- if(data) {
- unsigned int dsoff = SVAL(inbuf, smb_dsoff);
- if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
- goto bad_param;
- if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
- (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
- goto bad_param;
- memcpy( data, smb_base(inbuf) + dsoff, num_data);
- }
-
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
-
- if(num_data_sofar < total_data || num_params_sofar < total_params) {
- /* We need to send an interim response then receive the rest
- of the parameter/data bytes */
- outsize = set_message(outbuf,0,0,True);
- srv_signing_trans_stop();
- show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_trans2: send_smb failed.");
-
- while (num_data_sofar < total_data ||
- num_params_sofar < total_params) {
- BOOL ret;
- unsigned int param_disp;
- unsigned int param_off;
- unsigned int data_disp;
- unsigned int data_off;
-
- ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
-
- /* We need to re-calcuate the new length after we've read the secondary packet. */
- length = smb_len(inbuf) + 4;
-
- /*
- * The sequence number for the trans reply is always
- * based on the last secondary received.
- */
+ int outsize;
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
-
- if ((ret &&
- (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
- outsize = set_message(outbuf,0,0,True);
- if(ret)
- DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
- else
- DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
- goto bad_param;
- }
-
- /* Revise total_params and total_data in case
- they have changed downwards */
- if (SVAL(inbuf, smb_tpscnt) < total_params)
- total_params = SVAL(inbuf, smb_tpscnt);
- if (SVAL(inbuf, smb_tdscnt) < total_data)
- total_data = SVAL(inbuf, smb_tdscnt);
-
- num_params = SVAL(inbuf,smb_spscnt);
- param_off = SVAL(inbuf, smb_spsoff);
- param_disp = SVAL(inbuf, smb_spsdisp);
- num_params_sofar += num_params;
-
- num_data = SVAL(inbuf, smb_sdscnt);
- data_off = SVAL(inbuf, smb_sdsoff);
- data_disp = SVAL(inbuf, smb_sdsdisp);
- num_data_sofar += num_data;
-
- if (num_params_sofar > total_params || num_data_sofar > total_data)
- goto bad_param;
-
- if (num_params) {
- if (param_disp + num_params > total_params)
- goto bad_param;
- if ((param_disp + num_params < param_disp) ||
- (param_disp + num_params < num_params))
- goto bad_param;
- if (param_disp > total_params)
- goto bad_param;
- if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
- (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
- goto bad_param;
- if (params + param_disp < params)
- goto bad_param;
-
- memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
- }
- if (num_data) {
- if (data_disp + num_data > total_data)
- goto bad_param;
- if ((data_disp + num_data < data_disp) ||
- (data_disp + num_data < num_data))
- goto bad_param;
- if (data_disp > total_data)
- goto bad_param;
- if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
- (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
- goto bad_param;
- if (data + data_disp < data)
- goto bad_param;
-
- memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
- }
- }
- }
-
if (Protocol >= PROTOCOL_NT1) {
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
}
/* Now we must call the relevant TRANS2 function */
- switch(tran_call) {
+ switch(state->call) {
case TRANSACT2_OPEN:
START_PROFILE_NESTED(Trans2_open);
- outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_FINDFIRST:
START_PROFILE_NESTED(Trans2_findfirst);
- outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_FINDNEXT:
START_PROFILE_NESTED(Trans2_findnext);
- outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_QFSINFO:
START_PROFILE_NESTED(Trans2_qfsinfo);
- outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_SETFSINFO:
START_PROFILE_NESTED(Trans2_setfsinfo);
- outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_QPATHINFO:
case TRANSACT2_QFILEINFO:
START_PROFILE_NESTED(Trans2_qpathinfo);
- outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_SETPATHINFO:
case TRANSACT2_SETFILEINFO:
START_PROFILE_NESTED(Trans2_setpathinfo);
- outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_FINDNOTIFYFIRST:
START_PROFILE_NESTED(Trans2_findnotifyfirst);
- outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_FINDNOTIFYNEXT:
START_PROFILE_NESTED(Trans2_findnotifynext);
- outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_MKDIR:
START_PROFILE_NESTED(Trans2_mkdir);
- outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_GET_DFS_REFERRAL:
START_PROFILE_NESTED(Trans2_get_dfs_referral);
- outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
case TRANSACT2_IOCTL:
START_PROFILE_NESTED(Trans2_ioctl);
- outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
- &params, total_params, &data, total_data, max_data_bytes);
+ 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);
break;
default:
/* Error in request */
- DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
- SAFE_FREE(params);
- SAFE_FREE(data);
+ DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
+ outsize = ERROR_DOS(ERRSRV,ERRerror);
+ }
+ return outsize;
+}
+
+/****************************************************************************
+ Reply to a SMBtrans2.
+ ****************************************************************************/
+
+int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
+ int size, int bufsize)
+{
+ int outsize = 0;
+ unsigned int dsoff = SVAL(inbuf, smb_dsoff);
+ unsigned int dscnt = SVAL(inbuf, smb_dscnt);
+ unsigned int psoff = SVAL(inbuf, smb_psoff);
+ unsigned int pscnt = SVAL(inbuf, smb_pscnt);
+ unsigned int tran_call = SVAL(inbuf, smb_setup0);
+ struct trans_state *state;
+ NTSTATUS result;
+
+ START_PROFILE(SMBtrans2);
+
+ if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
+ SVAL(inbuf, smb_mid)))) {
+ DEBUG(2, ("Got invalid trans2 request: %s\n",
+ nt_errstr(result)));
END_PROFILE(SMBtrans2);
- srv_signing_trans_stop();
- return ERROR_DOS(ERRSRV,ERRerror);
+ return ERROR_NT(result);
}
-
- /* As we do not know how many data packets will need to be
- returned here the various call_trans2xxxx calls
- must send their own. Thus a call_trans2xxx routine only
- returns a value other than -1 when it wants to send
- an error packet.
- */
-
- srv_signing_trans_stop();
- SAFE_FREE(params);
- SAFE_FREE(data);
+ if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
+ && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
+ END_PROFILE(SMBtrans2);
+ return ERROR_DOS(ERRSRV,ERRaccess);
+ }
+
+ if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ END_PROFILE(SMBtrans2);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ state->cmd = SMBtrans2;
+
+ state->mid = SVAL(inbuf, smb_mid);
+ state->vuid = SVAL(inbuf, smb_uid);
+ state->setup_count = SVAL(inbuf, smb_suwcnt);
+ state->total_param = SVAL(inbuf, smb_tpscnt);
+ state->param = NULL;
+ state->total_data = SVAL(inbuf, smb_tdscnt);
+ state->data = NULL;
+ state->max_param_return = SVAL(inbuf, smb_mprcnt);
+ state->max_data_return = SVAL(inbuf, smb_mdrcnt);
+ state->max_setup_return = SVAL(inbuf, smb_msrcnt);
+ state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
+ state->one_way = BITSETW(inbuf+smb_vwv5,1);
+
+ state->call = tran_call;
+
+ /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
+ is so as a sanity check */
+ if (state->setup_count != 1) {
+ /*
+ * Need to have rc=0 for ioctl to get job id for OS/2.
+ * Network printing will fail if function is not successful.
+ * Similar function in reply.c will be used if protocol
+ * is LANMAN1.0 instead of LM1.2X002.
+ * Until DosPrintSetJobInfo with PRJINFO3 is supported,
+ * outbuf doesn't have to be set(only job id is used).
+ */
+ if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
+ (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
+ (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
+ DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
+ } else {
+ DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
+ DEBUG(2,("Transaction is %d\n",tran_call));
+ END_PROFILE(SMBtrans2);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ }
+
+ if ((dscnt > state->total_data) || (pscnt > state->total_param))
+ goto bad_param;
+
+ 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);
+ if (state->data == NULL) {
+ DEBUG(0,("reply_trans2: data malloc fail for %u "
+ "bytes !\n", state->total_data));
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans2);
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ }
+ if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
+ goto bad_param;
+ if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
+ (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
+ goto bad_param;
+
+ memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
+ }
+
+ 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);
+ if (state->param == NULL) {
+ DEBUG(0,("reply_trans: param malloc fail for %u "
+ "bytes !\n", state->total_param));
+ SAFE_FREE(state->data);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ }
+ if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
+ goto bad_param;
+ if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
+ (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
+ goto bad_param;
+
+ memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
+ }
+
+ state->received_data = dscnt;
+ state->received_param = pscnt;
+
+ if ((state->received_param == state->total_param) &&
+ (state->received_data == state->total_data)) {
+
+ outsize = handle_trans2(conn, state, inbuf, outbuf,
+ size, bufsize);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return outsize;
+ }
+
+ DLIST_ADD(conn->pending_trans, state);
+
+ /* We need to send an interim response then receive the rest
+ of the parameter/data bytes */
+ outsize = set_message(outbuf,0,0,False);
+ show_msg(outbuf);
END_PROFILE(SMBtrans2);
- return outsize; /* If a correct response was needed the
- call_trans2xxx calls have already sent
- it. If outsize != -1 then it is returning */
+ return outsize;
bad_param:
- srv_signing_trans_stop();
- SAFE_FREE(params);
- SAFE_FREE(data);
+ DEBUG(0,("reply_trans2: invalid trans parameters\n"));
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
END_PROFILE(SMBtrans2);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
+
+
+/****************************************************************************
+ Reply to a SMBtranss2
+ ****************************************************************************/
+
+int reply_transs2(connection_struct *conn,
+ char *inbuf,char *outbuf,int size,int bufsize)
+{
+ int outsize = 0;
+ unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
+ struct trans_state *state;
+
+ START_PROFILE(SMBtranss2);
+
+ show_msg(inbuf);
+
+ for (state = conn->pending_trans; state != NULL;
+ state = state->next) {
+ if (state->mid == SVAL(inbuf,smb_mid)) {
+ break;
+ }
+ }
+
+ if ((state == NULL) || (state->cmd != SMBtrans2)) {
+ END_PROFILE(SMBtranss2);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+
+ /* Revise state->total_param and state->total_data in case they have
+ changed downwards */
+
+ if (SVAL(inbuf, smb_tpscnt) < state->total_param)
+ state->total_param = SVAL(inbuf, smb_tpscnt);
+ if (SVAL(inbuf, smb_tdscnt) < state->total_data)
+ state->total_data = SVAL(inbuf, smb_tdscnt);
+
+ pcnt = SVAL(inbuf, smb_spscnt);
+ poff = SVAL(inbuf, smb_spsoff);
+ pdisp = SVAL(inbuf, smb_spsdisp);
+
+ dcnt = SVAL(inbuf, smb_sdscnt);
+ doff = SVAL(inbuf, smb_sdsoff);
+ ddisp = SVAL(inbuf, smb_sdsdisp);
+
+ state->received_param += pcnt;
+ state->received_data += dcnt;
+
+ if ((state->received_data > state->total_data) ||
+ (state->received_param > state->total_param))
+ goto bad_param;
+
+ if (pcnt) {
+ if (pdisp+pcnt > state->total_param)
+ goto bad_param;
+ if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
+ goto bad_param;
+ if (pdisp > state->total_param)
+ goto bad_param;
+ if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
+ (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->param + pdisp < state->param)
+ goto bad_param;
+
+ memcpy(state->param+pdisp,smb_base(inbuf)+poff,
+ pcnt);
+ }
+
+ if (dcnt) {
+ if (ddisp+dcnt > state->total_data)
+ goto bad_param;
+ if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
+ goto bad_param;
+ if (ddisp > state->total_data)
+ goto bad_param;
+ if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
+ (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->data + ddisp < state->data)
+ goto bad_param;
+
+ memcpy(state->data+ddisp, smb_base(inbuf)+doff,
+ dcnt);
+ }
+
+ if ((state->received_param < state->total_param) ||
+ (state->received_data < state->total_data)) {
+ END_PROFILE(SMBtranss);
+ return -1;
+ }
+
+ /* construct_reply_common has done us the favor to pre-fill the
+ * command field with SMBtranss2 which is wrong :-)
+ */
+ SCVAL(outbuf,smb_com,SMBtrans2);
+
+ outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
+
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+
+ if (outsize == 0) {
+ END_PROFILE(SMBtranss);
+ return(ERROR_DOS(ERRSRV,ERRnosupport));
+ }
+
+ END_PROFILE(SMBtranss2);
+ return(outsize);
+
+ bad_param:
+
+ DEBUG(0,("reply_transs2: invalid trans parameters\n"));
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtranss2);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+}
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index a0fe4197157..c62c9d928ab 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -30,18 +30,18 @@ extern struct current_user current_user;
gid_t get_current_user_gid_first(int *piterator)
{
*piterator = 0;
- return current_user.gid;
+ return current_user.ut.gid;
}
gid_t get_current_user_gid_next(int *piterator)
{
gid_t ret;
- if (!current_user.groups || *piterator >= current_user.ngroups) {
+ if (!current_user.ut.groups || *piterator >= current_user.ut.ngroups) {
return (gid_t)-1;
}
- ret = current_user.groups[*piterator];
+ ret = current_user.ut.groups[*piterator];
(*piterator) += 1;
return ret;
}
@@ -56,7 +56,7 @@ BOOL change_to_guest(void)
if (!pass) {
/* Don't need to free() this as its stored in a static */
- pass = getpwnam_alloc(lp_guestaccount());
+ pass = getpwnam_alloc(NULL, lp_guestaccount());
if (!pass)
return(False);
}
@@ -71,64 +71,13 @@ BOOL change_to_guest(void)
current_user.conn = NULL;
current_user.vuid = UID_FIELD_INVALID;
-
- passwd_free(&pass);
+ TALLOC_FREE(pass);
+ pass = NULL;
+
return True;
}
-/****************************************************************************
- Readonly share for this user ?
-****************************************************************************/
-
-static BOOL is_share_read_only_for_user(connection_struct *conn, user_struct *vuser)
-{
- char **list;
- const char *service = lp_servicename(conn->service);
- BOOL read_only_ret = lp_readonly(conn->service);
-
- if (!service)
- return read_only_ret;
-
- str_list_copy(&list, lp_readlist(conn->service));
- if (list) {
- if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
- DEBUG(0, ("is_share_read_only_for_user: ERROR: read list substitution failed\n"));
- }
- if (!str_list_substitute(list, "%S", service)) {
- DEBUG(0, ("is_share_read_only_for_user: ERROR: read list service substitution failed\n"));
- }
- if (user_in_list(vuser->user.unix_name, (const char **)list, vuser->groups, vuser->n_groups)) {
- read_only_ret = True;
- }
- str_list_free(&list);
- }
-
- str_list_copy(&list, lp_writelist(conn->service));
- if (list) {
- if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
- DEBUG(0, ("is_share_read_only_for_user: ERROR: write "
- "list substitution failed\n"));
- }
- if (!str_list_substitute(list, "%S", service)) {
- DEBUG(0, ("is_share_read_only_for_user: ERROR: write "
- "list service substitution failed\n"));
- }
- if (user_in_list(vuser->user.unix_name, (const char **)list,
- vuser->groups, vuser->n_groups)) {
- read_only_ret = False;
- }
- str_list_free(&list);
- }
-
- DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
- "%s\n", service,
- read_only_ret ? "read-only" : "read-write",
- vuser->user.unix_name ));
-
- return read_only_ret;
-}
-
/*******************************************************************
Check if a username is OK.
********************************************************************/
@@ -148,20 +97,25 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
}
}
- if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups))
+ if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum))
return(False);
- readonly_share = is_share_read_only_for_user(conn, vuser);
+ readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
+ vuser->nt_user_token,
+ conn->service);
if (!readonly_share &&
!share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) {
/* smb.conf allows r/w, but the security descriptor denies
* write. Fall back to looking at readonly. */
readonly_share = True;
- DEBUG(5,("falling back to read-only access-evaluation due to security descriptor\n"));
+ DEBUG(5,("falling back to read-only access-evaluation due to "
+ "security descriptor\n"));
}
- if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) {
+ if (!share_access_check(conn, snum, vuser,
+ readonly_share ?
+ FILE_READ_DATA : FILE_WRITE_DATA)) {
return False;
}
@@ -173,11 +127,9 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
ent->vuid = vuser->vuid;
ent->read_only = readonly_share;
- if (user_in_list(vuser->user.unix_name ,lp_admin_users(conn->service), vuser->groups, vuser->n_groups)) {
- ent->admin_user = True;
- } else {
- ent->admin_user = False;
- }
+ ent->admin_user = token_contains_name_in_list(
+ vuser->user.unix_name, NULL, vuser->nt_user_token,
+ lp_admin_users(conn->service));
conn->read_only = ent->read_only;
conn->admin_user = ent->admin_user;
@@ -213,38 +165,43 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
*/
if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
- (current_user.uid == conn->uid)) {
- DEBUG(4,("change_to_user: Skipping user change - already user\n"));
+ (current_user.ut.uid == conn->uid)) {
+ DEBUG(4,("change_to_user: Skipping user change - already "
+ "user\n"));
return(True);
} else if ((current_user.conn == conn) &&
(vuser != 0) && (current_user.vuid == vuid) &&
- (current_user.uid == vuser->uid)) {
- DEBUG(4,("change_to_user: Skipping user change - already user\n"));
+ (current_user.ut.uid == vuser->uid)) {
+ DEBUG(4,("change_to_user: Skipping user change - already "
+ "user\n"));
return(True);
}
snum = SNUM(conn);
if ((vuser) && !check_user_ok(conn, vuser, snum)) {
- DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) not permitted access to share %s.\n",
- vuser->user.smb_name, vuser->user.unix_name, vuid, lp_servicename(snum)));
+ DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
+ "not permitted access to share %s.\n",
+ vuser->user.smb_name, vuser->user.unix_name, vuid,
+ lp_servicename(snum)));
return False;
}
if (conn->force_user) /* security = share sets this too */ {
uid = conn->uid;
gid = conn->gid;
- current_user.groups = conn->groups;
- current_user.ngroups = conn->ngroups;
+ current_user.ut.groups = conn->groups;
+ current_user.ut.ngroups = conn->ngroups;
token = conn->nt_user_token;
} else if (vuser) {
uid = conn->admin_user ? 0 : vuser->uid;
gid = vuser->gid;
- current_user.ngroups = vuser->n_groups;
- current_user.groups = vuser->groups;
+ current_user.ut.ngroups = vuser->n_groups;
+ current_user.ut.groups = vuser->groups;
token = vuser->nt_user_token;
} else {
- DEBUG(2,("change_to_user: Invalid vuid used %d in accessing share %s.\n",vuid, lp_servicename(snum) ));
+ DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
+ "share %s.\n",vuid, lp_servicename(snum) ));
return False;
}
@@ -255,7 +212,13 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
*/
if((group_c = *lp_force_group(snum))) {
- BOOL is_guest = False;
+
+ token = dup_nt_token(NULL, token);
+ if (token == NULL) {
+ DEBUG(0, ("dup_nt_token failed\n"));
+ return False;
+ }
+ must_free_token = True;
if(group_c == '+') {
@@ -267,40 +230,28 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
*/
int i;
- for (i = 0; i < current_user.ngroups; i++) {
- if (current_user.groups[i] == conn->gid) {
+ for (i = 0; i < current_user.ut.ngroups; i++) {
+ if (current_user.ut.groups[i] == conn->gid) {
gid = conn->gid;
+ gid_to_sid(&token->user_sids[1], gid);
break;
}
}
} else {
gid = conn->gid;
+ gid_to_sid(&token->user_sids[1], gid);
}
-
- /*
- * We've changed the group list in the token - we must
- * re-create it.
- */
-
- if (vuser && vuser->guest)
- is_guest = True;
-
- token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest);
- if (!token) {
- DEBUG(1, ("change_to_user: create_nt_token failed!\n"));
- return False;
- }
- must_free_token = True;
}
- set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token);
+ set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
+ token);
/*
* Free the new token (as set_sec_ctx copies it).
*/
if (must_free_token)
- delete_nt_token(&token);
+ TALLOC_FREE(token);
current_user.conn = conn;
current_user.vuid = vuid;
@@ -340,8 +291,9 @@ BOOL become_authenticated_pipe_user(pipes_struct *p)
if (!push_sec_ctx())
return False;
- set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid,
- p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token);
+ set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid,
+ p->pipe_user.ut.ngroups, p->pipe_user.ut.groups,
+ p->pipe_user.nt_user_token);
return True;
}
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c
index bbb7b5bb308..55bf146c20f 100644
--- a/source/smbd/vfs-wrap.c
+++ b/source/smbd/vfs-wrap.c
@@ -759,11 +759,21 @@ BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op,
BOOL result;
START_PROFILE(syscall_fcntl_lock);
- result = fcntl_lock(fd, op, offset, count,type);
+ 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;
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 001d42d172f..9a6327b33b5 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -95,6 +95,7 @@ static struct vfs_ops default_vfs = {
vfswrap_utime,
vfswrap_ftruncate,
vfswrap_lock,
+ vfswrap_getlock,
vfswrap_symlink,
vfswrap_readlink,
vfswrap_link,
@@ -712,7 +713,7 @@ char *vfs_readdirname(connection_struct *conn, void *p)
return(NULL);
#endif
-#ifdef HAVE_BROKEN_READDIR
+#ifdef HAVE_BROKEN_READDIR_NAME
/* using /usr/ucb/cc is BAD */
dname = dname - 2;
#endif
diff --git a/source/smbwrapper/shared.c b/source/smbwrapper/shared.c
index ca8df5841d1..c7f1951f8bb 100644
--- a/source/smbwrapper/shared.c
+++ b/source/smbwrapper/shared.c
@@ -111,7 +111,7 @@ char *smbw_getshared(const char *name)
if (fstat(shared_fd, &st)) goto failed;
if (st.st_size != shared_size) {
- var = (char *)Realloc(variables, st.st_size);
+ var = (char *)Realloc(variables, st.st_size, True);
if (!var) goto failed;
else variables = var;
shared_size = st.st_size;
@@ -167,7 +167,7 @@ void smbw_setshared(const char *name, const char *val)
l1 = strlen(name)+1;
l2 = strlen(val)+1;
- var = (char *)Realloc(variables, shared_size + l1+l2+4);
+ var = (char *)Realloc(variables, shared_size + l1+l2+4, True);
if (!var) {
DEBUG(0,("out of memory in smbw_setshared\n"));
diff --git a/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c
index edcc7a5c2f9..d4a5b51af4e 100644
--- a/source/smbwrapper/smbw.c
+++ b/source/smbwrapper/smbw.c
@@ -76,7 +76,7 @@ void smbw_init(void)
pstrcpy(dyn_CONFIGFILE, p);
}
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
if (!init_names())
exit(1);
diff --git a/source/smbwrapper/smbw_dir.c b/source/smbwrapper/smbw_dir.c
index a89af54e1a3..a5bf10b29e0 100644
--- a/source/smbwrapper/smbw_dir.c
+++ b/source/smbwrapper/smbw_dir.c
@@ -75,7 +75,7 @@ static struct smbw_dir *cur_dir;
/*****************************************************
add a entry to a directory listing
*******************************************************/
-static void smbw_dir_add(struct file_info *finfo, const char *mask,
+static void smbw_dir_add(const char *mntpnt, struct file_info *finfo, const char *mask,
void *state)
{
struct file_info *cdl;
@@ -85,7 +85,7 @@ static void smbw_dir_add(struct file_info *finfo, const char *mask,
if (cur_dir->malloced == cur_dir->count) {
cdl = (struct file_info *)Realloc(cur_dir->list,
sizeof(cur_dir->list[0])*
- (cur_dir->count+100));
+ (cur_dir->count+100), True);
if (!cdl) {
/* oops */
return;
@@ -113,7 +113,7 @@ static void smbw_share_add(const char *share, uint32 type,
pstrcpy(finfo.name, share);
finfo.mode = aRONLY | aDIR;
- smbw_dir_add(&finfo, NULL, NULL);
+ smbw_dir_add("\\", &finfo, NULL, NULL);
}
@@ -130,7 +130,7 @@ static void smbw_server_add(const char *name, uint32 type,
pstrcpy(finfo.name, name);
finfo.mode = aRONLY | aDIR;
- smbw_dir_add(&finfo, NULL, NULL);
+ smbw_dir_add("\\", &finfo, NULL, NULL);
}
@@ -152,7 +152,7 @@ static void smbw_printjob_add(struct print_job_info *job)
finfo.mode = aRONLY;
finfo.size = job->size;
- smbw_dir_add(&finfo, NULL, NULL);
+ smbw_dir_add("\\", &finfo, NULL, NULL);
}
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
index 5d70c046d37..ad73a1d9aa0 100644
--- a/source/tdb/tdb.c
+++ b/source/tdb/tdb.c
@@ -1397,6 +1397,7 @@ int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val)
/* 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)) {
@@ -1406,9 +1407,8 @@ int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private_val)
TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));;
ret = -1;
}
- tdb->travlocks.next = tl.next;
SAFE_FREE(key.dptr);
- return count;
+ goto out;
}
SAFE_FREE(key.dptr);
}
@@ -1458,10 +1458,14 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
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)
+ if (unlock_record(tdb, tdb->travlocks.off) != 0) {
+ SAFE_FREE(k);
return tdb_null;
- if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0)
+ }
+ if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) {
+ SAFE_FREE(k);
return tdb_null;
+ }
tdb->travlocks.off = 0;
}
@@ -2094,11 +2098,27 @@ fail:
}
/* reopen all tdb's */
-int tdb_reopen_all(void)
+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;
}
diff --git a/source/tdb/tdb.h b/source/tdb/tdb.h
index d1c976cd56b..b5b87ee5a54 100644
--- a/source/tdb/tdb.h
+++ b/source/tdb/tdb.h
@@ -128,7 +128,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
tdb_hash_func hash_fn);
int tdb_reopen(TDB_CONTEXT *tdb);
-int tdb_reopen_all(void);
+int tdb_reopen_all(int);
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);
diff --git a/source/tdb/tdbback.c b/source/tdb/tdbback.c
index 3f5bf3891b3..7967a6bbf54 100644
--- a/source/tdb/tdbback.c
+++ b/source/tdb/tdbback.c
@@ -108,6 +108,7 @@ int backup_tdb(const char *old_name, const char *new_name)
/* stat the old tdb to find its permissions */
if (stat(old_name, &st) != 0) {
perror(old_name);
+ free(tmp_name);
return 1;
}
@@ -115,6 +116,7 @@ int backup_tdb(const char *old_name, const char *new_name)
tdb = tdb_open(old_name, 0, 0, O_RDWR, 0);
if (!tdb) {
printf("Failed to open %s\n", old_name);
+ free(tmp_name);
return 1;
}
diff --git a/source/tdb/tdbdump.c b/source/tdb/tdbdump.c
index 6cac0bc5ccd..b702fb07355 100644
--- a/source/tdb/tdbdump.c
+++ b/source/tdb/tdbdump.c
@@ -59,9 +59,10 @@ static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *stat
return 0;
}
-static int dump_tdb(const char *fname)
+static int dump_tdb(const char *fname, const char *keyname)
{
TDB_CONTEXT *tdb;
+ TDB_DATA key, value;
tdb = tdb_open(fname, 0, 0, O_RDONLY, 0);
if (!tdb) {
@@ -69,20 +70,55 @@ static int dump_tdb(const char *fname)
return 1;
}
- tdb_traverse(tdb, traverse_fn, NULL);
+ if (!keyname) {
+ tdb_traverse(tdb, traverse_fn, NULL);
+ } else {
+ key.dptr = (char *)keyname;
+ key.dsize = strlen( keyname);
+ value = tdb_fetch(tdb, key);
+ if (!value.dptr) {
+ return 1;
+ } else {
+ print_data(value);
+ free(value.dptr);
+ }
+ }
+
return 0;
}
+static void usage( void)
+{
+ printf( "Usage: tdbdump [options] <filename>\n\n");
+ printf( " -h this help message\n");
+ printf( " -k keyname dumps value of keyname\n");
+}
+
int main(int argc, char *argv[])
{
- char *fname;
+ char *fname, *keyname=NULL;
+ int c;
if (argc < 2) {
printf("Usage: tdbdump <fname>\n");
exit(1);
}
- fname = argv[1];
+ while ((c = getopt( argc, argv, "hk:")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+ exit( 0);
+ case 'k':
+ keyname = optarg;
+ break;
+ default:
+ usage();
+ exit( 1);
+ }
+ }
+
+ fname = argv[optind];
- return dump_tdb(fname);
+ return dump_tdb(fname, keyname);
}
diff --git a/source/tdb/tdbtorture.c b/source/tdb/tdbtorture.c
index d03cc2a6103..2d367b91e1f 100644
--- a/source/tdb/tdbtorture.c
+++ b/source/tdb/tdbtorture.c
@@ -103,7 +103,7 @@ static void addrec_db(void)
#if REOPEN_PROB
if (random() % REOPEN_PROB == 0) {
- tdb_reopen_all();
+ tdb_reopen_all(1);
goto next;
}
#endif
@@ -192,7 +192,7 @@ int main(int argc, char *argv[])
for (i=0;i<NPROC;i++) {
pids[i] = fork();
if (pids[i] == 0) {
- tdb_reopen_all();
+ tdb_reopen_all(1);
tdb_logging_function(db, tdb_log);
diff --git a/source/tdb/tdbutil.c b/source/tdb/tdbutil.c
index 53011006327..fc45fa93606 100644
--- a/source/tdb/tdbutil.c
+++ b/source/tdb/tdbutil.c
@@ -104,11 +104,19 @@ int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int tim
Lock a chain by string. Return -1 if timeout or lock failed.
****************************************************************************/
-int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout)
+int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval)
{
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
- return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK);
+ return tdb_chainlock(tdb, key);
+}
+
+int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
+ int timeout)
+{
+ TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
+
+ return tdb_chainlock_with_timeout(tdb, key, timeout);
}
/****************************************************************************
@@ -126,7 +134,7 @@ void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
Read lock a chain by string. Return -1 if timeout or lock failed.
****************************************************************************/
-int tdb_read_lock_bystring(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout)
+int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout)
{
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
@@ -311,7 +319,7 @@ int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldva
int32 val;
int32 ret = -1;
- if (tdb_lock_bystring(tdb, keystr,0) == -1)
+ if (tdb_lock_bystring(tdb, keystr) == -1)
return -1;
if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
@@ -352,7 +360,7 @@ BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldv
uint32 val;
BOOL ret = False;
- if (tdb_lock_bystring(tdb, keystr,0) == -1)
+ if (tdb_lock_bystring(tdb, keystr) == -1)
return False;
if (!tdb_fetch_uint32(tdb, keystr, &val)) {
@@ -495,21 +503,24 @@ BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len,
len1 = tdb_pack_va(NULL, 0, fmt, ap);
va_end(ap);
- if (mem_ctx != NULL)
+ if (mem_ctx != NULL) {
*buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8,
(*len) + len1);
- else
+ } else {
*buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1);
+ }
- if (*buf == NULL)
+ if (*buf == NULL) {
return False;
+ }
va_start(ap, fmt);
len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap);
va_end(ap);
- if (len1 != len2)
+ if (len1 != len2) {
return False;
+ }
*len += len2;
@@ -794,6 +805,14 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
return tdb;
}
+/****************************************************************************
+ 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.
diff --git a/source/tests/os2_delete.c b/source/tests/os2_delete.c
new file mode 100644
index 00000000000..b3aaf67f418
--- /dev/null
+++ b/source/tests/os2_delete.c
@@ -0,0 +1,214 @@
+/*
+ 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"
+
+#define FAILED(d) (fprintf(stderr, "Failed for %s - %s\n", d, strerror(errno)), exit(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()
+{
+ 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 main(void)
+{
+ int total_deleted = 0;
+ DIR *d;
+ struct dirent *de;
+
+ cleanup();
+ create_files();
+
+ 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);
+
+ printf("Deleted %d files of %d\n", total_deleted, NUM_FILES);
+
+ rmdir(TESTDIR) == 0 || FAILED("rmdir");
+
+ return 0;
+}
+/*
+ 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"
+
+#define FAILED(d) (fprintf(stderr, "Failed for %s - %s\n", d, strerror(errno)), exit(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()
+{
+ 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 main(void)
+{
+ int total_deleted = 0;
+ DIR *d;
+ struct dirent *de;
+
+ cleanup();
+ create_files();
+
+ 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);
+
+ printf("Deleted %d files of %d\n", total_deleted, NUM_FILES);
+
+ rmdir(TESTDIR) == 0 || FAILED("rmdir");
+
+ return 0;
+}
diff --git a/source/torture/locktest.c b/source/torture/locktest.c
index c8336ebaf66..b946e48666e 100644
--- a/source/torture/locktest.c
+++ b/source/torture/locktest.c
@@ -51,6 +51,20 @@ static BOOL zero_zero;
enum lock_op {OP_LOCK, OP_UNLOCK, OP_REOPEN};
+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)
+{
+ if (op == OP_LOCK) return "lock";
+ else if (op == OP_UNLOCK) return "unlock";
+ else return "reopen";
+}
+
struct record {
enum lock_op lock_op;
enum brl_type lock_type;
@@ -520,9 +534,9 @@ static void test_locks(char *share[NSERVERS])
close_files(cli, fnum);
for (i=0;i<n;i++) {
- printf("{%d, %d, %u, %u, %.0f, %.0f, %u},\n",
- recorded[i].lock_op,
- recorded[i].lock_type,
+ printf("{%s, %s, conn = %u, file = %u, start = %.0f, len = %.0f, %u},\n",
+ lock_op_name(recorded[i].lock_op),
+ lock_op_type(recorded[i].lock_type),
recorded[i].conn,
recorded[i].f,
(double)recorded[i].start,
@@ -569,6 +583,8 @@ static void usage(void)
setlinebuf(stdout);
+ load_case_tables();
+
dbf = x_stderr;
if (argc < 3 || argv[1][0] == '-') {
@@ -586,7 +602,7 @@ static void usage(void)
argc -= NSERVERS;
argv += NSERVERS;
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
if (getenv("USER")) {
diff --git a/source/torture/locktest2.c b/source/torture/locktest2.c
index fc180bfafe2..519acebe8e8 100644
--- a/source/torture/locktest2.c
+++ b/source/torture/locktest2.c
@@ -498,7 +498,7 @@ static void usage(void)
argc -= 4;
argv += 4;
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
if (getenv("USER")) {
diff --git a/source/torture/masktest.c b/source/torture/masktest.c
index 07bfe691217..ffc9a20e71c 100644
--- a/source/torture/masktest.c
+++ b/source/torture/masktest.c
@@ -454,7 +454,7 @@ static void usage(void)
argc -= 1;
argv += 1;
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
if (getenv("USER")) {
diff --git a/source/torture/msgtest.c b/source/torture/msgtest.c
index d691ab32f1d..f7c47ddbbf8 100644
--- a/source/torture/msgtest.c
+++ b/source/torture/msgtest.c
@@ -41,7 +41,7 @@ void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
setup_logging(argv[0],True);
- lp_load(dyn_CONFIGFILE,False,False,False);
+ lp_load(dyn_CONFIGFILE,False,False,False,True);
message_init();
diff --git a/source/torture/nsstest.c b/source/torture/nsstest.c
index 585a592bdcd..d2b17f0f635 100644
--- a/source/torture/nsstest.c
+++ b/source/torture/nsstest.c
@@ -174,6 +174,9 @@ again:
if (status == NSS_STATUS_TRYAGAIN) {
buflen *= 2;
buf = SMB_REALLOC(buf, buflen);
+ if (!buf) {
+ return NULL;
+ }
goto again;
}
if (status == NSS_STATUS_NOTFOUND) {
@@ -205,6 +208,9 @@ again:
if (status == NSS_STATUS_TRYAGAIN) {
buflen *= 2;
buf = SMB_REALLOC(buf, buflen);
+ if (!buf) {
+ return NULL;
+ }
goto again;
}
if (status == NSS_STATUS_NOTFOUND) {
@@ -237,6 +243,9 @@ again:
if (status == NSS_STATUS_TRYAGAIN) {
buflen *= 2;
buf = SMB_REALLOC(buf, buflen);
+ if (!buf) {
+ return NULL;
+ }
goto again;
}
if (status == NSS_STATUS_NOTFOUND) {
diff --git a/source/torture/rpctorture.c b/source/torture/rpctorture.c
index 28067c1a0ae..d69cc8eb8df 100644
--- a/source/torture/rpctorture.c
+++ b/source/torture/rpctorture.c
@@ -242,7 +242,7 @@ enum client_action
*term_code = 0;
#endif /* KANJI */
- if (!lp_load(dyn_CONFIGFILE,True, False, False))
+ if (!lp_load(dyn_CONFIGFILE,True, False, False, True))
{
fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
}
diff --git a/source/torture/t_push_ucs2.c b/source/torture/t_push_ucs2.c
index 8bfc6f7ad9e..8d327acfa56 100644
--- a/source/torture/t_push_ucs2.c
+++ b/source/torture/t_push_ucs2.c
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
int count = 1;
/* Needed to initialize character set */
- lp_load("/dev/null", True, False, False);
+ lp_load("/dev/null", True, False, False, True);
if (argc < 2) {
fprintf(stderr, "usage: %s STRING1 [COUNT]\n"
diff --git a/source/torture/t_strcmp.c b/source/torture/t_strcmp.c
index bc8640ee550..318423b8be0 100644
--- a/source/torture/t_strcmp.c
+++ b/source/torture/t_strcmp.c
@@ -12,7 +12,7 @@ int main(int argc, char *argv[])
int iters = 1;
/* Needed to initialize character set */
- lp_load("/dev/null", True, False, False);
+ lp_load("/dev/null", True, False, False, True);
if (argc < 3) {
fprintf(stderr, "usage: %s STRING1 STRING2 [ITERS]\n"
diff --git a/source/torture/t_strstr.c b/source/torture/t_strstr.c
index 7b928fb26be..49180b219f7 100644
--- a/source/torture/t_strstr.c
+++ b/source/torture/t_strstr.c
@@ -14,7 +14,7 @@ int main(int argc, char *argv[])
const char *ret = NULL;
/* Needed to initialize character set */
- lp_load("/dev/null", True, False, False);
+ lp_load("/dev/null", True, False, False, True);
if (argc < 3) {
fprintf(stderr, "usage: %s STRING1 STRING2 [ITERS]\n"
diff --git a/source/torture/torture.c b/source/torture/torture.c
index e995c3cc58a..0b3bfc18f4a 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -4916,7 +4916,7 @@ static void usage(void)
load_case_tables();
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
if (argc < 2) {
diff --git a/source/torture/vfstest.c b/source/torture/vfstest.c
index 1914a4acb50..61bb4b0bf65 100644
--- a/source/torture/vfstest.c
+++ b/source/torture/vfstest.c
@@ -113,7 +113,7 @@ static NTSTATUS cmd_conf(struct vfs_state *vfs, TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
- if (!lp_load(argv[1], False, True, False)) {
+ if (!lp_load(argv[1], False, True, False, True)) {
printf("Error loading \"%s\"\n", argv[1]);
return NT_STATUS_OK;
}
@@ -410,6 +410,11 @@ void exit_server(const char *reason)
exit(0);
}
+void exit_server_cleanly(const char *const reason)
+{
+ exit_server("normal exit");
+}
+
static int server_fd = -1;
int last_message = -1;
@@ -448,7 +453,7 @@ BOOL reload_services(BOOL test)
lp_killunused(conn_snum_used);
- ret = lp_load(dyn_CONFIGFILE, False, False, True);
+ ret = lp_load(dyn_CONFIGFILE, False, False, True, True);
/* perhaps the config filename is now set */
if (!test)
diff --git a/source/ubiqx/COPYING.LIB b/source/ubiqx/COPYING.LIB
deleted file mode 100644
index 8c8377da464..00000000000
--- a/source/ubiqx/COPYING.LIB
+++ /dev/null
@@ -1,481 +0,0 @@
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- Appendix: How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/source/ubiqx/README.UBI b/source/ubiqx/README.UBI
deleted file mode 100644
index a2c14ca62c9..00000000000
--- a/source/ubiqx/README.UBI
+++ /dev/null
@@ -1,18 +0,0 @@
-Fri Apr 17 10:21:56 CDT 1998
-
-The C code files in the samba/source/ubiqx directory are licensed under
-the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL). A copy of the
-LGPL should also be included in this directory under the name COPYING.LIB.
-If this file is not present, you can obtain a copy of the LGPL by writing
-to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
-USA.
-
-The versions of the ubiqx modules distributed with Samba may have been
-modified for inclusion with Samba. The main distribution, which contains
-additional available modules, can be found at:
-
- http://www.interads.co.uk/~crh/ubiqx/
-
-Chris Hertel
-Samba Team
-ubiqx@ubiqx.mn.org
diff --git a/source/ubiqx/sys_include.h b/source/ubiqx/sys_include.h
deleted file mode 100644
index 8ff270afe85..00000000000
--- a/source/ubiqx/sys_include.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef SYS_INCLUDE_H
-#define SYS_INCLUDE_H
-/* ========================================================================== **
- * sys_include.h
- *
- * Copyright (C) 1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- * This header provides system declarations and data types used internally
- * by the ubiqx modules.
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Samba version of sys_include.h
- *
- * ========================================================================== **
- */
-
-#ifndef _INCLUDES_H
-
-/* Block the inclusion of some Samba headers so that ubiqx types won't be
- * used before the headers that define them. These headers are not needed
- * in the ubiqx modules anyway.
- */
-#define _PROTO_H_
-#define _NAMESERV_H_
-#define _HASH_H_
-
-/* The main Samba system-adaptive header file.
- */
-#include "includes.h"
-
-#endif /* _INCLUDES_H */
-
-/* ================================ The End ================================= */
-#endif /* SYS_INCLUDE_H */
diff --git a/source/ubiqx/ubi_BinTree.c b/source/ubiqx/ubi_BinTree.c
deleted file mode 100644
index e452ac10dc2..00000000000
--- a/source/ubiqx/ubi_BinTree.c
+++ /dev/null
@@ -1,1172 +0,0 @@
-/* ========================================================================== **
- * ubi_BinTree.c
- *
- * Copyright (C) 1991-1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- *
- * This module implements a simple binary tree.
- *
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_BinTree.c,v
- * Revision 4.12 2004/06/06 04:51:56 crh
- * Fixed a small typo in ubi_BinTree.c (leftover testing cruft).
- * Did a small amount of formatting touchup to ubi_BinTree.h.
- *
- * Revision 4.11 2004/06/06 03:14:09 crh
- * Rewrote the ubi_btLeafNode() function. It now takes several paths in an
- * effort to find a deeper leaf node. There is a small amount of extra
- * overhead, but it is limited.
- *
- * Revision 4.10 2000/06/06 20:38:40 crh
- * In the ReplaceNode() function, the old node header was being copied
- * to the new node header using a byte-by-byte copy. This was causing
- * the 'insure' software testing program to report a memory leak. The
- * fix was to do a simple assignement: *newnode = *oldnode;
- * This quieted the (errant) memory leak reports and is probably a bit
- * faster than the bytewise copy.
- *
- * Revision 4.9 2000/01/08 23:24:30 crh
- * Clarified a variety of if( pointer ) lines, replacing them with
- * if( NULL != pointer ). This is more correct, and I have heard
- * of at least one (obscure?) system out there that uses a non-zero
- * value for NULL.
- * Also, speed improvement in Neighbor(). It was comparing pointers
- * when it could have compared two gender values. The pointer
- * comparison was somewhat indirect (does pointer equal the pointer
- * of the parent of the node pointed to by pointer). Urq.
- *
- * Revision 4.8 1999/09/22 03:40:30 crh
- * Modified ubi_btTraverse() and ubi_btKillTree(). They now return an
- * unsigned long indicating the number of nodes processed. The change
- * is subtle. An empty tree formerly returned False, and now returns
- * zero.
- *
- * Revision 4.7 1998/10/21 06:14:42 crh
- * Fixed bugs in FirstOf() and LastOf() reported by Massimo Campostrini.
- * See function comments.
- *
- * Revision 4.6 1998/07/25 17:02:10 crh
- * Added the ubi_trNewTree() macro.
- *
- * Revision 4.5 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 4.4 1998/06/03 17:42:46 crh
- * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is
- * included by all of the binary tree files.
- *
- * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in
- * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping
- * of tree types by simply changing a header. Unfortunately, the
- * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will
- * conflict if used together. You must either choose a single tree
- * type, or use the underlying function calls directly. Compare
- * the two header files for more information.
- *
- * Revision 4.3 1998/06/02 01:28:43 crh
- * Changed ubi_null.h to sys_include.h to make it more generic.
- *
- * Revision 4.2 1998/05/20 04:32:36 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- * Also, the balance and gender fields of the node were declared as
- * signed char. As I understand it, at least one SunOS or Solaris
- * compiler doesn't like "signed char". The declarations were
- * wrong anyway, so I changed them to simple "char".
- *
- * Revision 4.1 1998/03/31 06:11:57 crh
- * Thomas Aglassinger sent E'mail pointing out errors in the
- * dereferencing of function pointers, and a missing typecast.
- * Thanks, Thomas!
- *
- * Revision 4.0 1998/03/10 03:19:22 crh
- * Added the AVL field 'balance' to the ubi_btNode structure. This means
- * that all BinTree modules now use the same basic node structure, which
- * greatly simplifies the AVL module.
- * Decided that this was a big enough change to justify a new major revision
- * number. 3.0 was an error, so we're at 4.0.
- *
- * Revision 2.6 1998/01/24 06:27:46 crh
- * Added ubi_trCount() macro.
- *
- * Revision 2.5 1997/12/23 03:56:29 crh
- * In this version, all constants & macros defined in the header file have
- * the ubi_tr prefix. Also cleaned up anything that gcc complained about
- * when run with '-pedantic -fsyntax-only -Wall'.
- *
- * Revision 2.4 1997/07/26 04:11:10 crh
- * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE
- * and ubi_trFALSE.
- * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE.
- * + There used to be something called "ubi_TypeDefs.h". I got rid of it.
- * + Added function ubi_btLeafNode().
- *
- * Revision 2.3 1997/06/03 05:16:17 crh
- * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts.
- * Also changed the interface to function InitTree(). See the comments
- * for this function for more information.
- *
- * Revision 2.2 1995/10/03 22:00:07 CRH
- * Ubisized!
- *
- * Revision 2.1 95/03/09 23:37:10 CRH
- * Added the ModuleID static string and function. These modules are now
- * self-identifying.
- *
- * Revision 2.0 95/02/27 22:00:17 CRH
- * Revision 2.0 of this program includes the following changes:
- *
- * 1) A fix to a major typo in the RepaceNode() function.
- * 2) The addition of the static function Border().
- * 3) The addition of the public functions FirstOf() and LastOf(), which
- * use Border(). These functions are used with trees that allow
- * duplicate keys.
- * 4) A complete rewrite of the Locate() function. Locate() now accepts
- * a "comparison" operator.
- * 5) Overall enhancements to both code and comments.
- *
- * I decided to give this a new major rev number because the interface has
- * changed. In particular, there are two new functions, and changes to the
- * Locate() function.
- *
- * Revision 1.0 93/10/15 22:44:59 CRH
- * With this revision, I have added a set of #define's that provide a single,
- * standard API to all existing tree modules. Until now, each of the three
- * existing modules had a different function and typedef prefix, as follows:
- *
- * Module Prefix
- * ubi_BinTree ubi_bt
- * ubi_AVLtree ubi_avl
- * ubi_SplayTree ubi_spt
- *
- * To further complicate matters, only those portions of the base module
- * (ubi_BinTree) that were superceeded in the new module had the new names.
- * For example, if you were using ubi_SplayTree, the locate function was
- * called "ubi_sptLocate", but the next and previous functions remained
- * "ubi_btNext" and "ubi_btPrev".
- *
- * This was not too terrible if you were familiar with the modules and knew
- * exactly which tree model you wanted to use. If you wanted to be able to
- * change modules (for speed comparisons, etc), things could get messy very
- * quickly.
- *
- * So, I have added a set of defined names that get redefined in any of the
- * descendant modules. To use this standardized interface in your code,
- * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with
- * "ubi_tr". The "ubi_tr" names will resolve to the correct function or
- * datatype names for the module that you are using. Just remember to
- * include the header for that module in your program file. Because these
- * names are handled by the preprocessor, there is no added run-time
- * overhead.
- *
- * Note that the original names do still exist, and can be used if you wish
- * to write code directly to a specific module. This should probably only be
- * done if you are planning to implement a new descendant type, such as
- * red/black trees. CRH
- *
- * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH).
- *
- * ========================================================================== **
- */
-
-#include "ubi_BinTree.h" /* Header for this module. */
-
-
-/* ========================================================================== **
- * Static data.
- */
-
-static char ModuleID[] = "ubi_BinTree\n\
-\tRevision: 4.12\n\
-\tDate: 2004/06/06 04:51:56\n\
-\tAuthor: crh\n";
-
-/* ========================================================================== **
- * Internal (private) functions.
- */
-
-static ubi_btNodePtr qFind( ubi_btCompFunc cmp,
- ubi_btItemPtr FindMe,
- register ubi_btNodePtr p )
- /* ------------------------------------------------------------------------ **
- * This function performs a non-recursive search of a tree for a node
- * matching a specific key. It is called "qFind()" because it is
- * faster that TreeFind (below).
- *
- * Input:
- * cmp - a pointer to the tree's comparison function.
- * FindMe - a pointer to the key value for which to search.
- * p - a pointer to the starting point of the search. <p>
- * is considered to be the root of a subtree, and only
- * the subtree will be searched.
- *
- * Output:
- * A pointer to a node with a key that matches the key indicated by
- * FindMe, or NULL if no such node was found.
- *
- * Note: In a tree that allows duplicates, the pointer returned *might
- * not* point to the (sequentially) first occurance of the
- * desired key.
- * ------------------------------------------------------------------------ **
- */
- {
- int tmp;
-
- while( (NULL != p)
- && ((tmp = ubi_trAbNormal( (*cmp)(FindMe, p) )) != ubi_trEQUAL) )
- p = p->Link[tmp];
-
- return( p );
- } /* qFind */
-
-static ubi_btNodePtr TreeFind( ubi_btItemPtr findme,
- ubi_btNodePtr p,
- ubi_btNodePtr *parentp,
- char *gender,
- ubi_btCompFunc CmpFunc )
- /* ------------------------------------------------------------------------ **
- * TreeFind() searches a tree for a given value (findme). It will return a
- * pointer to the target node, if found, or NULL if the target node was not
- * found.
- *
- * TreeFind() also returns, via parameters, a pointer to the parent of the
- * target node, and a LEFT or RIGHT value indicating which child of the
- * parent is the target node. *If the target is not found*, then these
- * values indicate the place at which the target *should be found*. This
- * is useful when inserting a new node into a tree or searching for nodes
- * "near" the target node.
- *
- * The parameters are:
- *
- * findme - is a pointer to the key information to be searched for.
- * p - points to the root of the tree to be searched.
- * parentp - will return a pointer to a pointer to the !parent! of the
- * target node, which can be especially usefull if the target
- * was not found.
- * gender - returns LEFT or RIGHT to indicate which child of *parentp
- * was last searched.
- * CmpFunc - points to the comparison function.
- *
- * This function is called by ubi_btLocate() and ubi_btInsert().
- * ------------------------------------------------------------------------ **
- */
- {
- register ubi_btNodePtr tmp_p = p;
- ubi_btNodePtr tmp_pp = NULL;
- char tmp_gender = ubi_trEQUAL;
- int tmp_cmp;
-
- while( (NULL != tmp_p)
- && (ubi_trEQUAL != (tmp_cmp = ubi_trAbNormal((*CmpFunc)(findme, tmp_p)))) )
- {
- tmp_pp = tmp_p; /* Keep track of previous node. */
- tmp_gender = (char)tmp_cmp; /* Keep track of sex of child. */
- tmp_p = tmp_p->Link[tmp_cmp]; /* Go to child. */
- }
- *parentp = tmp_pp; /* Return results. */
- *gender = tmp_gender;
- return( tmp_p );
- } /* TreeFind */
-
-static void ReplaceNode( ubi_btNodePtr *parent,
- ubi_btNodePtr oldnode,
- ubi_btNodePtr newnode )
- /* ------------------------------------------------------------------------ **
- * Remove node oldnode from the tree, replacing it with node newnode.
- *
- * Input:
- * parent - A pointer to he parent pointer of the node to be
- * replaced. <parent> may point to the Link[] field of
- * a parent node, or it may indicate the root pointer at
- * the top of the tree.
- * oldnode - A pointer to the node that is to be replaced.
- * newnode - A pointer to the node that is to be installed in the
- * place of <*oldnode>.
- *
- * Notes: Don't forget to free oldnode.
- * Also, this function used to have a really nasty typo
- * bug. "oldnode" and "newnode" were swapped in the line
- * that now reads:
- * ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i];
- * Bleah!
- * ------------------------------------------------------------------------ **
- */
- {
- *newnode = *oldnode; /* Copy node internals to new node. */
-
- (*parent) = newnode; /* Old node's parent points to new child. */
- /* Now tell the children about their new step-parent. */
- if( oldnode->Link[ubi_trLEFT] )
- (oldnode->Link[ubi_trLEFT])->Link[ubi_trPARENT] = newnode;
- if( oldnode->Link[ubi_trRIGHT] )
- (oldnode->Link[ubi_trRIGHT])->Link[ubi_trPARENT] = newnode;
- } /* ReplaceNode */
-
-static void SwapNodes( ubi_btRootPtr RootPtr,
- ubi_btNodePtr Node1,
- ubi_btNodePtr Node2 )
- /* ------------------------------------------------------------------------ **
- * This function swaps two nodes in the tree. Node1 will take the place of
- * Node2, and Node2 will fill in the space left vacant by Node 1.
- *
- * Input:
- * RootPtr - pointer to the tree header structure for this tree.
- * Node1 - \
- * > These are the two nodes which are to be swapped.
- * Node2 - /
- *
- * Notes:
- * This function does a three step swap, using a dummy node as a place
- * holder. This function is used by ubi_btRemove().
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr *Parent;
- ubi_btNode dummy;
- ubi_btNodePtr dummy_p = &dummy;
-
- /* Replace Node 1 with the dummy, thus removing Node1 from the tree. */
- if( NULL != Node1->Link[ubi_trPARENT] )
- Parent = &((Node1->Link[ubi_trPARENT])->Link[(int)(Node1->gender)]);
- else
- Parent = &(RootPtr->root);
- ReplaceNode( Parent, Node1, dummy_p );
-
- /* Swap Node 1 with Node 2, placing Node 1 back into the tree. */
- if( NULL != Node2->Link[ubi_trPARENT] )
- Parent = &((Node2->Link[ubi_trPARENT])->Link[(int)(Node2->gender)]);
- else
- Parent = &(RootPtr->root);
- ReplaceNode( Parent, Node2, Node1 );
-
- /* Swap Node 2 and the dummy, thus placing Node 2 back into the tree. */
- if( NULL != dummy_p->Link[ubi_trPARENT] )
- Parent = &((dummy_p->Link[ubi_trPARENT])->Link[(int)(dummy_p->gender)]);
- else
- Parent = &(RootPtr->root);
- ReplaceNode( Parent, dummy_p, Node2 );
- } /* SwapNodes */
-
-/* -------------------------------------------------------------------------- **
- * These routines allow you to walk through the tree, forwards or backwards.
- */
-
-static ubi_btNodePtr SubSlide( register ubi_btNodePtr P,
- register int whichway )
- /* ------------------------------------------------------------------------ **
- * Slide down the side of a subtree.
- *
- * Given a starting node, this function returns a pointer to the LEFT-, or
- * RIGHT-most descendent, *or* (if whichway is PARENT) to the tree root.
- *
- * Input: P - a pointer to a starting place.
- * whichway - the direction (LEFT, RIGHT, or PARENT) in which to
- * travel.
- * Output: A pointer to a node that is either the root, or has no
- * whichway-th child but is within the subtree of P. Note that
- * the return value may be the same as P. The return value *will
- * be* NULL if P is NULL.
- * ------------------------------------------------------------------------ **
- */
- {
-
- if( NULL != P )
- while( NULL != P->Link[ whichway ] )
- P = P->Link[ whichway ];
- return( P );
- } /* SubSlide */
-
-static ubi_btNodePtr Neighbor( register ubi_btNodePtr P,
- register int whichway )
- /* ------------------------------------------------------------------------ **
- * Given starting point p, return the (key order) next or preceeding node
- * in the tree.
- *
- * Input: P - Pointer to our starting place node.
- * whichway - the direction in which to travel to find the
- * neighbor, i.e., the RIGHT neighbor or the LEFT
- * neighbor.
- *
- * Output: A pointer to the neighboring node, or NULL if P was NULL.
- *
- * Notes: If whichway is PARENT, the results are unpredictable.
- * ------------------------------------------------------------------------ **
- */
- {
- if( P )
- {
- if( NULL != P->Link[ whichway ] )
- return( SubSlide( P->Link[ whichway ], (char)ubi_trRevWay(whichway) ) );
- else
- while( NULL != P->Link[ ubi_trPARENT ] )
- {
- if( whichway == P->gender )
- P = P->Link[ ubi_trPARENT ];
- else
- return( P->Link[ ubi_trPARENT ] );
- }
- }
- return( NULL );
- } /* Neighbor */
-
-static ubi_btNodePtr Border( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe,
- ubi_btNodePtr p,
- int whichway )
- /* ------------------------------------------------------------------------ **
- * Given starting point p, which has a key value equal to *FindMe, locate
- * the first (index order) node with the same key value.
- *
- * This function is useful in trees that have can have duplicate keys.
- * For example, consider the following tree:
- * Tree Traversal
- * 2 If <p> points to the root and <whichway> is RIGHT, 3
- * / \ then the return value will be a pointer to the / \
- * 2 2 RIGHT child of the root node. The tree on 2 5
- * / / \ the right shows the order of traversal. / / \
- * 1 2 3 1 4 6
- *
- * Input: RootPtr - Pointer to the tree root structure.
- * FindMe - Key value for comparisons.
- * p - Pointer to the starting-point node.
- * whichway - the direction in which to travel to find the
- * neighbor, i.e., the RIGHT neighbor or the LEFT
- * neighbor.
- *
- * Output: A pointer to the first (index, or "traversal", order) node with
- * a Key value that matches *FindMe.
- *
- * Notes: If whichway is PARENT, or if the tree does not allow duplicate
- * keys, this function will return <p>.
- * ------------------------------------------------------------------------ **
- */
- {
- register ubi_btNodePtr q;
-
- /* Exit if there's nothing that can be done. */
- if( !ubi_trDups_OK( RootPtr ) || (ubi_trPARENT == whichway) )
- return( p );
-
- /* First, if needed, move up the tree. We need to get to the root of the
- * subtree that contains all of the matching nodes.
- */
- q = p->Link[ubi_trPARENT];
- while( (NULL != q)
- && (ubi_trEQUAL == ubi_trAbNormal( (*(RootPtr->cmp))(FindMe, q) )) )
- {
- p = q;
- q = p->Link[ubi_trPARENT];
- }
-
- /* Next, move back down in the "whichway" direction. */
- q = p->Link[whichway];
- while( NULL != q )
- {
- q = qFind( RootPtr->cmp, FindMe, q );
- if( q )
- {
- p = q;
- q = p->Link[whichway];
- }
- }
- return( p );
- } /* Border */
-
-
-/* ========================================================================== **
- * Exported utilities.
- */
-
-long ubi_btSgn( register long x )
- /* ------------------------------------------------------------------------ **
- * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}.
- *
- * Input: x - a signed long integer value.
- *
- * Output: the "sign" of x, represented as follows:
- * -1 == negative
- * 0 == zero (no sign)
- * 1 == positive
- *
- * Note: This utility is provided in order to facilitate the conversion
- * of C comparison function return values into BinTree direction
- * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the
- * ubi_trAbNormal() conversion macro!
- *
- * ------------------------------------------------------------------------ **
- */
- {
- return( (x)?((x>0)?(1):(-1)):(0) );
- } /* ubi_btSgn */
-
-ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr )
- /* ------------------------------------------------------------------------ **
- * Initialize a tree node.
- *
- * Input: a pointer to a ubi_btNode structure to be initialized.
- * Output: a pointer to the initialized ubi_btNode structure (ie. the
- * same as the input pointer).
- * ------------------------------------------------------------------------ **
- */
- {
- NodePtr->Link[ ubi_trLEFT ] = NULL;
- NodePtr->Link[ ubi_trPARENT ] = NULL;
- NodePtr->Link[ ubi_trRIGHT ] = NULL;
- NodePtr->gender = ubi_trEQUAL;
- NodePtr->balance = ubi_trEQUAL;
- return( NodePtr );
- } /* ubi_btInitNode */
-
-ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr,
- ubi_btCompFunc CompFunc,
- char Flags )
- /* ------------------------------------------------------------------------ **
- * Initialize the fields of a Tree Root header structure.
- *
- * Input: RootPtr - a pointer to an ubi_btRoot structure to be
- * initialized.
- * CompFunc - a pointer to a comparison function that will be used
- * whenever nodes in the tree must be compared against
- * outside values.
- * Flags - One bytes worth of flags. Flags include
- * ubi_trOVERWRITE and ubi_trDUPKEY. See the header
- * file for more info.
- *
- * Output: a pointer to the initialized ubi_btRoot structure (ie. the
- * same value as RootPtr).
- *
- * Note: The interface to this function has changed from that of
- * previous versions. The <Flags> parameter replaces two
- * boolean parameters that had the same basic effect.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- if( RootPtr )
- {
- RootPtr->root = NULL;
- RootPtr->count = 0L;
- RootPtr->cmp = CompFunc;
- RootPtr->flags = (Flags & ubi_trDUPKEY) ? ubi_trDUPKEY : Flags;
- } /* There are only two supported flags, and they are
- * mutually exclusive. ubi_trDUPKEY takes precedence
- * over ubi_trOVERWRITE.
- */
- return( RootPtr );
- } /* ubi_btInitTree */
-
-ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr,
- ubi_btNodePtr NewNode,
- ubi_btItemPtr ItemPtr,
- ubi_btNodePtr *OldNode )
- /* ------------------------------------------------------------------------ **
- * This function uses a non-recursive algorithm to add a new element to the
- * tree.
- *
- * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
- * the root of the tree to which NewNode is to be added.
- * NewNode - a pointer to an ubi_btNode structure that is NOT
- * part of any tree.
- * ItemPtr - A pointer to the sort key that is stored within
- * *NewNode. ItemPtr MUST point to information stored
- * in *NewNode or an EXACT DUPLICATE. The key data
- * indicated by ItemPtr is used to place the new node
- * into the tree.
- * OldNode - a pointer to an ubi_btNodePtr. When searching
- * the tree, a duplicate node may be found. If
- * duplicates are allowed, then the new node will
- * be simply placed into the tree. If duplicates
- * are not allowed, however, then one of two things
- * may happen.
- * 1) if overwritting *is not* allowed, this
- * function will return FALSE (indicating that
- * the new node could not be inserted), and
- * *OldNode will point to the duplicate that is
- * still in the tree.
- * 2) if overwritting *is* allowed, then this
- * function will swap **OldNode for *NewNode.
- * In this case, *OldNode will point to the node
- * that was removed (thus allowing you to free
- * the node).
- * ** If you are using overwrite mode, ALWAYS **
- * ** check the return value of this parameter! **
- * Note: You may pass NULL in this parameter, the
- * function knows how to cope. If you do this,
- * however, there will be no way to return a
- * pointer to an old (ie. replaced) node (which is
- * a problem if you are using overwrite mode).
- *
- * Output: a boolean value indicating success or failure. The function
- * will return FALSE if the node could not be added to the tree.
- * Such failure will only occur if duplicates are not allowed,
- * nodes cannot be overwritten, AND a duplicate key was found
- * within the tree.
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr OtherP,
- parent = NULL;
- char tmp;
-
- if( NULL == OldNode ) /* If they didn't give us a pointer, supply our own. */
- OldNode = &OtherP;
-
- (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */
-
- /* Find a place for the new node. */
- *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp));
-
- /* Now add the node to the tree... */
- if( NULL == (*OldNode) ) /* The easy one: we have a space for a new node! */
- {
- if( NULL == parent )
- RootPtr->root = NewNode;
- else
- {
- parent->Link[(int)tmp] = NewNode;
- NewNode->Link[ubi_trPARENT] = parent;
- NewNode->gender = tmp;
- }
- (RootPtr->count)++;
- return( ubi_trTRUE );
- }
-
- /* If we reach this point, we know that a duplicate node exists. This
- * section adds the node to the tree if duplicate keys are allowed.
- */
- if( ubi_trDups_OK(RootPtr) ) /* Key exists, add duplicate */
- {
- ubi_btNodePtr q;
-
- tmp = ubi_trRIGHT;
- q = (*OldNode);
- *OldNode = NULL;
- while( NULL != q )
- {
- parent = q;
- if( tmp == ubi_trEQUAL )
- tmp = ubi_trRIGHT;
- q = q->Link[(int)tmp];
- if ( q )
- tmp = ubi_trAbNormal( (*(RootPtr->cmp))(ItemPtr, q) );
- }
- parent->Link[(int)tmp] = NewNode;
- NewNode->Link[ubi_trPARENT] = parent;
- NewNode->gender = tmp;
- (RootPtr->count)++;
- return( ubi_trTRUE );
- }
-
- /* If we get to *this* point, we know that we are not allowed to have
- * duplicate nodes, but our node keys match, so... may we replace the
- * old one?
- */
- if( ubi_trOvwt_OK(RootPtr) ) /* Key exists, we replace */
- {
- if( NULL == parent )
- ReplaceNode( &(RootPtr->root), *OldNode, NewNode );
- else
- ReplaceNode( &(parent->Link[(int)((*OldNode)->gender)]),
- *OldNode, NewNode );
- return( ubi_trTRUE );
- }
-
- return( ubi_trFALSE ); /* Failure: could not replace an existing node. */
- } /* ubi_btInsert */
-
-ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr,
- ubi_btNodePtr DeadNode )
- /* ------------------------------------------------------------------------ **
- * This function removes the indicated node from the tree.
- *
- * Input: RootPtr - A pointer to the header of the tree that contains
- * the node to be removed.
- * DeadNode - A pointer to the node that will be removed.
- *
- * Output: This function returns a pointer to the node that was removed
- * from the tree (ie. the same as DeadNode).
- *
- * Note: The node MUST be in the tree indicated by RootPtr. If not,
- * strange and evil things will happen to your trees.
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr p,
- *parentp;
- int tmp;
-
- /* if the node has both left and right subtrees, then we have to swap
- * it with another node. The other node we choose will be the Prev()ious
- * node, which is garunteed to have no RIGHT child.
- */
- if( (NULL != DeadNode->Link[ubi_trLEFT])
- && (NULL != DeadNode->Link[ubi_trRIGHT]) )
- SwapNodes( RootPtr, DeadNode, ubi_btPrev( DeadNode ) );
-
- /* The parent of the node to be deleted may be another node, or it may be
- * the root of the tree. Since we're not sure, it's best just to have
- * a pointer to the parent pointer, whatever it is.
- */
- if( NULL == DeadNode->Link[ubi_trPARENT] )
- parentp = &( RootPtr->root );
- else
- parentp = &((DeadNode->Link[ubi_trPARENT])->Link[(int)(DeadNode->gender)]);
-
- /* Now link the parent to the only grand-child and patch up the gender. */
- tmp = ((DeadNode->Link[ubi_trLEFT])?ubi_trLEFT:ubi_trRIGHT);
-
- p = (DeadNode->Link[tmp]);
- if( NULL != p )
- {
- p->Link[ubi_trPARENT] = DeadNode->Link[ubi_trPARENT];
- p->gender = DeadNode->gender;
- }
- (*parentp) = p;
-
- /* Finished, reduce the node count and return. */
- (RootPtr->count)--;
- return( DeadNode );
- } /* ubi_btRemove */
-
-ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe,
- ubi_trCompOps CompOp )
- /* ------------------------------------------------------------------------ **
- * The purpose of ubi_btLocate() is to find a node or set of nodes given
- * a target value and a "comparison operator". The Locate() function is
- * more flexible and (in the case of trees that may contain dupicate keys)
- * more precise than the ubi_btFind() function. The latter is faster,
- * but it only searches for exact matches and, if the tree contains
- * duplicates, Find() may return a pointer to any one of the duplicate-
- * keyed records.
- *
- * Input:
- * RootPtr - A pointer to the header of the tree to be searched.
- * FindMe - An ubi_btItemPtr that indicates the key for which to
- * search.
- * CompOp - One of the following:
- * CompOp Return a pointer to the node with
- * ------ ---------------------------------
- * ubi_trLT - the last key value that is less
- * than FindMe.
- * ubi_trLE - the first key matching FindMe, or
- * the last key that is less than
- * FindMe.
- * ubi_trEQ - the first key matching FindMe.
- * ubi_trGE - the first key matching FindMe, or the
- * first key greater than FindMe.
- * ubi_trGT - the first key greater than FindMe.
- * Output:
- * A pointer to the node matching the criteria listed above under
- * CompOp, or NULL if no node matched the criteria.
- *
- * Notes:
- * In the case of trees with duplicate keys, Locate() will behave as
- * follows:
- *
- * Find: 3 Find: 3
- * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6
- * ^ ^ ^ ^ ^
- * LT EQ GT LE GE
- *
- * That is, when returning a pointer to a node with a key that is LESS
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * LAST matching node.
- * When returning a pointer to a node with a key that is GREATER
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * FIRST matching node.
- *
- * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf().
- * ------------------------------------------------------------------------ **
- */
- {
- register ubi_btNodePtr p;
- ubi_btNodePtr parent;
- char whichkid;
-
- /* Start by searching for a matching node. */
- p = TreeFind( FindMe,
- RootPtr->root,
- &parent,
- &whichkid,
- RootPtr->cmp );
-
- if( NULL != p ) /* If we have found a match, we can resolve as follows: */
- {
- switch( CompOp )
- {
- case ubi_trLT: /* It's just a jump to the left... */
- p = Border( RootPtr, FindMe, p, ubi_trLEFT );
- return( Neighbor( p, ubi_trLEFT ) );
- case ubi_trGT: /* ...and then a jump to the right. */
- p = Border( RootPtr, FindMe, p, ubi_trRIGHT );
- return( Neighbor( p, ubi_trRIGHT ) );
- default:
- p = Border( RootPtr, FindMe, p, ubi_trLEFT );
- return( p );
- }
- }
-
- /* Else, no match. */
- if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */
- return( NULL ); /* ...forget it. */
-
- /* We can still return a valid result for GT, GE, LE, and LT.
- * <parent> points to a node with a value that is either just before or
- * just after the target value.
- * Remaining possibilities are LT and GT (including LE & GE).
- */
- if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) )
- return( (ubi_trLEFT == whichkid) ? Neighbor( parent, whichkid ) : parent );
- else
- return( (ubi_trRIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent );
- } /* ubi_btLocate */
-
-ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe )
- /* ------------------------------------------------------------------------ **
- * This function performs a non-recursive search of a tree for any node
- * matching a specific key.
- *
- * Input:
- * RootPtr - a pointer to the header of the tree to be searched.
- * FindMe - a pointer to the key value for which to search.
- *
- * Output:
- * A pointer to a node with a key that matches the key indicated by
- * FindMe, or NULL if no such node was found.
- *
- * Note: In a tree that allows duplicates, the pointer returned *might
- * not* point to the (sequentially) first occurance of the
- * desired key. In such a tree, it may be more useful to use
- * ubi_btLocate().
- * ------------------------------------------------------------------------ **
- */
- {
- return( qFind( RootPtr->cmp, FindMe, RootPtr->root ) );
- } /* ubi_btFind */
-
-ubi_btNodePtr ubi_btNext( ubi_btNodePtr P )
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) Next node in the
- * tree.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "next" node in the tree, or NULL if P pointed
- * to the "last" node in the tree or was NULL.
- * ------------------------------------------------------------------------ **
- */
- {
- return( Neighbor( P, ubi_trRIGHT ) );
- } /* ubi_btNext */
-
-ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P )
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) Previous node in
- * the tree.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "previous" node in the tree, or NULL if P
- * pointed to the "first" node in the tree or was NULL.
- * ------------------------------------------------------------------------ **
- */
- {
- return( Neighbor( P, ubi_trLEFT ) );
- } /* ubi_btPrev */
-
-ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P )
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) First node in the
- * subtree of which *P is the root.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "first" node in a subtree that has *P as its
- * root. This function will return NULL only if P is NULL.
- * Note: In general, you will be passing in the value of the root field
- * of an ubi_btRoot structure.
- * ------------------------------------------------------------------------ **
- */
- {
- return( SubSlide( P, ubi_trLEFT ) );
- } /* ubi_btFirst */
-
-ubi_btNodePtr ubi_btLast( ubi_btNodePtr P )
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) Last node in the
- * subtree of which *P is the root.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "last" node in a subtree that has *P as its
- * root. This function will return NULL only if P is NULL.
- * Note: In general, you will be passing in the value of the root field
- * of an ubi_btRoot structure.
- * ------------------------------------------------------------------------ **
- */
- {
- return( SubSlide( P, ubi_trRIGHT ) );
- } /* ubi_btLast */
-
-ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr,
- ubi_btItemPtr MatchMe,
- ubi_btNodePtr p )
- /* ------------------------------------------------------------------------ **
- * Given a tree that a allows duplicate keys, and a pointer to a node in
- * the tree, this function will return a pointer to the first (traversal
- * order) node with the same key value.
- *
- * Input: RootPtr - A pointer to the root of the tree.
- * MatchMe - A pointer to the key value. This should probably
- * point to the key within node *p.
- * p - A pointer to a node in the tree.
- * Output: A pointer to the first node in the set of nodes with keys
- * matching <FindMe>.
- * Notes: Node *p MUST be in the set of nodes with keys matching
- * <FindMe>. If not, this function will return NULL.
- *
- * 4.7: Bug found & fixed by Massimo Campostrini,
- * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- /* If our starting point is invalid, return NULL. */
- if( (NULL == p)
- || (ubi_trEQUAL != ubi_trAbNormal( (*(RootPtr->cmp))( MatchMe, p ) )) )
- return( NULL );
- return( Border( RootPtr, MatchMe, p, ubi_trLEFT ) );
- } /* ubi_btFirstOf */
-
-ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr,
- ubi_btItemPtr MatchMe,
- ubi_btNodePtr p )
- /* ------------------------------------------------------------------------ **
- * Given a tree that a allows duplicate keys, and a pointer to a node in
- * the tree, this function will return a pointer to the last (traversal
- * order) node with the same key value.
- *
- * Input: RootPtr - A pointer to the root of the tree.
- * MatchMe - A pointer to the key value. This should probably
- * point to the key within node *p.
- * p - A pointer to a node in the tree.
- * Output: A pointer to the last node in the set of nodes with keys
- * matching <FindMe>.
- * Notes: Node *p MUST be in the set of nodes with keys matching
- * <FindMe>. If not, this function will return NULL.
- *
- * 4.7: Bug found & fixed by Massimo Campostrini,
- * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- /* If our starting point is invalid, return NULL. */
- if( (NULL != p)
- || (ubi_trEQUAL != ubi_trAbNormal( (*(RootPtr->cmp))( MatchMe, p ) )) )
- return( NULL );
- return( Border( RootPtr, MatchMe, p, ubi_trRIGHT ) );
- } /* ubi_btLastOf */
-
-unsigned long ubi_btTraverse( ubi_btRootPtr RootPtr,
- ubi_btActionRtn EachNode,
- void *UserData )
- /* ------------------------------------------------------------------------ **
- * Traverse a tree in sorted order (non-recursively). At each node, call
- * (*EachNode)(), passing a pointer to the current node, and UserData as the
- * second parameter.
- *
- * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates
- * the tree to be traversed.
- * EachNode - a pointer to a function to be called at each node
- * as the node is visited.
- * UserData - a generic pointer that may point to anything that
- * you choose.
- *
- * Output: A count of the number of nodes visited. This will be zero
- * if the tree is empty.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr p = ubi_btFirst( RootPtr->root );
- unsigned long count = 0;
-
- while( NULL != p )
- {
- (*EachNode)( p, UserData );
- count++;
- p = ubi_btNext( p );
- }
- return( count );
- } /* ubi_btTraverse */
-
-unsigned long ubi_btKillTree( ubi_btRootPtr RootPtr,
- ubi_btKillNodeRtn FreeNode )
- /* ------------------------------------------------------------------------ **
- * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot
- * structure. Return a count of the number of nodes deleted.
- *
- * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates
- * the root of the tree to delete.
- * FreeNode - a function that will be called for each node in the
- * tree to deallocate the memory used by the node.
- *
- * Output: The number of nodes removed from the tree.
- * A value of 0 will be returned if:
- * - The tree actually contains 0 entries.
- * - the value of <RootPtr> is NULL, in which case the tree is
- * assumed to be empty
- * - the value of <FreeNode> is NULL, in which case entries
- * cannot be removed, so 0 is returned. *Make sure that you
- * provide a valid value for <FreeNode>*.
- * In all other cases, you should get a positive value equal to
- * the value of RootPtr->count upon entry.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr p, q;
- unsigned long count = 0;
-
- if( (NULL == RootPtr) || (NULL == FreeNode) )
- return( 0 );
-
- p = ubi_btFirst( RootPtr->root );
- while( NULL != p )
- {
- q = p;
- while( q->Link[ubi_trRIGHT] )
- q = SubSlide( q->Link[ubi_trRIGHT], ubi_trLEFT );
- p = q->Link[ubi_trPARENT];
- if( NULL != p )
- p->Link[ ((p->Link[ubi_trLEFT] == q)?ubi_trLEFT:ubi_trRIGHT) ] = NULL;
- (*FreeNode)((void *)q);
- count++;
- }
-
- /* overkill... */
- (void)ubi_btInitTree( RootPtr,
- RootPtr->cmp,
- RootPtr->flags );
- return( count );
- } /* ubi_btKillTree */
-
-ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
- /* ------------------------------------------------------------------------ **
- * Returns a pointer to a leaf node.
- *
- * Input: leader - Pointer to a node at which to start the descent.
- *
- * Output: A pointer to a leaf node, selected in a somewhat arbitrary
- * manner but with an effort to dig deep.
- *
- * Notes: I wrote this function because I was using splay trees as a
- * database cache. The cache had a maximum size on it, and I
- * needed a way of choosing a node to sacrifice if the cache
- * became full. In a splay tree, less recently accessed nodes
- * tend toward the bottom of the tree, meaning that leaf nodes
- * are good candidates for removal. (I really can't think of
- * any other reason to use this function.)
- * + In a simple binary tree, or in an AVL tree, the most recently
- * added nodes tend to be nearer the bottom, making this a *bad*
- * way to choose which node to remove from the cache.
- * + Randomizing the traversal order is probably a good idea. You
- * can improve the randomization of leaf node selection by passing
- * in pointers to nodes other than the root node each time. A
- * pointer to any node in the tree will do. Of course, if you
- * pass a pointer to a leaf node you'll get the same thing back.
- * + In an unbalanced splay tree, if you simply traverse downward
- * until you hit a leaf node it is possible to accidentally
- * stumble onto a short path. The result will be a leaf node
- * that is actually very high in the tree--possibly a very
- * recently accessed node. Not good. This function can follow
- * multiple paths in an effort to find a leaf node deeper
- * in the tree. Following a single path, of course, is the
- * fastest way to find a leaf node. A complete traversal would
- * be sure to find the deepest leaf but would be very costly in
- * terms of time. This function uses a compromise that has
- * worked well in testing.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- #define MAXPATHS 4 /* Set higher for more maximum paths, lower for fewer. */
- ubi_trNodePtr p[MAXPATHS];
- ubi_trNodePtr q[MAXPATHS];
- int whichway = ubi_trLEFT;
- int paths;
- int i, j;
-
- /* If the subtree is empty, return NULL.
- */
- if( NULL == leader )
- return( NULL );
-
- /* Initialize the p[] array with a pointer to the single node we've been
- * given as a starting point.
- */
- p[0] = leader;
- paths = 1;
- while( paths > 0 )
- {
- for( i = 0; i < paths; i++ )
- q[i] = p[i];
-
- for( i = j = 0; (i < paths) && (j < MAXPATHS); i++ )
- {
- if( NULL != q[i]->Link[whichway] )
- p[j++] = q[i]->Link[whichway];
- whichway = ubi_trRevWay( whichway );
- if( (j < MAXPATHS) && (NULL != q[i]->Link[whichway]) )
- p[j++] = q[i]->Link[whichway];
- }
- paths = j;
- }
-
- return( q[0] );
- } /* ubi_btLeafNode */
-
-int ubi_btModuleID( int size, char *list[] )
- /* ------------------------------------------------------------------------ **
- * Returns a set of strings that identify the module.
- *
- * Input: size - The number of elements in the array <list>.
- * list - An array of pointers of type (char *). This array
- * should, initially, be empty. This function will fill
- * in the array with pointers to strings.
- * Output: The number of elements of <list> that were used. If this value
- * is less than <size>, the values of the remaining elements are
- * not guaranteed.
- *
- * Notes: Please keep in mind that the pointers returned indicate strings
- * stored in static memory. Don't free() them, don't write over
- * them, etc. Just read them.
- * ------------------------------------------------------------------------ **
- */
- {
- if( size > 0 )
- {
- list[0] = ModuleID;
- if( size > 1 )
- list[1] = NULL;
- return( 1 );
- }
- return( 0 );
- } /* ubi_btModuleID */
-
-
-/* ========================================================================== */
diff --git a/source/ubiqx/ubi_BinTree.h b/source/ubiqx/ubi_BinTree.h
deleted file mode 100644
index 43ca1a98716..00000000000
--- a/source/ubiqx/ubi_BinTree.h
+++ /dev/null
@@ -1,887 +0,0 @@
-#ifndef UBI_BINTREE_H
-#define UBI_BINTREE_H
-/* ========================================================================== **
- * ubi_BinTree.h
- *
- * Copyright (C) 1991-1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- *
- * This module implements a simple binary tree.
- *
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_BinTree.h,v
- * Revision 4.12 2004/06/06 04:51:56 crh
- * Fixed a small typo in ubi_BinTree.c (leftover testing cruft).
- * Did a small amount of formatting touchup to ubi_BinTree.h.
- *
- * Revision 4.11 2004/06/06 03:14:09 crh
- * Rewrote the ubi_btLeafNode() function. It now takes several paths in an
- * effort to find a deeper leaf node. There is a small amount of extra
- * overhead, but it is limited.
- *
- * Revision 4.10 2000/06/06 20:38:40 crh
- * In the ReplaceNode() function, the old node header was being copied
- * to the new node header using a byte-by-byte copy. This was causing
- * the 'insure' software testing program to report a memory leak. The
- * fix was to do a simple assignement: *newnode = *oldnode;
- * This quieted the (errant) memory leak reports and is probably a bit
- * faster than the bytewise copy.
- *
- * Revision 4.9 2000/01/08 23:24:30 crh
- * Clarified a variety of if( pointer ) lines, replacing them with
- * if( NULL != pointer ). This is more correct, and I have heard
- * of at least one (obscure?) system out there that uses a non-zero
- * value for NULL.
- * Also, speed improvement in Neighbor(). It was comparing pointers
- * when it could have compared two gender values. The pointer
- * comparison was somewhat indirect (does pointer equal the pointer
- * of the parent of the node pointed to by pointer). Urq.
- *
- * Revision 4.8 1999/09/22 03:40:30 crh
- * Modified ubi_btTraverse() and ubi_btKillTree(). They now return an
- * unsigned long indicating the number of nodes processed. The change
- * is subtle. An empty tree formerly returned False, and now returns
- * zero.
- *
- * Revision 4.7 1998/10/21 06:15:07 crh
- * Fixed bugs in FirstOf() and LastOf() reported by Massimo Campostrini.
- * See function comments.
- *
- * Revision 4.6 1998/07/25 17:02:10 crh
- * Added the ubi_trNewTree() macro.
- *
- * Revision 4.5 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 4.4 1998/06/03 17:42:46 crh
- * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is
- * included by all of the binary tree files.
- *
- * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in
- * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping
- * of tree types by simply changing a header. Unfortunately, the
- * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will
- * conflict if used together. You must either choose a single tree
- * type, or use the underlying function calls directly. Compare
- * the two header files for more information.
- *
- * Revision 4.3 1998/06/02 01:28:43 crh
- * Changed ubi_null.h to sys_include.h to make it more generic.
- *
- * Revision 4.2 1998/05/20 04:32:36 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- * Also, the balance and gender fields of the node were declared as
- * signed char. As I understand it, at least one SunOS or Solaris
- * compiler doesn't like "signed char". The declarations were
- * wrong anyway, so I changed them to simple "char".
- *
- * Revision 4.1 1998/03/31 06:13:47 crh
- * Thomas Aglassinger sent E'mail pointing out errors in the
- * dereferencing of function pointers, and a missing typecast.
- * Thanks, Thomas!
- *
- * Revision 4.0 1998/03/10 03:16:04 crh
- * Added the AVL field 'balance' to the ubi_btNode structure. This means
- * that all BinTree modules now use the same basic node structure, which
- * greatly simplifies the AVL module.
- * Decided that this was a big enough change to justify a new major revision
- * number. 3.0 was an error, so we're at 4.0.
- *
- * Revision 2.6 1998/01/24 06:27:30 crh
- * Added ubi_trCount() macro.
- *
- * Revision 2.5 1997/12/23 03:59:21 crh
- * In this version, all constants & macros defined in the header file have
- * the ubi_tr prefix. Also cleaned up anything that gcc complained about
- * when run with '-pedantic -fsyntax-only -Wall'.
- *
- * Revision 2.4 1997/07/26 04:11:14 crh
- * + Just to be annoying I changed ubi_TRUE and ubi_FALSE to ubi_trTRUE
- * and ubi_trFALSE.
- * + There is now a type ubi_trBool to go with ubi_trTRUE and ubi_trFALSE.
- * + There used to be something called "ubi_TypeDefs.h". I got rid of it.
- * + Added function ubi_btLeafNode().
- *
- * Revision 2.3 1997/06/03 05:15:27 crh
- * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid conflicts.
- * Also changed the interface to function InitTree(). See the comments
- * for this function for more information.
- *
- * Revision 2.2 1995/10/03 22:00:40 CRH
- * Ubisized!
- *
- * Revision 2.1 95/03/09 23:43:46 CRH
- * Added the ModuleID static string and function. These modules are now
- * self-identifying.
- *
- * Revision 2.0 95/02/27 22:00:33 CRH
- * Revision 2.0 of this program includes the following changes:
- *
- * 1) A fix to a major typo in the RepaceNode() function.
- * 2) The addition of the static function Border().
- * 3) The addition of the public functions FirstOf() and LastOf(), which
- * use Border(). These functions are used with trees that allow
- * duplicate keys.
- * 4) A complete rewrite of the Locate() function. Locate() now accepts
- * a "comparison" operator.
- * 5) Overall enhancements to both code and comments.
- *
- * I decided to give this a new major rev number because the interface has
- * changed. In particular, there are two new functions, and changes to the
- * Locate() function.
- *
- * Revision 1.0 93/10/15 22:55:04 CRH
- * With this revision, I have added a set of #define's that provide a single,
- * standard API to all existing tree modules. Until now, each of the three
- * existing modules had a different function and typedef prefix, as follows:
- *
- * Module Prefix
- * ubi_BinTree ubi_bt
- * ubi_AVLtree ubi_avl
- * ubi_SplayTree ubi_spt
- *
- * To further complicate matters, only those portions of the base module
- * (ubi_BinTree) that were superceeded in the new module had the new names.
- * For example, if you were using ubi_SplayTree, the locate function was
- * called "ubi_sptLocate", but the next and previous functions remained
- * "ubi_btNext" and "ubi_btPrev".
- *
- * This was not too terrible if you were familiar with the modules and knew
- * exactly which tree model you wanted to use. If you wanted to be able to
- * change modules (for speed comparisons, etc), things could get messy very
- * quickly.
- *
- * So, I have added a set of defined names that get redefined in any of the
- * descendant modules. To use this standardized interface in your code,
- * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with
- * "ubi_tr". The "ubi_tr" names will resolve to the correct function or
- * datatype names for the module that you are using. Just remember to
- * include the header for that module in your program file. Because these
- * names are handled by the preprocessor, there is no added run-time
- * overhead.
- *
- * Note that the original names do still exist, and can be used if you wish
- * to write code directly to a specific module. This should probably only be
- * done if you are planning to implement a new descendant type, such as
- * red/black trees. CRH
- *
- * V0.0 - June, 1991 - Written by Christopher R. Hertel (CRH).
- *
- * ========================================================================== **
- */
-
-#include "sys_include.h" /* Global include file, used to adapt the ubiqx
- * modules to the host environment and the project
- * with which the modules will be used. See
- * sys_include.h for more info.
- */
-
-/* -------------------------------------------------------------------------- **
- * Macros and constants.
- *
- * General purpose:
- * ubi_trTRUE - Boolean TRUE.
- * ubi_trFALSE - Boolean FALSE.
- *
- * Flags used in the tree header:
- * ubi_trOVERWRITE - This flag indicates that an existing node may be
- * overwritten by a new node with a matching key.
- * ubi_trDUPKEY - This flag indicates that the tree allows duplicate
- * keys. If the tree does allow duplicates, the
- * overwrite flag is ignored.
- *
- * Node link array index constants: (Each node has an array of three
- * pointers. One to the left, one to the right, and one back to the
- * parent.)
- * ubi_trLEFT - Left child pointer.
- * ubi_trPARENT - Parent pointer.
- * ubi_trRIGHT - Right child pointer.
- * ubi_trEQUAL - Synonym for PARENT.
- *
- * ubi_trCompOps: These values are used in the ubi_trLocate() function.
- * ubi_trLT - request the first instance of the greatest key less than
- * the search key.
- * ubi_trLE - request the first instance of the greatest key that is less
- * than or equal to the search key.
- * ubi_trEQ - request the first instance of key that is equal to the
- * search key.
- * ubi_trGE - request the first instance of a key that is greater than
- * or equal to the search key.
- * ubi_trGT - request the first instance of the first key that is greater
- * than the search key.
- * -------------------------------------------------------------------------- **
- */
-
-#define ubi_trTRUE 0xFF
-#define ubi_trFALSE 0x00
-
-#define ubi_trOVERWRITE 0x01 /* Turn on allow overwrite */
-#define ubi_trDUPKEY 0x02 /* Turn on allow duplicate keys */
-
-/* Pointer array index constants... */
-#define ubi_trLEFT 0x00
-#define ubi_trPARENT 0x01
-#define ubi_trRIGHT 0x02
-#define ubi_trEQUAL ubi_trPARENT
-
-typedef enum {
- ubi_trLT = 1,
- ubi_trLE,
- ubi_trEQ,
- ubi_trGE,
- ubi_trGT
- } ubi_trCompOps;
-
-/* -------------------------------------------------------------------------- **
- * These three macros allow simple manipulation of pointer index values (LEFT,
- * RIGHT, and PARENT).
- *
- * Normalize() - converts {LEFT, PARENT, RIGHT} into {-1, 0 ,1}. C
- * uses {negative, zero, positive} values to indicate
- * {less than, equal to, greater than}.
- * AbNormal() - converts {negative, zero, positive} to {LEFT, PARENT,
- * RIGHT} (opposite of Normalize()). Note: C comparison
- * functions, such as strcmp(), return {negative, zero,
- * positive} values, which are not necessarily {-1, 0,
- * 1}. This macro uses the the ubi_btSgn() function to
- * compensate.
- * RevWay() - converts LEFT to RIGHT and RIGHT to LEFT. PARENT (EQUAL)
- * is left as is.
- * -------------------------------------------------------------------------- **
- */
-
-#define ubi_trNormalize(W) ((char)( (W) - ubi_trEQUAL ))
-#define ubi_trAbNormal(W) ((char)( ((char)ubi_btSgn( (long)(W) )) \
- + ubi_trEQUAL ))
-#define ubi_trRevWay(W) ((char)( ubi_trEQUAL - ((W) - ubi_trEQUAL) ))
-
-/* -------------------------------------------------------------------------- **
- * These macros allow us to quickly read the values of the OVERWRITE and
- * DUPlicate KEY bits of the tree root flags field.
- * -------------------------------------------------------------------------- **
- */
-
-#define ubi_trDups_OK(A) \
- ((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE))
-#define ubi_trOvwt_OK(A) \
- ((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE))
-
-/* -------------------------------------------------------------------------- **
- * Additional Macros...
- *
- * ubi_trCount() - Given a pointer to a tree root, this macro returns the
- * number of nodes currently in the tree.
- *
- * ubi_trNewTree() - This macro makes it easy to declare and initialize a
- * tree header in one step. The line
- *
- * static ubi_trNewTree( MyTree, cmpfn, ubi_trDUPKEY );
- *
- * is equivalent to
- *
- * static ubi_trRoot MyTree[1]
- * = {{ NULL, cmpfn, 0, ubi_trDUPKEY }};
- *
- * -------------------------------------------------------------------------- **
- */
-
-#define ubi_trCount( R ) (((ubi_trRootPtr)(R))->count)
-
-#define ubi_trNewTree( N, C, F ) ubi_trRoot (N)[1] = {{ NULL, (C), 0, (F) }}
-
-/* -------------------------------------------------------------------------- **
- * Typedefs...
- *
- * ubi_trBool - Your typcial true or false...
- *
- * Item Pointer: The ubi_btItemPtr is a generic pointer. It is used to
- * indicate a key that is being searched for within the tree.
- * Searching occurs whenever the ubi_trFind(), ubi_trLocate(),
- * or ubi_trInsert() functions are called.
- * -------------------------------------------------------------------------- **
- */
-
-typedef unsigned char ubi_trBool;
-
-typedef void *ubi_btItemPtr; /* A pointer to key data within a node. */
-
-/* ------------------------------------------------------------------------- **
- * Binary Tree Node Structure: This structure defines the basic elements of
- * the tree nodes. In general you *SHOULD NOT PLAY WITH THESE FIELDS*!
- * But, of course, I have to put the structure into this header so that
- * you can use it as a building block.
- *
- * The fields are as follows:
- * Link - an array of pointers. These pointers are manipulated by
- * the BT routines. The pointers indicate the left and right
- * child nodes and the parent node. By keeping track of the
- * parent pointer, we avoid the need for recursive routines or
- * hand-tooled stacks to keep track of our path back to the
- * root. The use of these pointers is subject to change without
- * notice.
- * gender - a one-byte field indicating whether the node is the RIGHT or
- * LEFT child of its parent. If the node is the root of the
- * tree, gender will be PARENT.
- * balance - only used by the AVL tree module. This field indicates
- * the height balance at a given node. See ubi_AVLtree for
- * details.
- *
- * ------------------------------------------------------------------------- **
- */
-
-typedef struct ubi_btNodeStruct {
- struct ubi_btNodeStruct *Link[ 3 ];
- char gender;
- char balance;
- } ubi_btNode;
-
-typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */
-
-/* ------------------------------------------------------------------------- **
- * The next three typedefs define standard function types used by the binary
- * tree management routines. In particular:
- *
- * ubi_btCompFunc is a pointer to a comparison function. Comparison
- * functions are passed an ubi_btItemPtr and an
- * ubi_btNodePtr. They return a value that is (<0), 0,
- * or (>0) to indicate that the Item is (respectively)
- * "less than", "equal to", or "greater than" the Item
- * contained within the node. (See ubi_btInitTree()).
- * ubi_btActionRtn is a pointer to a function that may be called for each
- * node visited when performing a tree traversal (see
- * ubi_btTraverse()). The function will be passed two
- * parameters: the first is a pointer to a node in the
- * tree, the second is a generic pointer that may point to
- * anything that you like.
- * ubi_btKillNodeRtn is a pointer to a function that will deallocate the
- * memory used by a node (see ubi_btKillTree()). Since
- * memory management is left up to you, deallocation may
- * mean anything that you want it to mean. Just remember
- * that the tree *will* be destroyed and that none of the
- * node pointers will be valid any more.
- * ------------------------------------------------------------------------- **
- */
-
-typedef int (*ubi_btCompFunc)( ubi_btItemPtr, ubi_btNodePtr );
-
-typedef void (*ubi_btActionRtn)( ubi_btNodePtr, void * );
-
-typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr );
-
-/* -------------------------------------------------------------------------- **
- * Tree Root Structure: This structure gives us a convenient handle for
- * accessing whole binary trees. The fields are:
- * root - A pointer to the root node of the tree.
- * count - A count of the number of nodes stored in the tree.
- * cmp - A pointer to the comparison routine to be used when building or
- * searching the tree.
- * flags - A set of bit flags. Two flags are currently defined:
- *
- * ubi_trOVERWRITE - If set, this flag indicates that a new node should
- * (bit 0x01) overwrite an old node if the two have identical
- * keys (ie., the keys are equal).
- * ubi_trDUPKEY - If set, this flag indicates that the tree is
- * (bit 0x02) allowed to contain nodes with duplicate keys.
- *
- * NOTE: ubi_trInsert() tests ubi_trDUPKEY before ubi_trOVERWRITE.
- *
- * All of these values are set when you initialize the root structure by
- * calling ubi_trInitTree().
- * -------------------------------------------------------------------------- **
- */
-
-typedef struct {
- ubi_btNodePtr root; /* A pointer to the root node of the tree */
- ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */
- unsigned long count; /* A count of the number of nodes in the tree */
- char flags; /* Overwrite Y|N, Duplicate keys Y|N... */
- } ubi_btRoot;
-
-typedef ubi_btRoot *ubi_btRootPtr; /* Pointer to an ubi_btRoot structure. */
-
-
-/* -------------------------------------------------------------------------- **
- * Function Prototypes.
- */
-
-long ubi_btSgn( long x );
- /* ------------------------------------------------------------------------ **
- * Return the sign of x; {negative,zero,positive} ==> {-1, 0, 1}.
- *
- * Input: x - a signed long integer value.
- *
- * Output: the "sign" of x, represented as follows:
- * -1 == negative
- * 0 == zero (no sign)
- * 1 == positive
- *
- * Note: This utility is provided in order to facilitate the conversion
- * of C comparison function return values into BinTree direction
- * values: {LEFT, PARENT, EQUAL}. It is INCORPORATED into the
- * AbNormal() conversion macro!
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr );
- /* ------------------------------------------------------------------------ **
- * Initialize a tree node.
- *
- * Input: a pointer to a ubi_btNode structure to be initialized.
- * Output: a pointer to the initialized ubi_btNode structure (ie. the
- * same as the input pointer).
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btRootPtr ubi_btInitTree( ubi_btRootPtr RootPtr,
- ubi_btCompFunc CompFunc,
- char Flags );
- /* ------------------------------------------------------------------------ **
- * Initialize the fields of a Tree Root header structure.
- *
- * Input: RootPtr - a pointer to an ubi_btRoot structure to be
- * initialized.
- * CompFunc - a pointer to a comparison function that will be used
- * whenever nodes in the tree must be compared against
- * outside values.
- * Flags - One bytes worth of flags. Flags include
- * ubi_trOVERWRITE and ubi_trDUPKEY. See the header
- * file for more info.
- *
- * Output: a pointer to the initialized ubi_btRoot structure (ie. the
- * same value as RootPtr).
- *
- * Note: The interface to this function has changed from that of
- * previous versions. The <Flags> parameter replaces two
- * boolean parameters that had the same basic effect.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr,
- ubi_btNodePtr NewNode,
- ubi_btItemPtr ItemPtr,
- ubi_btNodePtr *OldNode );
- /* ------------------------------------------------------------------------ **
- * This function uses a non-recursive algorithm to add a new element to the
- * tree.
- *
- * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
- * the root of the tree to which NewNode is to be added.
- * NewNode - a pointer to an ubi_btNode structure that is NOT
- * part of any tree.
- * ItemPtr - A pointer to the sort key that is stored within
- * *NewNode. ItemPtr MUST point to information stored
- * in *NewNode or an EXACT DUPLICATE. The key data
- * indicated by ItemPtr is used to place the new node
- * into the tree.
- * OldNode - a pointer to an ubi_btNodePtr. When searching
- * the tree, a duplicate node may be found. If
- * duplicates are allowed, then the new node will
- * be simply placed into the tree. If duplicates
- * are not allowed, however, then one of two things
- * may happen.
- * 1) if overwritting *is not* allowed, this
- * function will return FALSE (indicating that
- * the new node could not be inserted), and
- * *OldNode will point to the duplicate that is
- * still in the tree.
- * 2) if overwritting *is* allowed, then this
- * function will swap **OldNode for *NewNode.
- * In this case, *OldNode will point to the node
- * that was removed (thus allowing you to free
- * the node).
- * ** If you are using overwrite mode, ALWAYS **
- * ** check the return value of this parameter! **
- * Note: You may pass NULL in this parameter, the
- * function knows how to cope. If you do this,
- * however, there will be no way to return a
- * pointer to an old (ie. replaced) node (which is
- * a problem if you are using overwrite mode).
- *
- * Output: a boolean value indicating success or failure. The function
- * will return FALSE if the node could not be added to the tree.
- * Such failure will only occur if duplicates are not allowed,
- * nodes cannot be overwritten, AND a duplicate key was found
- * within the tree.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btRemove( ubi_btRootPtr RootPtr,
- ubi_btNodePtr DeadNode );
- /* ------------------------------------------------------------------------ **
- * This function removes the indicated node from the tree.
- *
- * Input: RootPtr - A pointer to the header of the tree that contains
- * the node to be removed.
- * DeadNode - A pointer to the node that will be removed.
- *
- * Output: This function returns a pointer to the node that was removed
- * from the tree (ie. the same as DeadNode).
- *
- * Note: The node MUST be in the tree indicated by RootPtr. If not,
- * strange and evil things will happen to your trees.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe,
- ubi_trCompOps CompOp );
- /* ------------------------------------------------------------------------ **
- * The purpose of ubi_btLocate() is to find a node or set of nodes given
- * a target value and a "comparison operator". The Locate() function is
- * more flexible and (in the case of trees that may contain dupicate keys)
- * more precise than the ubi_btFind() function. The latter is faster,
- * but it only searches for exact matches and, if the tree contains
- * duplicates, Find() may return a pointer to any one of the duplicate-
- * keyed records.
- *
- * Input:
- * RootPtr - A pointer to the header of the tree to be searched.
- * FindMe - An ubi_btItemPtr that indicates the key for which to
- * search.
- * CompOp - One of the following:
- * CompOp Return a pointer to the node with
- * ------ ---------------------------------
- * ubi_trLT - the last key value that is less
- * than FindMe.
- * ubi_trLE - the first key matching FindMe, or
- * the last key that is less than
- * FindMe.
- * ubi_trEQ - the first key matching FindMe.
- * ubi_trGE - the first key matching FindMe, or the
- * first key greater than FindMe.
- * ubi_trGT - the first key greater than FindMe.
- * Output:
- * A pointer to the node matching the criteria listed above under
- * CompOp, or NULL if no node matched the criteria.
- *
- * Notes:
- * In the case of trees with duplicate keys, Locate() will behave as
- * follows:
- *
- * Find: 3 Find: 3
- * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6
- * ^ ^ ^ ^ ^
- * LT EQ GT LE GE
- *
- * That is, when returning a pointer to a node with a key that is LESS
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * LAST matching node.
- * When returning a pointer to a node with a key that is GREATER
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * FIRST matching node.
- *
- * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf().
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btFind( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe );
- /* ------------------------------------------------------------------------ **
- * This function performs a non-recursive search of a tree for any node
- * matching a specific key.
- *
- * Input:
- * RootPtr - a pointer to the header of the tree to be searched.
- * FindMe - a pointer to the key value for which to search.
- *
- * Output:
- * A pointer to a node with a key that matches the key indicated by
- * FindMe, or NULL if no such node was found.
- *
- * Note: In a tree that allows duplicates, the pointer returned *might
- * not* point to the (sequentially) first occurance of the
- * desired key. In such a tree, it may be more useful to use
- * ubi_btLocate().
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btNext( ubi_btNodePtr P );
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) Next node in the
- * tree.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "next" node in the tree, or NULL if P pointed
- * to the "last" node in the tree or was NULL.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btPrev( ubi_btNodePtr P );
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) Previous node in
- * the tree.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "previous" node in the tree, or NULL if P
- * pointed to the "first" node in the tree or was NULL.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btFirst( ubi_btNodePtr P );
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) First node in the
- * subtree of which *P is the root.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "first" node in a subtree that has *P as its
- * root. This function will return NULL only if P is NULL.
- * Note: In general, you will be passing in the value of the root field
- * of an ubi_btRoot structure.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btLast( ubi_btNodePtr P );
- /* ------------------------------------------------------------------------ **
- * Given the node indicated by P, find the (sorted order) Last node in the
- * subtree of which *P is the root.
- * Input: P - a pointer to a node that exists in a binary tree.
- * Output: A pointer to the "last" node in a subtree that has *P as its
- * root. This function will return NULL only if P is NULL.
- * Note: In general, you will be passing in the value of the root field
- * of an ubi_btRoot structure.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btFirstOf( ubi_btRootPtr RootPtr,
- ubi_btItemPtr MatchMe,
- ubi_btNodePtr p );
- /* ------------------------------------------------------------------------ **
- * Given a tree that a allows duplicate keys, and a pointer to a node in
- * the tree, this function will return a pointer to the first (traversal
- * order) node with the same key value.
- *
- * Input: RootPtr - A pointer to the root of the tree.
- * MatchMe - A pointer to the key value. This should probably
- * point to the key within node *p.
- * p - A pointer to a node in the tree.
- * Output: A pointer to the first node in the set of nodes with keys
- * matching <FindMe>.
- * Notes: Node *p MUST be in the set of nodes with keys matching
- * <FindMe>. If not, this function will return NULL.
- *
- * 4.7: Bug found & fixed by Massimo Campostrini,
- * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa.
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btLastOf( ubi_btRootPtr RootPtr,
- ubi_btItemPtr MatchMe,
- ubi_btNodePtr p );
- /* ------------------------------------------------------------------------ **
- * Given a tree that a allows duplicate keys, and a pointer to a node in
- * the tree, this function will return a pointer to the last (traversal
- * order) node with the same key value.
- *
- * Input: RootPtr - A pointer to the root of the tree.
- * MatchMe - A pointer to the key value. This should probably
- * point to the key within node *p.
- * p - A pointer to a node in the tree.
- * Output: A pointer to the last node in the set of nodes with keys
- * matching <FindMe>.
- * Notes: Node *p MUST be in the set of nodes with keys matching
- * <FindMe>. If not, this function will return NULL.
- *
- * 4.7: Bug found & fixed by Massimo Campostrini,
- * Istituto Nazionale di Fisica Nucleare, Sezione di Pisa.
- *
- * ------------------------------------------------------------------------ **
- */
-
-unsigned long ubi_btTraverse( ubi_btRootPtr RootPtr,
- ubi_btActionRtn EachNode,
- void *UserData );
- /* ------------------------------------------------------------------------ **
- * Traverse a tree in sorted order (non-recursively). At each node, call
- * (*EachNode)(), passing a pointer to the current node, and UserData as the
- * second parameter.
- *
- * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates
- * the tree to be traversed.
- * EachNode - a pointer to a function to be called at each node
- * as the node is visited.
- * UserData - a generic pointer that may point to anything that
- * you choose.
- *
- * Output: A count of the number of nodes visited. This will be zero
- * if the tree is empty.
- *
- * ------------------------------------------------------------------------ **
- */
-
-
-unsigned long ubi_btKillTree( ubi_btRootPtr RootPtr,
- ubi_btKillNodeRtn FreeNode );
- /* ------------------------------------------------------------------------ **
- * Delete an entire tree (non-recursively) and reinitialize the ubi_btRoot
- * structure. Return a count of the number of nodes deleted.
- *
- * Input: RootPtr - a pointer to an ubi_btRoot structure that indicates
- * the root of the tree to delete.
- * FreeNode - a function that will be called for each node in the
- * tree to deallocate the memory used by the node.
- *
- * Output: The number of nodes removed from the tree.
- * A value of 0 will be returned if:
- * - The tree actually contains 0 entries.
- * - the value of <RootPtr> is NULL, in which case the tree is
- * assumed to be empty
- * - the value of <FreeNode> is NULL, in which case entries
- * cannot be removed, so 0 is returned. *Make sure that you
- * provide a valid value for <FreeNode>*.
- * In all other cases, you should get a positive value equal to
- * the value of RootPtr->count upon entry.
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
- /* ------------------------------------------------------------------------ **
- * Returns a pointer to a leaf node.
- *
- * Input: leader - Pointer to a node at which to start the descent.
- *
- * Output: A pointer to a leaf node, selected in a somewhat arbitrary
- * manner but with an effort to dig deep.
- *
- * Notes: I wrote this function because I was using splay trees as a
- * database cache. The cache had a maximum size on it, and I
- * needed a way of choosing a node to sacrifice if the cache
- * became full. In a splay tree, less recently accessed nodes
- * tend toward the bottom of the tree, meaning that leaf nodes
- * are good candidates for removal. (I really can't think of
- * any other reason to use this function.)
- * + In a simple binary tree, or in an AVL tree, the most recently
- * added nodes tend to be nearer the bottom, making this a *bad*
- * way to choose which node to remove from the cache.
- * + Randomizing the traversal order is probably a good idea. You
- * can improve the randomization of leaf node selection by passing
- * in pointers to nodes other than the root node each time. A
- * pointer to any node in the tree will do. Of course, if you
- * pass a pointer to a leaf node you'll get the same thing back.
- * + In an unbalanced splay tree, if you simply traverse downward
- * until you hit a leaf node it is possible to accidentally
- * stumble onto a short path. The result will be a leaf node
- * that is actually very high in the tree--possibly a very
- * recently accessed node. Not good. This function can follow
- * multiple paths in an effort to find a leaf node deeper
- * in the tree. Following a single path, of course, is the
- * fastest way to find a leaf node. A complete traversal would
- * be sure to find the deepest leaf but would be very costly in
- * terms of time. This function uses a compromise that has
- * worked well in testing.
- *
- * ------------------------------------------------------------------------ **
- */
-
-
-int ubi_btModuleID( int size, char *list[] );
- /* ------------------------------------------------------------------------ **
- * Returns a set of strings that identify the module.
- *
- * Input: size - The number of elements in the array <list>.
- * list - An array of pointers of type (char *). This array
- * should, initially, be empty. This function will fill
- * in the array with pointers to strings.
- * Output: The number of elements of <list> that were used. If this value
- * is less than <size>, the values of the remaining elements are
- * not guaranteed.
- *
- * Notes: Please keep in mind that the pointers returned indicate strings
- * stored in static memory. Don't free() them, don't write over
- * them, etc. Just read them.
- * ------------------------------------------------------------------------ **
- */
-
-/* -------------------------------------------------------------------------- **
- * Masquarade...
- *
- * This set of defines allows you to write programs that will use any of the
- * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree).
- * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by
- * including the appropriate module header.
- */
-
-#define ubi_trItemPtr ubi_btItemPtr
-
-#define ubi_trNode ubi_btNode
-#define ubi_trNodePtr ubi_btNodePtr
-
-#define ubi_trRoot ubi_btRoot
-#define ubi_trRootPtr ubi_btRootPtr
-
-#define ubi_trCompFunc ubi_btCompFunc
-#define ubi_trActionRtn ubi_btActionRtn
-#define ubi_trKillNodeRtn ubi_btKillNodeRtn
-
-#define ubi_trSgn( x ) ubi_btSgn( x )
-
-#define ubi_trInitNode( Np ) ubi_btInitNode( (ubi_btNodePtr)(Np) )
-
-#define ubi_trInitTree( Rp, Cf, Fl ) \
- ubi_btInitTree( (ubi_btRootPtr)(Rp), (ubi_btCompFunc)(Cf), (Fl) )
-
-#define ubi_trInsert( Rp, Nn, Ip, On ) \
- ubi_btInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \
- (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) )
-
-#define ubi_trRemove( Rp, Dn ) \
- ubi_btRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) )
-
-#define ubi_trLocate( Rp, Ip, Op ) \
- ubi_btLocate( (ubi_btRootPtr)(Rp), \
- (ubi_btItemPtr)(Ip), \
- (ubi_trCompOps)(Op) )
-
-#define ubi_trFind( Rp, Ip ) \
- ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) )
-
-#define ubi_trNext( P ) ubi_btNext( (ubi_btNodePtr)(P) )
-
-#define ubi_trPrev( P ) ubi_btPrev( (ubi_btNodePtr)(P) )
-
-#define ubi_trFirst( P ) ubi_btFirst( (ubi_btNodePtr)(P) )
-
-#define ubi_trLast( P ) ubi_btLast( (ubi_btNodePtr)(P) )
-
-#define ubi_trFirstOf( Rp, Ip, P ) \
- ubi_btFirstOf( (ubi_btRootPtr)(Rp), \
- (ubi_btItemPtr)(Ip), \
- (ubi_btNodePtr)(P) )
-
-#define ubi_trLastOf( Rp, Ip, P ) \
- ubi_btLastOf( (ubi_btRootPtr)(Rp), \
- (ubi_btItemPtr)(Ip), \
- (ubi_btNodePtr)(P) )
-
-#define ubi_trTraverse( Rp, En, Ud ) \
- ubi_btTraverse((ubi_btRootPtr)(Rp), (ubi_btActionRtn)(En), (void *)(Ud))
-
-#define ubi_trKillTree( Rp, Fn ) \
- ubi_btKillTree( (ubi_btRootPtr)(Rp), (ubi_btKillNodeRtn)(Fn) )
-
-#define ubi_trLeafNode( Nd ) \
- ubi_btLeafNode( (ubi_btNodePtr)(Nd) )
-
-#define ubi_trModuleID( s, l ) ubi_btModuleID( s, l )
-
-/* ========================================================================== */
-#endif /* UBI_BINTREE_H */
diff --git a/source/ubiqx/ubi_Cache.c b/source/ubiqx/ubi_Cache.c
deleted file mode 100644
index f428dcefe97..00000000000
--- a/source/ubiqx/ubi_Cache.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/* ========================================================================== **
- * ubi_Cache.c
- *
- * Copyright (C) 1997 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- *
- * This module implements a generic cache.
- *
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * This module uses a splay tree to implement a simple cache. The cache
- * module adds a thin layer of functionality to the splay tree. In
- * particular:
- *
- * - The tree (cache) may be limited in size by the number of
- * entries permitted or the amount of memory used. When either
- * limit is exceeded cache entries are removed until the cache
- * conforms.
- * - Some statistical information is kept so that an approximate
- * "hit ratio" can be calculated.
- * - There are several functions available that provide access to
- * and management of cache size limits, hit ratio, and tree
- * trimming.
- *
- * The splay tree is used because recently accessed items tend toward the
- * top of the tree and less recently accessed items tend toward the bottom.
- * This makes it easy to purge less recently used items should the cache
- * exceed its limits.
- *
- * To use this module, you will need to supply a comparison function of
- * type ubi_trCompFunc and a node-freeing function of type
- * ubi_trKillNodeRtn. See ubi_BinTree.h for more information on
- * these. (This is all basic ubiqx tree management stuff.)
- *
- * Notes:
- *
- * - Cache performance will start to suffer dramatically if the
- * cache becomes large enough to force the OS to start swapping
- * memory to disk. This is because the nodes of the underlying tree
- * will be scattered across memory in an order that is completely
- * unrelated to their traversal order. As more and more of the
- * cache is placed into swap space, more and more swaps will be
- * required for a simple traversal (...and then there's the splay
- * operation).
- *
- * In one simple test under Linux, the load and dump of a cache of
- * 400,000 entries took only 1min, 40sec of real time. The same
- * test with 450,000 records took 2 *hours* and eight minutes.
- *
- * - In an effort to save memory, I considered using an unsigned
- * short to save the per-entry entry size. I would have tucked this
- * value into some unused space in the tree node structure. On
- * 32-bit word aligned systems this would have saved an additional
- * four bytes per entry. I may revisit this issue, but for now I've
- * decided against it.
- *
- * Using an unsigned short would limit the size of an entry to 64K
- * bytes. That's probably more than enough for most applications.
- * The key word in that last sentence, however, is "probably". I
- * really dislike imposing such limits on things.
- *
- * - Each entry keeps track of the amount of memory it used and the
- * cache header keeps the total. This information is provided via
- * the EntrySize parameter in ubi_cachePut(), so it is up to you to
- * make sure that the numbers are accurate. (The numbers don't even
- * have to represent bytes used.)
- *
- * As you consider this, note that the strdup() function--as an
- * example--will call malloc(). The latter generally allocates a
- * multiple of the system word size, which may be more than the
- * number of bytes needed to store the string.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_Cache.c,v
- * Revision 0.4 1999/09/22 03:42:24 crh
- * Fixed a minor typo.
- *
- * Revision 0.3 1998/06/03 18:00:15 crh
- * Further fiddling with sys_include.h, which is no longer explicitly
- * included by this module since it is inherited from ubi_BinTree.h.
- *
- * Revision 0.2 1998/06/02 01:36:18 crh
- * Changed include name from ubi_null.h to sys_include.h to make it
- * more generic.
- *
- * Revision 0.1 1998/05/20 04:36:02 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 0.0 1997/12/18 06:24:33 crh
- * Initial Revision.
- *
- * ========================================================================== **
- */
-
-#include "ubi_Cache.h" /* Header for *this* module. */
-
-/* -------------------------------------------------------------------------- **
- * Static data...
- */
-
-/* commented out until I make use of it...
-static char ModuleID[] =
-"ubi_Cache\n\
-\tRevision: 0.4 \n\
-\tDate: 1999/09/22 03:42:24 \n\
-\tAuthor: crh \n";
-*/
-
-/* -------------------------------------------------------------------------- **
- * Internal functions...
- */
-
-static void free_entry( ubi_cacheRootPtr CachePtr, ubi_cacheEntryPtr EntryPtr )
- /* ------------------------------------------------------------------------ **
- * Free a ubi_cacheEntry, and adjust the mem_used counter accordingly.
- *
- * Input: CachePtr - A pointer to the cache from which the entry has
- * been removed.
- * EntryPtr - A pointer to the already removed entry.
- *
- * Output: none.
- *
- * Notes: The entry must be removed from the cache *before* this function
- * is called!!!!
- * ------------------------------------------------------------------------ **
- */
- {
- CachePtr->mem_used -= EntryPtr->entry_size;
- (*CachePtr->free_func)( (void *)EntryPtr );
- } /* free_entry */
-
-static void cachetrim( ubi_cacheRootPtr crptr )
- /* ------------------------------------------------------------------------ **
- * Remove entries from the cache until the number of entries and the amount
- * of memory used are *both* below or at the maximum.
- *
- * Input: crptr - pointer to the cache to be trimmed.
- *
- * Output: None.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- while( ( crptr->max_entries && (crptr->max_entries < crptr->root.count) )
- || ( crptr->max_memory && (crptr->max_memory < crptr->mem_used) ) )
- {
- if( !ubi_cacheReduce( crptr, 1 ) )
- return;
- }
- } /* cachetrim */
-
-
-/* -------------------------------------------------------------------------- **
- * Exported functions...
- */
-
-ubi_cacheRootPtr ubi_cacheInit( ubi_cacheRootPtr CachePtr,
- ubi_trCompFunc CompFunc,
- ubi_trKillNodeRtn FreeFunc,
- unsigned long MaxEntries,
- unsigned long MaxMemory )
- /* ------------------------------------------------------------------------ **
- * Initialize a cache header structure.
- *
- * Input: CachePtr - A pointer to a ubi_cacheRoot structure that is
- * to be initialized.
- * CompFunc - A pointer to the function that will be called
- * to compare two cache values. See the module
- * comments, above, for more information.
- * FreeFunc - A pointer to a function that will be called
- * to free a cache entry. If you allocated
- * the cache entry using malloc(), then this
- * will likely be free(). If you are allocating
- * cache entries from a free list, then this will
- * likely be a function that returns memory to the
- * free list, etc.
- * MaxEntries - The maximum number of entries that will be
- * allowed to exist in the cache. If this limit
- * is exceeded, then existing entries will be
- * removed from the cache. A value of zero
- * indicates that there is no limit on the number
- * of cache entries. See ubi_cachePut().
- * MaxMemory - The maximum amount of memory, in bytes, to be
- * allocated to the cache (excluding the cache
- * header). If this is exceeded, existing entries
- * in the cache will be removed until enough memory
- * has been freed to meet the condition. See
- * ubi_cachePut().
- *
- * Output: A pointer to the initialized cache (i.e., the same as CachePtr).
- *
- * Notes: Both MaxEntries and MaxMemory may be changed after the cache
- * has been created. See
- * ubi_cacheSetMaxEntries()
- * ubi_cacheSetMaxMemory()
- * ubi_cacheGetMaxEntries()
- * ubi_cacheGetMaxMemory() (the latter two are macros).
- *
- * - Memory is allocated in multiples of the word size. The
- * return value of the strlen() function does not reflect
- * this; it will allways be less than or equal to the amount
- * of memory actually allocated. Keep this in mind when
- * choosing a value for MaxMemory.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- if( CachePtr )
- {
- (void)ubi_trInitTree( CachePtr, CompFunc, ubi_trOVERWRITE );
- CachePtr->free_func = FreeFunc;
- CachePtr->max_entries = MaxEntries;
- CachePtr->max_memory = MaxMemory;
- CachePtr->mem_used = 0;
- CachePtr->cache_hits = 0;
- CachePtr->cache_trys = 0;
- }
- return( CachePtr );
- } /* ubi_cacheInit */
-
-ubi_cacheRootPtr ubi_cacheClear( ubi_cacheRootPtr CachePtr )
- /* ------------------------------------------------------------------------ **
- * Remove and free all entries in an existing cache.
- *
- * Input: CachePtr - A pointer to the cache that is to be cleared.
- *
- * Output: A pointer to the cache header (i.e., the same as CachePtr).
- * This function re-initializes the cache header.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- if( CachePtr )
- {
- (void)ubi_trKillTree( CachePtr, CachePtr->free_func );
- CachePtr->mem_used = 0;
- CachePtr->cache_hits = 0;
- CachePtr->cache_trys = 0;
- }
- return( CachePtr );
- } /* ubi_cacheClear */
-
-void ubi_cachePut( ubi_cacheRootPtr CachePtr,
- unsigned long EntrySize,
- ubi_cacheEntryPtr EntryPtr,
- ubi_trItemPtr Key )
- /* ------------------------------------------------------------------------ **
- * Add an entry to the cache.
- *
- * Input: CachePtr - A pointer to the cache into which the entry
- * will be added.
- * EntrySize - The size, in bytes, of the memory block indicated
- * by EntryPtr. This will be copied into the
- * EntryPtr->entry_size field.
- * EntryPtr - A pointer to a memory block that begins with a
- * ubi_cacheEntry structure. The entry structure
- * should be followed immediately by the data to be
- * cached (even if that is a pointer to yet more data).
- * Key - Pointer used to identify the lookup key within the
- * Entry.
- *
- * Output: None.
- *
- * Notes: After adding the new node, the cache is "trimmed". This
- * removes extra nodes if the tree has exceeded it's memory or
- * entry count limits. It is unlikely that the newly added node
- * will be purged from the cache (assuming a reasonably large
- * cache), since new nodes in a splay tree (which is what this
- * module was designed to use) are moved to the top of the tree
- * and the cache purge process removes nodes from the bottom of
- * the tree.
- * - The underlying splay tree is opened in OVERWRITE mode. If
- * the input key matches an existing key, the existing entry will
- * be politely removed from the tree and freed.
- * - Memory is allocated in multiples of the word size. The
- * return value of the strlen() function does not reflect
- * this; it will allways be less than or equal to the amount
- * of memory actually allocated.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_trNodePtr OldNode;
-
- EntryPtr->entry_size = EntrySize;
- CachePtr->mem_used += EntrySize;
- (void)ubi_trInsert( CachePtr, EntryPtr, Key, &OldNode );
- if( OldNode )
- free_entry( CachePtr, (ubi_cacheEntryPtr)OldNode );
-
- cachetrim( CachePtr );
- } /* ubi_cachePut */
-
-ubi_cacheEntryPtr ubi_cacheGet( ubi_cacheRootPtr CachePtr,
- ubi_trItemPtr FindMe )
- /* ------------------------------------------------------------------------ **
- * Attempt to retrieve an entry from the cache.
- *
- * Input: CachePtr - A ponter to the cache that is to be searched.
- * FindMe - A ubi_trItemPtr that indicates the key for which
- * to search.
- *
- * Output: A pointer to the cache entry that was found, or NULL if no
- * matching entry was found.
- *
- * Notes: This function also updates the hit ratio counters.
- * The counters are unsigned short. If the number of cache tries
- * reaches 32768, then both the number of tries and the number of
- * hits are divided by two. This prevents the counters from
- * overflowing. See the comments in ubi_cacheHitRatio() for
- * additional notes.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_trNodePtr FoundPtr;
-
- FoundPtr = ubi_trFind( CachePtr, FindMe );
-
- if( FoundPtr )
- CachePtr->cache_hits++;
- CachePtr->cache_trys++;
-
- if( CachePtr->cache_trys & 0x8000 )
- {
- CachePtr->cache_hits = CachePtr->cache_hits / 2;
- CachePtr->cache_trys = CachePtr->cache_trys / 2;
- }
-
- return( (ubi_cacheEntryPtr)FoundPtr );
- } /* ubi_cacheGet */
-
-ubi_trBool ubi_cacheDelete( ubi_cacheRootPtr CachePtr, ubi_trItemPtr DeleteMe )
- /* ------------------------------------------------------------------------ **
- * Find and delete the specified cache entry.
- *
- * Input: CachePtr - A pointer to the cache.
- * DeleteMe - The key of the entry to be deleted.
- *
- * Output: TRUE if the entry was found & freed, else FALSE.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_trNodePtr FoundPtr;
-
- FoundPtr = ubi_trFind( CachePtr, DeleteMe );
- if( FoundPtr )
- {
- (void)ubi_trRemove( CachePtr, FoundPtr );
- free_entry( CachePtr, (ubi_cacheEntryPtr)FoundPtr );
- return( ubi_trTRUE );
- }
- return( ubi_trFALSE );
- } /* ubi_cacheDelete */
-
-ubi_trBool ubi_cacheReduce( ubi_cacheRootPtr CachePtr, unsigned long count )
- /* ------------------------------------------------------------------------ **
- * Remove <count> entries from the bottom of the cache.
- *
- * Input: CachePtr - A pointer to the cache which is to be reduced in
- * size.
- * count - The number of entries to remove.
- *
- * Output: The function will return TRUE if <count> entries were removed,
- * else FALSE. A return value of FALSE should indicate that
- * there were less than <count> entries in the cache, and that the
- * cache is now empty.
- *
- * Notes: This function forces a reduction in the number of cache entries
- * without requiring that the MaxMemory or MaxEntries values be
- * changed.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_trNodePtr NodePtr;
-
- while( count )
- {
- NodePtr = ubi_trLeafNode( CachePtr->root.root );
- if( NULL == NodePtr )
- return( ubi_trFALSE );
- else
- {
- (void)ubi_trRemove( CachePtr, NodePtr );
- free_entry( CachePtr, (ubi_cacheEntryPtr)NodePtr );
- }
- count--;
- }
- return( ubi_trTRUE );
- } /* ubi_cacheReduce */
-
-unsigned long ubi_cacheSetMaxEntries( ubi_cacheRootPtr CachePtr,
- unsigned long NewSize )
- /* ------------------------------------------------------------------------ **
- * Change the maximum number of entries allowed to exist in the cache.
- *
- * Input: CachePtr - A pointer to the cache to be modified.
- * NewSize - The new maximum number of cache entries.
- *
- * Output: The maximum number of entries previously allowed to exist in
- * the cache.
- *
- * Notes: If the new size is less than the old size, this function will
- * trim the cache (remove excess entries).
- * - A value of zero indicates an unlimited number of entries.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- unsigned long oldsize = CachePtr->max_entries; /* Save the old value. */
-
- CachePtr->max_entries = NewSize; /* Apply the new value. */
- if( (NewSize < oldsize) || (NewSize && !oldsize) ) /* If size is smaller, */
- cachetrim( CachePtr ); /* remove excess. */
- return( oldsize );
- } /* ubi_cacheSetMaxEntries */
-
-unsigned long ubi_cacheSetMaxMemory( ubi_cacheRootPtr CachePtr,
- unsigned long NewSize )
- /* ------------------------------------------------------------------------ **
- * Change the maximum amount of memory to be used for storing cache
- * entries.
- *
- * Input: CachePtr - A pointer to the cache to be modified.
- * NewSize - The new cache memory size.
- *
- * Output: The previous maximum memory size.
- *
- * Notes: If the new size is less than the old size, this function will
- * trim the cache (remove excess entries).
- * - A value of zero indicates that the cache has no memory limit.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- unsigned long oldsize = CachePtr->max_memory; /* Save the old value. */
-
- CachePtr->max_memory = NewSize; /* Apply the new value. */
- if( (NewSize < oldsize) || (NewSize && !oldsize) ) /* If size is smaller, */
- cachetrim( CachePtr ); /* remove excess. */
- return( oldsize );
- } /* ubi_cacheSetMaxMemory */
-
-int ubi_cacheHitRatio( ubi_cacheRootPtr CachePtr )
- /* ------------------------------------------------------------------------ **
- * Returns a value that is 10,000 times the slightly weighted average hit
- * ratio for the cache.
- *
- * Input: CachePtr - Pointer to the cache to be queried.
- *
- * Output: An integer that is 10,000 times the number of successful
- * cache hits divided by the number of cache lookups, or:
- * (10000 * hits) / trys
- * You can easily convert this to a float, or do something
- * like this (where i is the return value of this function):
- *
- * printf( "Hit rate : %d.%02d%%\n", (i/100), (i%100) );
- *
- * Notes: I say "slightly-weighted", because the numerator and
- * denominator are both accumulated in locations of type
- * 'unsigned short'. If the number of cache trys becomes
- * large enough, both are divided by two. (See function
- * ubi_cacheGet().)
- * Dividing both numerator and denominator by two does not
- * change the ratio (much...it is an integer divide), but it
- * does mean that subsequent increments to either counter will
- * have twice as much significance as previous ones.
- *
- * - The value returned by this function will be in the range
- * [0..10000] because ( 0 <= cache_hits <= cache_trys ) will
- * always be true.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int tmp = 0;
-
- if( CachePtr->cache_trys )
- tmp = (int)( (10000 * (long)(CachePtr->cache_hits) )
- / (long)(CachePtr->cache_trys) );
- return( tmp );
- } /* ubi_cacheHitRatio */
-
-/* -------------------------------------------------------------------------- */
diff --git a/source/ubiqx/ubi_Cache.h b/source/ubiqx/ubi_Cache.h
deleted file mode 100644
index 0fc3a074f72..00000000000
--- a/source/ubiqx/ubi_Cache.h
+++ /dev/null
@@ -1,412 +0,0 @@
-#ifndef UBI_CACHE_H
-#define UBI_CACHE_H
-/* ========================================================================== **
- * ubi_Cache.h
- *
- * Copyright (C) 1997 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- *
- * This module implements a generic cache.
- *
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * This module uses a splay tree to implement a simple cache. The cache
- * module adds a thin layer of functionality to the splay tree. In
- * particular:
- *
- * - The tree (cache) may be limited in size by the number of
- * entries permitted or the amount of memory used. When either
- * limit is exceeded cache entries are removed until the cache
- * conforms.
- * - Some statistical information is kept so that an approximate
- * "hit ratio" can be calculated.
- * - There are several functions available that provide access to
- * and management of cache size limits, hit ratio, and tree
- * trimming.
- *
- * The splay tree is used because recently accessed items tend toward the
- * top of the tree and less recently accessed items tend toward the bottom.
- * This makes it easy to purge less recently used items should the cache
- * exceed its limits.
- *
- * To use this module, you will need to supply a comparison function of
- * type ubi_trCompFunc and a node-freeing function of type
- * ubi_trKillNodeRtn. See ubi_BinTree.h for more information on
- * these. (This is all basic ubiqx tree management stuff.)
- *
- * Notes:
- *
- * - Cache performance will start to suffer dramatically if the
- * cache becomes large enough to force the OS to start swapping
- * memory to disk. This is because the nodes of the underlying tree
- * will be scattered across memory in an order that is completely
- * unrelated to their traversal order. As more and more of the
- * cache is placed into swap space, more and more swaps will be
- * required for a simple traversal (...and then there's the splay
- * operation).
- *
- * In one simple test under Linux, the load and dump of a cache of
- * 400,000 entries took only 1min, 40sec of real time. The same
- * test with 450,000 records took 2 *hours* and eight minutes.
- *
- * - In an effort to save memory, I considered using an unsigned
- * short to save the per-entry entry size. I would have tucked this
- * value into some unused space in the tree node structure. On
- * 32-bit word aligned systems this would have saved an additional
- * four bytes per entry. I may revisit this issue, but for now I've
- * decided against it.
- *
- * Using an unsigned short would limit the size of an entry to 64K
- * bytes. That's probably more than enough for most applications.
- * The key word in that last sentence, however, is "probably". I
- * really dislike imposing such limits on things.
- *
- * - Each entry keeps track of the amount of memory it used and the
- * cache header keeps the total. This information is provided via
- * the EntrySize parameter in ubi_cachePut(), so it is up to you to
- * make sure that the numbers are accurate. (The numbers don't even
- * have to represent bytes used.)
- *
- * As you consider this, note that the strdup() function--as an
- * example--will call malloc(). The latter generally allocates a
- * multiple of the system word size, which may be more than the
- * number of bytes needed to store the string.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_Cache.h,v
- * Revision 0.4 1999/09/22 03:42:24 crh
- * Fixed a minor typo.
- *
- * Revision 0.3 1998/06/03 18:00:15 crh
- * Further fiddling with sys_include.h, which is no longer explicitly
- * included by this module since it is inherited from ubi_BinTree.h.
- *
- * Revision 0.2 1998/06/02 01:36:18 crh
- * Changed include name from ubi_null.h to sys_include.h to make it
- * more generic.
- *
- * Revision 0.1 1998/05/20 04:36:02 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 0.0 1997/12/18 06:25:23 crh
- * Initial Revision.
- *
- * ========================================================================== **
- */
-
-#include "ubi_SplayTree.h"
-
-/* -------------------------------------------------------------------------- **
- * Typedefs...
- *
- * ubi_cacheRoot - Cache header structure, which consists of a binary
- * tree root and other required housekeeping fields, as
- * listed below.
- * ubi_cacheRootPtr - Pointer to a Cache.
- *
- * ubi_cacheEntry - A cache Entry, which consists of a tree node
- * structure and the size (in bytes) of the entry
- * data. The entry size should be supplied via
- * the EntrySize parameter of the ubi_cachePut()
- * function.
- *
- * ubi_cacheEntryPtr - Pointer to a ubi_cacheEntry.
- *
- */
-
-typedef struct
- {
- ubi_trRoot root; /* Splay tree control structure. */
- ubi_trKillNodeRtn free_func; /* Function used to free entries. */
- unsigned long max_entries; /* Max cache entries. 0 == unlimited */
- unsigned long max_memory; /* Max memory to use. 0 == unlimited */
- unsigned long mem_used; /* Memory currently in use (bytes). */
- unsigned short cache_hits; /* Incremented on succesful find. */
- unsigned short cache_trys; /* Incremented on cache lookup. */
- } ubi_cacheRoot;
-
-typedef ubi_cacheRoot *ubi_cacheRootPtr;
-
-
-typedef struct
- {
- ubi_trNode node; /* Tree node structure. */
- unsigned long entry_size; /* Entry size. Used when managing
- * caches with maximum memory limits.
- */
- } ubi_cacheEntry;
-
-typedef ubi_cacheEntry *ubi_cacheEntryPtr;
-
-
-/* -------------------------------------------------------------------------- **
- * Macros...
- *
- * ubi_cacheGetMaxEntries() - Report the current maximum number of entries
- * allowed in the cache. Zero indicates no
- * maximum.
- * ubi_cacheGetMaxMemory() - Report the current maximum amount of memory
- * that may be used in the cache. Zero
- * indicates no maximum.
- * ubi_cacheGetEntryCount() - Report the current number of entries in the
- * cache.
- * ubi_cacheGetMemUsed() - Report the amount of memory currently in use
- * by the cache.
- */
-
-#define ubi_cacheGetMaxEntries( Cptr ) (((ubi_cacheRootPtr)(Cptr))->max_entries)
-#define ubi_cacheGetMaxMemory( Cptr ) (((ubi_cacheRootPtr)(Cptr))->max_memory)
-
-#define ubi_cacheGetEntryCount( Cptr ) (((ubi_cacheRootPtr)(Cptr))->root.count)
-#define ubi_cacheGetMemUsed( Cptr ) (((ubi_cacheRootPtr)(Cptr))->mem_used)
-
-/* -------------------------------------------------------------------------- **
- * Prototypes...
- */
-
-ubi_cacheRootPtr ubi_cacheInit( ubi_cacheRootPtr CachePtr,
- ubi_trCompFunc CompFunc,
- ubi_trKillNodeRtn FreeFunc,
- unsigned long MaxEntries,
- unsigned long MaxMemory );
- /* ------------------------------------------------------------------------ **
- * Initialize a cache header structure.
- *
- * Input: CachePtr - A pointer to a ubi_cacheRoot structure that is
- * to be initialized.
- * CompFunc - A pointer to the function that will be called
- * to compare two cache values. See the module
- * comments, above, for more information.
- * FreeFunc - A pointer to a function that will be called
- * to free a cache entry. If you allocated
- * the cache entry using malloc(), then this
- * will likely be free(). If you are allocating
- * cache entries from a free list, then this will
- * likely be a function that returns memory to the
- * free list, etc.
- * MaxEntries - The maximum number of entries that will be
- * allowed to exist in the cache. If this limit
- * is exceeded, then existing entries will be
- * removed from the cache. A value of zero
- * indicates that there is no limit on the number
- * of cache entries. See ubi_cachePut().
- * MaxMemory - The maximum amount of memory, in bytes, to be
- * allocated to the cache (excluding the cache
- * header). If this is exceeded, existing entries
- * in the cache will be removed until enough memory
- * has been freed to meet the condition. See
- * ubi_cachePut().
- *
- * Output: A pointer to the initialized cache (i.e., the same as CachePtr).
- *
- * Notes: Both MaxEntries and MaxMemory may be changed after the cache
- * has been created. See
- * ubi_cacheSetMaxEntries()
- * ubi_cacheSetMaxMemory()
- * ubi_cacheGetMaxEntries()
- * ubi_cacheGetMaxMemory() (the latter two are macros).
- *
- * - Memory is allocated in multiples of the word size. The
- * return value of the strlen() function does not reflect
- * this; it will allways be less than or equal to the amount
- * of memory actually allocated. Keep this in mind when
- * choosing a value for MaxMemory.
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_cacheRootPtr ubi_cacheClear( ubi_cacheRootPtr CachePtr );
- /* ------------------------------------------------------------------------ **
- * Remove and free all entries in an existing cache.
- *
- * Input: CachePtr - A pointer to the cache that is to be cleared.
- *
- * Output: A pointer to the cache header (i.e., the same as CachePtr).
- * This function re-initializes the cache header.
- *
- * ------------------------------------------------------------------------ **
- */
-
-void ubi_cachePut( ubi_cacheRootPtr CachePtr,
- unsigned long EntrySize,
- ubi_cacheEntryPtr EntryPtr,
- ubi_trItemPtr Key );
- /* ------------------------------------------------------------------------ **
- * Add an entry to the cache.
- *
- * Input: CachePtr - A pointer to the cache into which the entry
- * will be added.
- * EntrySize - The size, in bytes, of the memory block indicated
- * by EntryPtr. This will be copied into the
- * EntryPtr->entry_size field.
- * EntryPtr - A pointer to a memory block that begins with a
- * ubi_cacheEntry structure. The entry structure
- * should be followed immediately by the data to be
- * cached (even if that is a pointer to yet more data).
- * Key - Pointer used to identify the lookup key within the
- * Entry.
- *
- * Output: None.
- *
- * Notes: After adding the new node, the cache is "trimmed". This
- * removes extra nodes if the tree has exceeded it's memory or
- * entry count limits. It is unlikely that the newly added node
- * will be purged from the cache (assuming a reasonably large
- * cache), since new nodes in a splay tree (which is what this
- * module was designed to use) are moved to the top of the tree
- * and the cache purge process removes nodes from the bottom of
- * the tree.
- * - The underlying splay tree is opened in OVERWRITE mode. If
- * the input key matches an existing key, the existing entry will
- * be politely removed from the tree and freed.
- * - Memory is allocated in multiples of the word size. The
- * return value of the strlen() function does not reflect
- * this; it will allways be less than or equal to the amount
- * of memory actually allocated.
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_cacheEntryPtr ubi_cacheGet( ubi_cacheRootPtr CachePtr,
- ubi_trItemPtr FindMe );
- /* ------------------------------------------------------------------------ **
- * Attempt to retrieve an entry from the cache.
- *
- * Input: CachePtr - A ponter to the cache that is to be searched.
- * FindMe - A ubi_trItemPtr that indicates the key for which
- * to search.
- *
- * Output: A pointer to the cache entry that was found, or NULL if no
- * matching entry was found.
- *
- * Notes: This function also updates the hit ratio counters.
- * The counters are unsigned short. If the number of cache tries
- * reaches 32768, then both the number of tries and the number of
- * hits are divided by two. This prevents the counters from
- * overflowing. See the comments in ubi_cacheHitRatio() for
- * additional notes.
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_trBool ubi_cacheDelete( ubi_cacheRootPtr CachePtr, ubi_trItemPtr DeleteMe );
- /* ------------------------------------------------------------------------ **
- * Find and delete the specified cache entry.
- *
- * Input: CachePtr - A pointer to the cache.
- * DeleteMe - The key of the entry to be deleted.
- *
- * Output: TRUE if the entry was found & freed, else FALSE.
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_trBool ubi_cacheReduce( ubi_cacheRootPtr CachePtr, unsigned long count );
- /* ------------------------------------------------------------------------ **
- * Remove <count> entries from the bottom of the cache.
- *
- * Input: CachePtr - A pointer to the cache which is to be reduced in
- * size.
- * count - The number of entries to remove.
- *
- * Output: The function will return TRUE if <count> entries were removed,
- * else FALSE. A return value of FALSE should indicate that
- * there were less than <count> entries in the cache, and that the
- * cache is now empty.
- *
- * Notes: This function forces a reduction in the number of cache entries
- * without requiring that the MaxMemory or MaxEntries values be
- * changed.
- *
- * ------------------------------------------------------------------------ **
- */
-
-unsigned long ubi_cacheSetMaxEntries( ubi_cacheRootPtr CachePtr,
- unsigned long NewSize );
- /* ------------------------------------------------------------------------ **
- * Change the maximum number of entries allowed to exist in the cache.
- *
- * Input: CachePtr - A pointer to the cache to be modified.
- * NewSize - The new maximum number of cache entries.
- *
- * Output: The maximum number of entries previously allowed to exist in
- * the cache.
- *
- * Notes: If the new size is less than the old size, this function will
- * trim the cache (remove excess entries).
- * - A value of zero indicates an unlimited number of entries.
- *
- * ------------------------------------------------------------------------ **
- */
-
-unsigned long ubi_cacheSetMaxMemory( ubi_cacheRootPtr CachePtr,
- unsigned long NewSize );
- /* ------------------------------------------------------------------------ **
- * Change the maximum amount of memory to be used for storing cache
- * entries.
- *
- * Input: CachePtr - A pointer to the cache to be modified.
- * NewSize - The new cache memory size.
- *
- * Output: The previous maximum memory size.
- *
- * Notes: If the new size is less than the old size, this function will
- * trim the cache (remove excess entries).
- * - A value of zero indicates that the cache has no memory limit.
- *
- * ------------------------------------------------------------------------ **
- */
-
-int ubi_cacheHitRatio( ubi_cacheRootPtr CachePtr );
- /* ------------------------------------------------------------------------ **
- * Returns a value that is 10,000 times the slightly weighted average hit
- * ratio for the cache.
- *
- * Input: CachePtr - Pointer to the cache to be queried.
- *
- * Output: An integer that is 10,000 times the number of successful
- * cache hits divided by the number of cache lookups, or:
- * (10000 * hits) / trys
- * You can easily convert this to a float, or do something
- * like this (where i is the return value of this function):
- *
- * printf( "Hit rate : %d.%02d%%\n", (i/100), (i%100) );
- *
- * Notes: I say "slightly-weighted", because the numerator and
- * denominator are both accumulated in locations of type
- * 'unsigned short'. If the number of cache trys becomes
- * large enough, both are divided by two. (See function
- * ubi_cacheGet().)
- * Dividing both numerator and denominator by two does not
- * change the ratio (much...it is an integer divide), but it
- * does mean that subsequent increments to either counter will
- * have twice as much significance as previous ones.
- *
- * - The value returned by this function will be in the range
- * [0..10000] because ( 0 <= cache_hits <= cache_trys ) will
- * always be true.
- *
- * ------------------------------------------------------------------------ **
- */
-
-/* -------------------------------------------------------------------------- */
-#endif /* ubi_CACHE_H */
diff --git a/source/ubiqx/ubi_SplayTree.c b/source/ubiqx/ubi_SplayTree.c
deleted file mode 100644
index 222506bd06b..00000000000
--- a/source/ubiqx/ubi_SplayTree.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/* ========================================================================== **
- * ubi_SplayTree.c
- *
- * Copyright (C) 1993-1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- *
- * This module implements "splay" trees. Splay trees are binary trees
- * that are rearranged (splayed) whenever a node is accessed. The
- * splaying process *tends* to make the tree bushier (improves balance),
- * and the nodes that are accessed most frequently *tend* to be closer to
- * the top.
- *
- * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and
- * Robert Tarjan. Journal of the Association for Computing
- * Machinery Vol 32, No. 3, July 1985 pp. 652-686
- *
- * See also: http://www.cs.cmu.edu/~sleator/
- *
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_SplayTree.c,v
- * Revision 4.5 2000/01/08 23:26:49 crh
- * Added ubi_trSplay() macro, which does a type cast for us.
- *
- * Revision 4.4 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 4.3 1998/06/03 17:45:05 crh
- * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is
- * included by all of the binary tree files.
- *
- * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem
- * to like syntax like this:
- *
- * if( (a = b) )
- *
- * The fix was to change lines like the above to:
- *
- * if( 0 != (a=b) )
- *
- * Which means the same thing.
- *
- * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in
- * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping
- * of tree types by simply changing a header. Unfortunately, the
- * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will
- * conflict if used together. You must either choose a single tree
- * type, or use the underlying function calls directly. Compare
- * the two header files for more information.
- *
- * Revision 4.2 1998/06/02 01:29:14 crh
- * Changed ubi_null.h to sys_include.h to make it more generic.
- *
- * Revision 4.1 1998/05/20 04:37:54 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 4.0 1998/03/10 03:41:33 crh
- * Minor comment changes. The revision number is now 4.0 to match the
- * BinTree and AVLtree modules.
- *
- * Revision 2.7 1998/01/24 06:37:08 crh
- * Added a URL for more information.
- *
- * Revision 2.6 1997/12/23 04:01:12 crh
- * In this version, all constants & macros defined in the header file have
- * the ubi_tr prefix. Also cleaned up anything that gcc complained about
- * when run with '-pedantic -fsyntax-only -Wall'.
- *
- * Revision 2.5 1997/07/26 04:15:42 crh
- * + Cleaned up a few minor syntax annoyances that gcc discovered for me.
- * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE.
- *
- * Revision 2.4 1997/06/03 04:42:21 crh
- * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing
- * problems.
- *
- * Revision 2.3 1995/10/03 22:19:07 CRH
- * Ubisized!
- * Also, added the function ubi_sptSplay().
- *
- * Revision 2.1 95/03/09 23:54:42 CRH
- * Added the ModuleID static string and function. These modules are now
- * self-identifying.
- *
- * Revision 2.0 95/02/27 22:34:46 CRH
- * This module was updated to match the interface changes made to the
- * ubi_BinTree module. In particular, the interface to the Locate() function
- * has changed. See ubi_BinTree for more information on changes and new
- * functions.
- *
- * The revision number was also upped to match ubi_BinTree.
- *
- * Revision 1.1 93/10/18 20:35:16 CRH
- * I removed the hard-coded logical device names from the include file
- * specifications. CRH
- *
- * Revision 1.0 93/10/15 23:00:15 CRH
- * With this revision, I have added a set of #define's that provide a single,
- * standard API to all existing tree modules. Until now, each of the three
- * existing modules had a different function and typedef prefix, as follows:
- *
- * Module Prefix
- * ubi_BinTree ubi_bt
- * ubi_AVLtree ubi_avl
- * ubi_SplayTree ubi_spt
- *
- * To further complicate matters, only those portions of the base module
- * (ubi_BinTree) that were superceeded in the new module had the new names.
- * For example, if you were using ubi_SplayTree, the locate function was
- * called "ubi_sptLocate", but the next and previous functions remained
- * "ubi_btNext" and "ubi_btPrev".
- *
- * This was not too terrible if you were familiar with the modules and knew
- * exactly which tree model you wanted to use. If you wanted to be able to
- * change modules (for speed comparisons, etc), things could get messy very
- * quickly.
- *
- * So, I have added a set of defined names that get redefined in any of the
- * descendant modules. To use this standardized interface in your code,
- * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with
- * "ubi_tr". The "ubi_tr" names will resolve to the correct function or
- * datatype names for the module that you are using. Just remember to
- * include the header for that module in your program file. Because these
- * names are handled by the preprocessor, there is no added run-time
- * overhead.
- *
- * Note that the original names do still exist, and can be used if you wish
- * to write code directly to a specific module. This should probably only be
- * done if you are planning to implement a new descendant type, such as
- * red/black trees. CRH
- *
- * Revision 0.1 93/04/25 22:03:32 CRH
- * Simply changed the <exec/types.h> #include reference the .c file to
- * use <stdlib.h> instead. The latter is portable, the former is not.
- *
- * Revision 0.0 93/04/21 23:05:52 CRH
- * Initial version, written by Christopher R. Hertel.
- * This module implements Splay Trees using the ubi_BinTree module as a basis.
- *
- * ========================================================================== **
- */
-
-#include "ubi_SplayTree.h" /* Header for THIS module. */
-
-/* ========================================================================== **
- * Static data.
- */
-
-static char ModuleID[] = "ubi_SplayTree\n\
-\tRevision: 4.5 \n\
-\tDate: 2000/01/08 23:26:49 \n\
-\tAuthor: crh \n";
-
-
-/* ========================================================================== **
- * Private functions...
- */
-
-static void Rotate( ubi_btNodePtr p )
- /* ------------------------------------------------------------------------ **
- * This function performs a single rotation, moving node *p up one level
- * in the tree.
- *
- * Input: p - a pointer to an ubi_btNode in a tree.
- *
- * Output: None.
- *
- * Notes: This implements a single rotation in either direction (left
- * or right). This is the basic building block of all splay
- * tree rotations.
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr parentp;
- ubi_btNodePtr tmp;
- char way;
- char revway;
-
- parentp = p->Link[ubi_trPARENT]; /* Find parent. */
-
- if( parentp ) /* If no parent, then we're already the root. */
- {
- way = p->gender;
- revway = ubi_trRevWay(way);
- tmp = p->Link[(int)revway];
-
- parentp->Link[(int)way] = tmp;
- if( tmp )
- {
- tmp->Link[ubi_trPARENT] = parentp;
- tmp->gender = way;
- }
-
- tmp = parentp->Link[ubi_trPARENT];
- p->Link[ubi_trPARENT] = tmp;
- p->gender = parentp->gender;
- if( tmp )
- tmp->Link[(int)(p->gender)] = p;
-
- parentp->Link[ubi_trPARENT] = p;
- parentp->gender = revway;
- p->Link[(int)revway] = parentp;
- }
- } /* Rotate */
-
-static ubi_btNodePtr Splay( ubi_btNodePtr SplayWithMe )
- /* ------------------------------------------------------------------------ **
- * Move the node indicated by SplayWithMe to the root of the tree by
- * splaying the tree.
- *
- * Input: SplayWithMe - A pointer to an ubi_btNode within a tree.
- *
- * Output: A pointer to the root of the splay tree (i.e., the same as
- * SplayWithMe).
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr parent;
-
- while( NULL != (parent = SplayWithMe->Link[ubi_trPARENT]) )
- {
- if( parent->gender == SplayWithMe->gender ) /* Zig-Zig */
- Rotate( parent );
- else
- {
- if( ubi_trEQUAL != parent->gender ) /* Zig-Zag */
- Rotate( SplayWithMe );
- }
- Rotate( SplayWithMe ); /* Zig */
- } /* while */
- return( SplayWithMe );
- } /* Splay */
-
-/* ========================================================================== **
- * Exported utilities.
- */
-
-ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr,
- ubi_btNodePtr NewNode,
- ubi_btItemPtr ItemPtr,
- ubi_btNodePtr *OldNode )
- /* ------------------------------------------------------------------------ **
- * This function uses a non-recursive algorithm to add a new element to the
- * splay tree.
- *
- * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
- * the root of the tree to which NewNode is to be added.
- * NewNode - a pointer to an ubi_btNode structure that is NOT
- * part of any tree.
- * ItemPtr - A pointer to the sort key that is stored within
- * *NewNode. ItemPtr MUST point to information stored
- * in *NewNode or an EXACT DUPLICATE. The key data
- * indicated by ItemPtr is used to place the new node
- * into the tree.
- * OldNode - a pointer to an ubi_btNodePtr. When searching
- * the tree, a duplicate node may be found. If
- * duplicates are allowed, then the new node will
- * be simply placed into the tree. If duplicates
- * are not allowed, however, then one of two things
- * may happen.
- * 1) if overwritting *is not* allowed, this
- * function will return FALSE (indicating that
- * the new node could not be inserted), and
- * *OldNode will point to the duplicate that is
- * still in the tree.
- * 2) if overwritting *is* allowed, then this
- * function will swap **OldNode for *NewNode.
- * In this case, *OldNode will point to the node
- * that was removed (thus allowing you to free
- * the node).
- * ** If you are using overwrite mode, ALWAYS **
- * ** check the return value of this parameter! **
- * Note: You may pass NULL in this parameter, the
- * function knows how to cope. If you do this,
- * however, there will be no way to return a
- * pointer to an old (ie. replaced) node (which is
- * a problem if you are using overwrite mode).
- *
- * Output: a boolean value indicating success or failure. The function
- * will return FALSE if the node could not be added to the tree.
- * Such failure will only occur if duplicates are not allowed,
- * nodes cannot be overwritten, AND a duplicate key was found
- * within the tree.
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr OtherP;
-
- if( !(OldNode) )
- OldNode = &OtherP;
-
- if( ubi_btInsert( RootPtr, NewNode, ItemPtr, OldNode ) )
- {
- RootPtr->root = Splay( NewNode );
- return( ubi_trTRUE );
- }
-
- /* Splay the unreplacable, duplicate keyed, unique, old node. */
- RootPtr->root = Splay( (*OldNode) );
- return( ubi_trFALSE );
- } /* ubi_sptInsert */
-
-ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode )
- /* ------------------------------------------------------------------------ **
- * This function removes the indicated node from the tree.
- *
- * Input: RootPtr - A pointer to the header of the tree that contains
- * the node to be removed.
- * DeadNode - A pointer to the node that will be removed.
- *
- * Output: This function returns a pointer to the node that was removed
- * from the tree (ie. the same as DeadNode).
- *
- * Note: The node MUST be in the tree indicated by RootPtr. If not,
- * strange and evil things will happen to your trees.
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr p;
-
- (void)Splay( DeadNode ); /* Move dead node to root. */
- if( NULL != (p = DeadNode->Link[ubi_trLEFT]) )
- { /* If left subtree exists... */
- ubi_btNodePtr q = DeadNode->Link[ubi_trRIGHT];
-
- p->Link[ubi_trPARENT] = NULL; /* Left subtree node becomes root.*/
- p->gender = ubi_trPARENT;
- p = ubi_btLast( p ); /* Find rightmost left node... */
- p->Link[ubi_trRIGHT] = q; /* ...attach right tree. */
- if( q )
- q->Link[ubi_trPARENT] = p;
- RootPtr->root = Splay( p ); /* Resplay at p. */
- }
- else
- {
- if( NULL != (p = DeadNode->Link[ubi_trRIGHT]) )
- { /* No left, but right subtree exists... */
- p->Link[ubi_trPARENT] = NULL; /* Right subtree root becomes... */
- p->gender = ubi_trPARENT; /* ...overall tree root. */
- RootPtr->root = p;
- }
- else
- RootPtr->root = NULL; /* No subtrees => empty tree. */
- }
-
- (RootPtr->count)--; /* Decrement node count. */
- return( DeadNode ); /* Return pointer to pruned node. */
- } /* ubi_sptRemove */
-
-ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe,
- ubi_trCompOps CompOp )
- /* ------------------------------------------------------------------------ **
- * The purpose of ubi_btLocate() is to find a node or set of nodes given
- * a target value and a "comparison operator". The Locate() function is
- * more flexible and (in the case of trees that may contain dupicate keys)
- * more precise than the ubi_btFind() function. The latter is faster,
- * but it only searches for exact matches and, if the tree contains
- * duplicates, Find() may return a pointer to any one of the duplicate-
- * keyed records.
- *
- * Input:
- * RootPtr - A pointer to the header of the tree to be searched.
- * FindMe - An ubi_btItemPtr that indicates the key for which to
- * search.
- * CompOp - One of the following:
- * CompOp Return a pointer to the node with
- * ------ ---------------------------------
- * ubi_trLT - the last key value that is less
- * than FindMe.
- * ubi_trLE - the first key matching FindMe, or
- * the last key that is less than
- * FindMe.
- * ubi_trEQ - the first key matching FindMe.
- * ubi_trGE - the first key matching FindMe, or the
- * first key greater than FindMe.
- * ubi_trGT - the first key greater than FindMe.
- * Output:
- * A pointer to the node matching the criteria listed above under
- * CompOp, or NULL if no node matched the criteria.
- *
- * Notes:
- * In the case of trees with duplicate keys, Locate() will behave as
- * follows:
- *
- * Find: 3 Find: 3
- * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6
- * ^ ^ ^ ^ ^
- * LT EQ GT LE GE
- *
- * That is, when returning a pointer to a node with a key that is LESS
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * LAST matching node.
- * When returning a pointer to a node with a key that is GREATER
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * FIRST matching node.
- *
- * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf().
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr p;
-
- p = ubi_btLocate( RootPtr, FindMe, CompOp );
- if( p )
- RootPtr->root = Splay( p );
- return( p );
- } /* ubi_sptLocate */
-
-ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe )
- /* ------------------------------------------------------------------------ **
- * This function performs a non-recursive search of a tree for any node
- * matching a specific key.
- *
- * Input:
- * RootPtr - a pointer to the header of the tree to be searched.
- * FindMe - a pointer to the key value for which to search.
- *
- * Output:
- * A pointer to a node with a key that matches the key indicated by
- * FindMe, or NULL if no such node was found.
- *
- * Note: In a tree that allows duplicates, the pointer returned *might
- * not* point to the (sequentially) first occurance of the
- * desired key. In such a tree, it may be more useful to use
- * ubi_sptLocate().
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_btNodePtr p;
-
- p = ubi_btFind( RootPtr, FindMe );
- if( p )
- RootPtr->root = Splay( p );
- return( p );
- } /* ubi_sptFind */
-
-void ubi_sptSplay( ubi_btRootPtr RootPtr,
- ubi_btNodePtr SplayMe )
- /* ------------------------------------------------------------------------ **
- * This function allows you to splay the tree at a given node, thus moving
- * the node to the top of the tree.
- *
- * Input:
- * RootPtr - a pointer to the header of the tree to be splayed.
- * SplayMe - a pointer to a node within the tree. This will become
- * the new root node.
- * Output: None.
- *
- * Notes: This is an uncharacteristic function for this group of modules
- * in that it provides access to the internal balancing routines,
- * which would normally be hidden.
- * Splaying the tree will not damage it (assuming that I've done
- * *my* job), but there is overhead involved. I don't recommend
- * that you use this function unless you understand the underlying
- * Splay Tree principles involved.
- * ------------------------------------------------------------------------ **
- */
- {
- RootPtr->root = Splay( SplayMe );
- } /* ubi_sptSplay */
-
-int ubi_sptModuleID( int size, char *list[] )
- /* ------------------------------------------------------------------------ **
- * Returns a set of strings that identify the module.
- *
- * Input: size - The number of elements in the array <list>.
- * list - An array of pointers of type (char *). This array
- * should, initially, be empty. This function will fill
- * in the array with pointers to strings.
- * Output: The number of elements of <list> that were used. If this value
- * is less than <size>, the values of the remaining elements are
- * not guaranteed.
- *
- * Notes: Please keep in mind that the pointers returned indicate strings
- * stored in static memory. Don't free() them, don't write over
- * them, etc. Just read them.
- * ------------------------------------------------------------------------ **
- */
- {
- if( size > 0 )
- {
- list[0] = ModuleID;
- if( size > 1 )
- return( 1 + ubi_btModuleID( --size, &(list[1]) ) );
- return( 1 );
- }
- return( 0 );
- } /* ubi_sptModuleID */
-
-/* ================================ The End ================================= */
-
diff --git a/source/ubiqx/ubi_SplayTree.h b/source/ubiqx/ubi_SplayTree.h
deleted file mode 100644
index e4fac796a91..00000000000
--- a/source/ubiqx/ubi_SplayTree.h
+++ /dev/null
@@ -1,377 +0,0 @@
-#ifndef UBI_SPLAYTREE_H
-#define UBI_SPLAYTREE_H
-/* ========================================================================== **
- * ubi_SplayTree.h
- *
- * Copyright (C) 1993-1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- *
- * This module implements "splay" trees. Splay trees are binary trees
- * that are rearranged (splayed) whenever a node is accessed. The
- * splaying process *tends* to make the tree bushier (improves balance),
- * and the nodes that are accessed most frequently *tend* to be closer to
- * the top.
- *
- * References: "Self-Adjusting Binary Search Trees", by Daniel Sleator and
- * Robert Tarjan. Journal of the Association for Computing
- * Machinery Vol 32, No. 3, July 1985 pp. 652-686
- *
- * See also: http://www.cs.cmu.edu/~sleator/
- *
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_SplayTree.h,v
- * Revision 4.5 2000/01/08 23:26:49 crh
- * Added ubi_trSplay() macro, which does a type cast for us.
- *
- * Revision 4.4 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 4.3 1998/06/03 17:45:05 crh
- * Further fiddling with sys_include.h. It's now in ubi_BinTree.h which is
- * included by all of the binary tree files.
- *
- * Also fixed some warnings produced by lint on Irix 6.2, which doesn't seem
- * to like syntax like this:
- *
- * if( (a = b) )
- *
- * The fix was to change lines like the above to:
- *
- * if( 0 != (a=b) )
- *
- * Which means the same thing.
- *
- * Reminder: Some of the ubi_tr* macros in ubi_BinTree.h are redefined in
- * ubi_AVLtree.h and ubi_SplayTree.h. This allows easy swapping
- * of tree types by simply changing a header. Unfortunately, the
- * macro redefinitions in ubi_AVLtree.h and ubi_SplayTree.h will
- * conflict if used together. You must either choose a single tree
- * type, or use the underlying function calls directly. Compare
- * the two header files for more information.
- *
- * Revision 4.2 1998/06/02 01:29:14 crh
- * Changed ubi_null.h to sys_include.h to make it more generic.
- *
- * Revision 4.1 1998/05/20 04:37:54 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 4.0 1998/03/10 03:40:57 crh
- * Minor comment changes. The revision number is now 4.0 to match the
- * BinTree and AVLtree modules.
- *
- * Revision 2.7 1998/01/24 06:37:57 crh
- * Added a URL for more information.
- *
- * Revision 2.6 1997/12/23 04:02:20 crh
- * In this version, all constants & macros defined in the header file have
- * the ubi_tr prefix. Also cleaned up anything that gcc complained about
- * when run with '-pedantic -fsyntax-only -Wall'.
- *
- * Revision 2.5 1997/07/26 04:15:46 crh
- * + Cleaned up a few minor syntax annoyances that gcc discovered for me.
- * + Changed ubi_TRUE and ubi_FALSE to ubi_trTRUE and ubi_trFALSE.
- *
- * Revision 2.4 1997/06/03 05:22:56 crh
- * Changed TRUE and FALSE to ubi_TRUE and ubi_FALSE to avoid causing
- * problems.
- *
- * Revision 2.3 1995/10/03 22:19:37 CRH
- * Ubisized!
- * Also, added the function ubi_sptSplay().
- *
- * Revision 2.1 95/03/09 23:55:04 CRH
- * Added the ModuleID static string and function. These modules are now
- * self-identifying.
- *
- * Revision 2.0 95/02/27 22:34:55 CRH
- * This module was updated to match the interface changes made to the
- * ubi_BinTree module. In particular, the interface to the Locate() function
- * has changed. See ubi_BinTree for more information on changes and new
- * functions.
- *
- * The revision number was also upped to match ubi_BinTree.
- *
- *
- * Revision 1.0 93/10/15 22:59:36 CRH
- * With this revision, I have added a set of #define's that provide a single,
- * standard API to all existing tree modules. Until now, each of the three
- * existing modules had a different function and typedef prefix, as follows:
- *
- * Module Prefix
- * ubi_BinTree ubi_bt
- * ubi_AVLtree ubi_avl
- * ubi_SplayTree ubi_spt
- *
- * To further complicate matters, only those portions of the base module
- * (ubi_BinTree) that were superceeded in the new module had the new names.
- * For example, if you were using ubi_SplayTree, the locate function was
- * called "ubi_sptLocate", but the next and previous functions remained
- * "ubi_btNext" and "ubi_btPrev".
- *
- * This was not too terrible if you were familiar with the modules and knew
- * exactly which tree model you wanted to use. If you wanted to be able to
- * change modules (for speed comparisons, etc), things could get messy very
- * quickly.
- *
- * So, I have added a set of defined names that get redefined in any of the
- * descendant modules. To use this standardized interface in your code,
- * simply replace all occurances of "ubi_bt", "ubi_avl", and "ubi_spt" with
- * "ubi_tr". The "ubi_tr" names will resolve to the correct function or
- * datatype names for the module that you are using. Just remember to
- * include the header for that module in your program file. Because these
- * names are handled by the preprocessor, there is no added run-time
- * overhead.
- *
- * Note that the original names do still exist, and can be used if you wish
- * to write code directly to a specific module. This should probably only be
- * done if you are planning to implement a new descendant type, such as
- * red/black trees. CRH
- *
- * Revision 0.0 93/04/21 23:07:13 CRH
- * Initial version, written by Christopher R. Hertel.
- * This module implements Splay Trees using the ubi_BinTree module as a basis.
- *
- * ========================================================================== **
- */
-
-#include "ubi_BinTree.h" /* Base binary tree functions, types, etc. */
-
-/* ========================================================================== **
- * Function prototypes...
- */
-
-ubi_trBool ubi_sptInsert( ubi_btRootPtr RootPtr,
- ubi_btNodePtr NewNode,
- ubi_btItemPtr ItemPtr,
- ubi_btNodePtr *OldNode );
- /* ------------------------------------------------------------------------ **
- * This function uses a non-recursive algorithm to add a new element to the
- * splay tree.
- *
- * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
- * the root of the tree to which NewNode is to be added.
- * NewNode - a pointer to an ubi_btNode structure that is NOT
- * part of any tree.
- * ItemPtr - A pointer to the sort key that is stored within
- * *NewNode. ItemPtr MUST point to information stored
- * in *NewNode or an EXACT DUPLICATE. The key data
- * indicated by ItemPtr is used to place the new node
- * into the tree.
- * OldNode - a pointer to an ubi_btNodePtr. When searching
- * the tree, a duplicate node may be found. If
- * duplicates are allowed, then the new node will
- * be simply placed into the tree. If duplicates
- * are not allowed, however, then one of two things
- * may happen.
- * 1) if overwritting *is not* allowed, this
- * function will return FALSE (indicating that
- * the new node could not be inserted), and
- * *OldNode will point to the duplicate that is
- * still in the tree.
- * 2) if overwritting *is* allowed, then this
- * function will swap **OldNode for *NewNode.
- * In this case, *OldNode will point to the node
- * that was removed (thus allowing you to free
- * the node).
- * ** If you are using overwrite mode, ALWAYS **
- * ** check the return value of this parameter! **
- * Note: You may pass NULL in this parameter, the
- * function knows how to cope. If you do this,
- * however, there will be no way to return a
- * pointer to an old (ie. replaced) node (which is
- * a problem if you are using overwrite mode).
- *
- * Output: a boolean value indicating success or failure. The function
- * will return FALSE if the node could not be added to the tree.
- * Such failure will only occur if duplicates are not allowed,
- * nodes cannot be overwritten, AND a duplicate key was found
- * within the tree.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_sptRemove( ubi_btRootPtr RootPtr, ubi_btNodePtr DeadNode );
- /* ------------------------------------------------------------------------ **
- * This function removes the indicated node from the tree.
- *
- * Input: RootPtr - A pointer to the header of the tree that contains
- * the node to be removed.
- * DeadNode - A pointer to the node that will be removed.
- *
- * Output: This function returns a pointer to the node that was removed
- * from the tree (ie. the same as DeadNode).
- *
- * Note: The node MUST be in the tree indicated by RootPtr. If not,
- * strange and evil things will happen to your trees.
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_sptLocate( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe,
- ubi_trCompOps CompOp );
- /* ------------------------------------------------------------------------ **
- * The purpose of ubi_btLocate() is to find a node or set of nodes given
- * a target value and a "comparison operator". The Locate() function is
- * more flexible and (in the case of trees that may contain dupicate keys)
- * more precise than the ubi_btFind() function. The latter is faster,
- * but it only searches for exact matches and, if the tree contains
- * duplicates, Find() may return a pointer to any one of the duplicate-
- * keyed records.
- *
- * Input:
- * RootPtr - A pointer to the header of the tree to be searched.
- * FindMe - An ubi_btItemPtr that indicates the key for which to
- * search.
- * CompOp - One of the following:
- * CompOp Return a pointer to the node with
- * ------ ---------------------------------
- * ubi_trLT - the last key value that is less
- * than FindMe.
- * ubi_trLE - the first key matching FindMe, or
- * the last key that is less than
- * FindMe.
- * ubi_trEQ - the first key matching FindMe.
- * ubi_trGE - the first key matching FindMe, or the
- * first key greater than FindMe.
- * ubi_trGT - the first key greater than FindMe.
- * Output:
- * A pointer to the node matching the criteria listed above under
- * CompOp, or NULL if no node matched the criteria.
- *
- * Notes:
- * In the case of trees with duplicate keys, Locate() will behave as
- * follows:
- *
- * Find: 3 Find: 3
- * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6
- * ^ ^ ^ ^ ^
- * LT EQ GT LE GE
- *
- * That is, when returning a pointer to a node with a key that is LESS
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * LAST matching node.
- * When returning a pointer to a node with a key that is GREATER
- * THAN the target key (FindMe), Locate() will return a pointer to the
- * FIRST matching node.
- *
- * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf().
- * ------------------------------------------------------------------------ **
- */
-
-ubi_btNodePtr ubi_sptFind( ubi_btRootPtr RootPtr,
- ubi_btItemPtr FindMe );
- /* ------------------------------------------------------------------------ **
- * This function performs a non-recursive search of a tree for any node
- * matching a specific key.
- *
- * Input:
- * RootPtr - a pointer to the header of the tree to be searched.
- * FindMe - a pointer to the key value for which to search.
- *
- * Output:
- * A pointer to a node with a key that matches the key indicated by
- * FindMe, or NULL if no such node was found.
- *
- * Note: In a tree that allows duplicates, the pointer returned *might
- * not* point to the (sequentially) first occurance of the
- * desired key. In such a tree, it may be more useful to use
- * ubi_sptLocate().
- * ------------------------------------------------------------------------ **
- */
-
-void ubi_sptSplay( ubi_btRootPtr RootPtr,
- ubi_btNodePtr SplayMe );
- /* ------------------------------------------------------------------------ **
- * This function allows you to splay the tree at a given node, thus moving
- * the node to the top of the tree.
- *
- * Input:
- * RootPtr - a pointer to the header of the tree to be splayed.
- * SplayMe - a pointer to a node within the tree. This will become
- * the new root node.
- * Output: None.
- *
- * Notes: This is an uncharacteristic function for this group of modules
- * in that it provides access to the internal balancing routines,
- * which would normally be hidden.
- * Splaying the tree will not damage it (assuming that I've done
- * *my* job), but there is overhead involved. I don't recommend
- * that you use this function unless you understand the underlying
- * Splay Tree principles involved.
- * ------------------------------------------------------------------------ **
- */
-
-int ubi_sptModuleID( int size, char *list[] );
- /* ------------------------------------------------------------------------ **
- * Returns a set of strings that identify the module.
- *
- * Input: size - The number of elements in the array <list>.
- * list - An array of pointers of type (char *). This array
- * should, initially, be empty. This function will fill
- * in the array with pointers to strings.
- * Output: The number of elements of <list> that were used. If this value
- * is less than <size>, the values of the remaining elements are
- * not guaranteed.
- *
- * Notes: Please keep in mind that the pointers returned indicate strings
- * stored in static memory. Don't free() them, don't write over
- * them, etc. Just read them.
- * ------------------------------------------------------------------------ **
- */
-
-/* -------------------------------------------------------------------------- **
- * Masquarade...
- *
- * This set of defines allows you to write programs that will use any of the
- * implemented binary tree modules (currently BinTree, AVLtree, and SplayTree).
- * Instead of using ubi_bt..., use ubi_tr..., and select the tree type by
- * including the appropriate module header.
- */
-
-#undef ubi_trInsert
-#undef ubi_trRemove
-#undef ubi_trLocate
-#undef ubi_trFind
-#undef ubi_trModuleID
-
-#define ubi_trInsert( Rp, Nn, Ip, On ) \
- ubi_sptInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \
- (ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) )
-
-#define ubi_trRemove( Rp, Dn ) \
- ubi_sptRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) )
-
-#define ubi_trLocate( Rp, Ip, Op ) \
- ubi_sptLocate( (ubi_btRootPtr)(Rp), \
- (ubi_btItemPtr)(Ip), \
- (ubi_trCompOps)(Op) )
-
-#define ubi_trFind( Rp, Ip ) \
- ubi_sptFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) )
-
-#define ubi_trSplay( Rp, Sm ) \
- ubi_sptSplay( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Sm) )
-
-#define ubi_trModuleID( s, l ) ubi_sptModuleID( s, l )
-
-/* ================================ The End ================================= */
-#endif /* UBI_SPLAYTREE_H */
diff --git a/source/ubiqx/ubi_dLinkList.c b/source/ubiqx/ubi_dLinkList.c
deleted file mode 100644
index eb95033c695..00000000000
--- a/source/ubiqx/ubi_dLinkList.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* ========================================================================== **
- * ubi_dLinkList.c
- *
- * Copyright (C) 1997, 1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- * This module implements simple doubly-linked lists.
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_dLinkList.c,v
- * Revision 0.11 1999/06/19 16:58:06 crh
- * Renamed the ubi_slRemove() function in ubi_sLinkList to
- * ubi_slRemoveNext(). I was bothered by the fact that it didn't
- * match the functionality of the ubi_dlRemove() function in
- * ubi_dLinkList. The new name is more 'correct'.
- *
- * Revision 0.10 1998/07/24 07:30:20 crh
- * Added the ubi_dlNewList() macro.
- *
- * Revision 0.9 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 0.8 1998/06/03 18:06:03 crh
- * Further fiddling with sys_include.h, which has been moved from the .c file
- * to the .h file.
- *
- * Revision 0.7 1998/06/02 01:38:47 crh
- * Changed include file name from ubi_null.h to sys_include.h to make it
- * more generic.
- *
- * Revision 0.6 1998/05/20 04:38:05 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 0.5 1998/03/10 02:55:00 crh
- * Simplified the code and added macros for stack & queue manipulations.
- *
- * Revision 0.4 1998/01/03 01:53:56 crh
- * Added ubi_dlCount() macro.
- *
- * Revision 0.3 1997/10/15 03:05:39 crh
- * Added some handy type casting to the macros. Added AddHere and RemThis
- * macros.
- *
- * Revision 0.2 1997/10/08 03:07:21 crh
- * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead()
- * macro, which was passing the wrong value for <After> to Insert().
- *
- * Revision 0.1 1997/10/07 04:34:07 crh
- * Initial Revision.
- *
- * -------------------------------------------------------------------------- **
- * This module is similar to the ubi_sLinkList module, but it is neither a
- * descendant type nor an easy drop-in replacement for the latter. One key
- * difference is that the ubi_dlRemove() function removes the indicated node,
- * while the ubi_slRemoveNext() function (in ubi_sLinkList) removes the node
- * *following* the indicated node.
- *
- * ========================================================================== **
- */
-
-#include "ubi_dLinkList.h" /* Header for *this* module. */
-
-/* ========================================================================== **
- * Functions...
- */
-
-ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr )
- /* ------------------------------------------------------------------------ **
- * Initialize a doubly-linked list header.
- *
- * Input: ListPtr - A pointer to the list structure that is to be
- * initialized for use.
- *
- * Output: A pointer to the initialized list header (i.e., same as
- * <ListPtr>).
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ListPtr->Head = NULL;
- ListPtr->Tail = NULL;
- ListPtr->count = 0;
- return( ListPtr );
- } /* ubi_dlInitList */
-
-ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr,
- ubi_dlNodePtr New,
- ubi_dlNodePtr After )
- /* ------------------------------------------------------------------------ **
- * Insert a new node into the list.
- *
- * Input: ListPtr - A pointer to the list into which the node is to
- * be inserted.
- * New - Pointer to the new node.
- * After - NULL, or a pointer to a node that is already in the
- * list.
- * If NULL, then <New> will be added at the head of the
- * list, else it will be added following <After>.
- *
- * Output: A pointer to the node that was inserted into the list (i.e.,
- * the same as <New>).
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_dlNodePtr PredNode = After ? After : (ubi_dlNodePtr)ListPtr;
-
- New->Next = PredNode->Next;
- New->Prev = After;
- PredNode->Next = New;
- if( New->Next )
- New->Next->Prev = New;
- else
- ListPtr->Tail = New;
-
- (ListPtr->count)++;
-
- return( New );
- } /* ubi_dlInsert */
-
-ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old )
- /* ------------------------------------------------------------------------ **
- * Remove a node from the list.
- *
- * Input: ListPtr - A pointer to the list from which <Old> is to be
- * removed.
- * Old - A pointer to the node that is to be removed from the
- * list.
- *
- * Output: A pointer to the node that was removed (i.e., <Old>).
- *
- * ------------------------------------------------------------------------ **
- */
- {
- if( Old )
- {
- if( Old->Next )
- Old->Next->Prev = Old->Prev;
- else
- ListPtr->Tail = Old->Prev;
-
- if( Old->Prev )
- Old->Prev->Next = Old->Next;
- else
- ListPtr->Head = Old->Next;
-
- (ListPtr->count)--;
- }
-
- return( Old );
- } /* ubi_dlRemove */
-
-/* ================================ The End ================================= */
diff --git a/source/ubiqx/ubi_dLinkList.h b/source/ubiqx/ubi_dLinkList.h
deleted file mode 100644
index 682e566ee67..00000000000
--- a/source/ubiqx/ubi_dLinkList.h
+++ /dev/null
@@ -1,242 +0,0 @@
-#ifndef UBI_DLINKLIST_H
-#define UBI_DLINKLIST_H
-/* ========================================================================== **
- * ubi_dLinkList.h
- *
- * Copyright (C) 1997, 1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- * This module implements simple doubly-linked lists.
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_dLinkList.h,v
- * Revision 0.11 1999/06/19 16:58:06 crh
- * Renamed the ubi_slRemove() function in ubi_sLinkList to
- * ubi_slRemoveNext(). I was bothered by the fact that it didn't
- * match the functionality of the ubi_dlRemove() function in
- * ubi_dLinkList. The new name is more 'correct'.
- *
- * Revision 0.10 1998/07/24 07:30:20 crh
- * Added the ubi_dlNewList() macro.
- *
- * Revision 0.9 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 0.8 1998/06/03 18:06:03 crh
- * Further fiddling with sys_include.h, which has been moved from the .c file
- * to the .h file.
- *
- * Revision 0.7 1998/06/02 01:38:47 crh
- * Changed include file name from ubi_null.h to sys_include.h to make it
- * more generic.
- *
- * Revision 0.6 1998/05/20 04:38:05 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 0.5 1998/03/10 02:54:04 crh
- * Simplified the code and added macros for stack & queue manipulations.
- *
- * Revision 0.4 1998/01/03 01:53:44 crh
- * Added ubi_dlCount() macro.
- *
- * Revision 0.3 1997/10/15 03:04:31 crh
- * Added some handy type casting to the macros. Added AddHere and RemThis
- * macros.
- *
- * Revision 0.2 1997/10/08 03:08:16 crh
- * Fixed a few forgotten link-ups in Insert(), and fixed the AddHead()
- * macro, which was passing the wrong value for <After> to Insert().
- *
- * Revision 0.1 1997/10/07 04:34:38 crh
- * Initial Revision.
- *
- * -------------------------------------------------------------------------- **
- * This module is similar to the ubi_sLinkList module, but it is neither a
- * descendant type nor an easy drop-in replacement for the latter. One key
- * difference is that the ubi_dlRemove() function removes the indicated node,
- * while the ubi_slRemoveNext() function (in ubi_sLinkList) removes the node
- * *following* the indicated node.
- *
- * ========================================================================== **
- */
-
-#include "sys_include.h" /* System-specific includes. */
-
-/* ========================================================================== **
- * Typedefs...
- *
- * ubi_dlNode - This is the basic node structure.
- * ubi_dlNodePtr - Pointer to a node.
- * ubi_dlList - This is the list header structure.
- * ubi_dlListPtr - Pointer to a List (i.e., a list header structure).
- *
- */
-
-typedef struct ubi_dlListNode
- {
- struct ubi_dlListNode *Next;
- struct ubi_dlListNode *Prev;
- } ubi_dlNode;
-
-typedef ubi_dlNode *ubi_dlNodePtr;
-
-typedef struct
- {
- ubi_dlNodePtr Head;
- ubi_dlNodePtr Tail;
- unsigned long count;
- } ubi_dlList;
-
-typedef ubi_dlList *ubi_dlListPtr;
-
-/* ========================================================================== **
- * Macros...
- *
- * ubi_dlNewList - Macro used to declare and initialize a new list in one
- * swell foop. It is used when defining a variable of
- * type ubi_dlList. The definition
- * static ubi_dlNewList( gerbil );
- * is translated to
- * static ubi_dlList gerbil[1] = {{ NULL, NULL, 0 }};
- *
- * ubi_dlCount - Return the number of entries currently in the list.
- *
- * ubi_dlAddHead - Add a new node at the head of the list.
- * ubi_dlAddNext - Add a node following the given node.
- * ubi_dlAddTail - Add a new node at the tail of the list.
- * Note: AddTail evaluates the L parameter twice.
- *
- * ubi_dlRemHead - Remove the node at the head of the list, if any.
- * Note: RemHead evaluates the L parameter twice.
- * ubi_dlRemThis - Remove the indicated node.
- * ubi_dlRemTail - Remove the node at the tail of the list, if any.
- * Note: RemTail evaluates the L parameter twice.
- *
- * ubi_dlFirst - Return a pointer to the first node in the list, if any.
- * ubi_dlLast - Return a pointer to the last node in the list, if any.
- * ubi_dlNext - Given a node, return a pointer to the next node.
- * ubi_dlPrev - Given a node, return a pointer to the previous node.
- *
- * ubi_dlPush - Add a node at the head of the list (synonym of AddHead).
- * ubi_dlPop - Remove a node at the head of the list (synonym of RemHead).
- * ubi_dlEnqueue - Add a node at the tail of the list (sysnonym of AddTail).
- * ubi_dlDequeue - Remove a node at the head of the list (synonym of RemHead).
- *
- * Note that all of these provide type casting of the parameters. The
- * Add and Rem macros are nothing more than nice front-ends to the
- * Insert and Remove operations.
- *
- * Also note that the First, Next and Last macros do no parameter checking!
- *
- */
-
-#define ubi_dlNewList( L ) ubi_dlList (L)[1] = {{ NULL, NULL, 0 }}
-
-#define ubi_dlCount( L ) (((ubi_dlListPtr)(L))->count)
-
-#define ubi_dlAddHead( L, N ) \
- ubi_dlInsert( (ubi_dlListPtr)(L), (ubi_dlNodePtr)(N), NULL )
-
-#define ubi_dlAddNext( L, N, A ) \
- ubi_dlInsert( (ubi_dlListPtr)(L), \
- (ubi_dlNodePtr)(N), \
- (ubi_dlNodePtr)(A) )
-
-#define ubi_dlAddTail( L, N ) \
- ubi_dlInsert( (ubi_dlListPtr)(L), \
- (ubi_dlNodePtr)(N), \
- (((ubi_dlListPtr)(L))->Tail) )
-
-#define ubi_dlRemHead( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \
- (((ubi_dlListPtr)(L))->Head) )
-
-#define ubi_dlRemThis( L, N ) ubi_dlRemove( (ubi_dlListPtr)(L), \
- (ubi_dlNodePtr)(N) )
-
-#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \
- (((ubi_dlListPtr)(L))->Tail) )
-
-#define ubi_dlFirst( L ) (((ubi_dlListPtr)(L))->Head)
-
-#define ubi_dlLast( L ) (((ubi_dlListPtr)(L))->Tail)
-
-#define ubi_dlNext( N ) (((ubi_dlNodePtr)(N))->Next)
-
-#define ubi_dlPrev( N ) (((ubi_dlNodePtr)(N))->Prev)
-
-#define ubi_dlPush ubi_dlAddHead
-#define ubi_dlPop ubi_dlRemHead
-#define ubi_dlEnqueue ubi_dlAddTail
-#define ubi_dlDequeue ubi_dlRemHead
-
-/* ========================================================================== **
- * Function prototypes...
- */
-
-ubi_dlListPtr ubi_dlInitList( ubi_dlListPtr ListPtr );
- /* ------------------------------------------------------------------------ **
- * Initialize a doubly-linked list header.
- *
- * Input: ListPtr - A pointer to the list structure that is to be
- * initialized for use.
- *
- * Output: A pointer to the initialized list header (i.e., same as
- * <ListPtr>).
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr,
- ubi_dlNodePtr New,
- ubi_dlNodePtr After );
- /* ------------------------------------------------------------------------ **
- * Insert a new node into the list.
- *
- * Input: ListPtr - A pointer to the list into which the node is to
- * be inserted.
- * New - Pointer to the new node.
- * After - NULL, or a pointer to a node that is already in the
- * list.
- * If NULL, then <New> will be added at the head of the
- * list, else it will be added following <After>.
- *
- * Output: A pointer to the node that was inserted into the list (i.e.,
- * the same as <New>).
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old );
- /* ------------------------------------------------------------------------ **
- * Remove a node from the list.
- *
- * Input: ListPtr - A pointer to the list from which <Old> is to be
- * removed.
- * Old - A pointer to the node that is to be removed from the
- * list.
- *
- * Output: A pointer to the node that was removed (i.e., <Old>).
- *
- * ------------------------------------------------------------------------ **
- */
-
-/* ================================ The End ================================= */
-#endif /* UBI_DLINKLIST_H */
diff --git a/source/ubiqx/ubi_sLinkList.c b/source/ubiqx/ubi_sLinkList.c
deleted file mode 100644
index ff75931b470..00000000000
--- a/source/ubiqx/ubi_sLinkList.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* ========================================================================== **
- * ubi_sLinkList.c
- *
- * Copyright (C) 1997, 1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- * This module implements a simple singly-linked list.
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_sLinkList.c,v
- * Revision 0.10 1999/06/19 16:58:06 crh
- * Renamed the ubi_slRemove() function in ubi_sLinkList to
- * ubi_slRemoveNext(). I was bothered by the fact that it didn't
- * match the functionality of the ubi_dlRemove() function in
- * ubi_dLinkList. The new name is more 'correct'.
- *
- * Revision 0.9 1998/07/24 07:30:20 crh
- * Added the ubi_slNewList() macro.
- *
- * Revision 0.8 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 0.7 1998/06/03 18:06:03 crh
- * Further fiddling with sys_include.h, which has been moved from the .c file
- * to the .h file.
- *
- * Revision 0.6 1998/06/02 01:38:47 crh
- * Changed include file name from ubi_null.h to sys_include.h to make it
- * more generic.
- *
- * Revision 0.5 1998/05/20 04:38:05 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 0.4 1998/03/10 02:23:20 crh
- * Combined ubi_StackQueue and ubi_sLinkList into one module. Redesigned
- * the functions and macros. Not a complete rewrite but close to it.
- *
- * Revision 0.3 1998/01/03 01:59:52 crh
- * Added ubi_slCount() macro.
- *
- * Revision 0.2 1997/10/21 03:35:18 crh
- * Added parameter <After> in function Insert(). Made necessary changes
- * to macro AddHead() and added macro AddHere().
- *
- * Revision 0.1 1997/10/16 02:53:45 crh
- * Initial Revision.
- *
- * -------------------------------------------------------------------------- **
- * This module implements a singly-linked list which may also be used as a
- * queue or a stack. For a queue, entries are added at the tail and removed
- * from the head of the list. For a stack, the entries are entered and
- * removed from the head of the list. A traversal of the list will always
- * start at the head of the list and proceed toward the tail. This is all
- * mind-numbingly simple, but I'm surprised by the number of programs out
- * there which re-implement this a dozen or so times.
- *
- * Note: When the list header is initialized, the Tail pointer is set to
- * point to the Head pointer. This simplifies things a great deal,
- * except that you can't initialize a stack or queue by simply
- * zeroing it out. One sure way to initialize the header is to call
- * ubi_slInit(). Another option would be something like this:
- *
- * ubi_slNewList( MyList );
- *
- * Which translates to:
- *
- * ubi_slList MyList[1] = { NULL, (ubi_slNodePtr)MyList, 0 };
- *
- * See ubi_slInit(), ubi_slNewList(), and the ubi_slList structure
- * for more info.
- *
- * + Also, note that this module is similar to the ubi_dLinkList
- * module. There are three key differences:
- * - This is a singly-linked list, the other is a doubly-linked
- * list.
- * - In this module, if the list is empty, the tail pointer will
- * point back to the head of the list as described above. This
- * is not done in ubi_dLinkList.
- * - The ubi_slRemoveNext() function, by necessity, removes the
- * 'next' node. In ubi_dLinkList, the ubi_dlRemove() function
- * removes the 'current' node.
- *
- * ========================================================================== **
- */
-
-#include "ubi_sLinkList.h" /* Header for *this* module. */
-
-/* ========================================================================== **
- * Functions...
- */
-
-ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr )
- /* ------------------------------------------------------------------------ **
- * Initialize a singly-linked list header.
- *
- * Input: ListPtr - A pointer to the list structure that is to be
- * initialized for use.
- *
- * Output: A pointer to the initialized list header (i.e., same as
- * <ListPtr>).
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ListPtr->Head = NULL;
- ListPtr->Tail = (ubi_slNodePtr)ListPtr;
- ListPtr->count = 0;
- return( ListPtr );
- } /* ubi_slInitList */
-
-ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr,
- ubi_slNodePtr New,
- ubi_slNodePtr After )
- /* ------------------------------------------------------------------------ **
- * Add a node to the list.
- *
- * Input: ListPtr - A pointer to the list into which the node is to
- * be inserted.
- * New - Pointer to the node that is to be added to the list.
- * After - Pointer to a list in a node after which the new node
- * will be inserted. If NULL, then the new node will
- * be added at the head of the list.
- *
- * Output: A pointer to the node that was inserted into the list (i.e.,
- * the same as <New>).
- *
- * ------------------------------------------------------------------------ **
- */
- {
- After = After ? After : (ubi_slNodePtr)ListPtr;
- New->Next = After->Next;
- After->Next = New;
- if( !(New->Next) )
- ListPtr->Tail = New;
- (ListPtr->count)++;
- return( New );
- } /* ubi_slInsert */
-
-ubi_slNodePtr ubi_slRemoveNext( ubi_slListPtr ListPtr, ubi_slNodePtr AfterMe )
- /* ------------------------------------------------------------------------ **
- * Remove the node followng <AfterMe>. If <AfterMe> is NULL, remove from
- * the head of the list.
- *
- * Input: ListPtr - A pointer to the list from which the node is to be
- * removed.
- * AfterMe - Pointer to the node preceeding the node to be
- * removed.
- *
- * Output: A pointer to the node that was removed, or NULL if the list is
- * empty.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- ubi_slNodePtr DelNode;
-
- AfterMe = AfterMe ? AfterMe : (ubi_slNodePtr)ListPtr;
- DelNode = AfterMe->Next;
- if( DelNode )
- {
- if( !(DelNode->Next) )
- ListPtr->Tail = AfterMe;
- AfterMe->Next = DelNode->Next;
- (ListPtr->count)--;
- }
- return( DelNode );
- } /* ubi_slRemoveNext */
-
-/* ================================ The End ================================= */
diff --git a/source/ubiqx/ubi_sLinkList.h b/source/ubiqx/ubi_sLinkList.h
deleted file mode 100644
index 53bfa400671..00000000000
--- a/source/ubiqx/ubi_sLinkList.h
+++ /dev/null
@@ -1,254 +0,0 @@
-#ifndef UBI_SLINKLIST_H
-#define UBI_SLINKLIST_H
-/* ========================================================================== **
- * ubi_sLinkList.h
- *
- * Copyright (C) 1997, 1998 by Christopher R. Hertel
- *
- * Email: crh@ubiqx.mn.org
- * -------------------------------------------------------------------------- **
- * This module implements a simple singly-linked list.
- * -------------------------------------------------------------------------- **
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * -------------------------------------------------------------------------- **
- *
- * Log: ubi_sLinkList.h,v
- * Revision 0.10 1999/06/19 16:58:06 crh
- * Renamed the ubi_slRemove() function in ubi_sLinkList to
- * ubi_slRemoveNext(). I was bothered by the fact that it didn't
- * match the functionality of the ubi_dlRemove() function in
- * ubi_dLinkList. The new name is more 'correct'.
- *
- * Revision 0.9 1998/07/24 07:30:20 crh
- * Added the ubi_slNewList() macro.
- *
- * Revision 0.8 1998/06/04 21:29:27 crh
- * Upper-cased defined constants (eg UBI_BINTREE_H) in some header files.
- * This is more "standard", and is what people expect. Weird, eh?
- *
- * Revision 0.7 1998/06/03 18:06:03 crh
- * Further fiddling with sys_include.h, which has been moved from the .c file
- * to the .h file.
- *
- * Revision 0.6 1998/06/02 01:38:47 crh
- * Changed include file name from ubi_null.h to sys_include.h to make it
- * more generic.
- *
- * Revision 0.5 1998/05/20 04:38:05 crh
- * The C file now includes ubi_null.h. See ubi_null.h for more info.
- *
- * Revision 0.4 1998/03/10 02:22:39 crh
- * Combined ubi_StackQueue and ubi_sLinkList into one module. Redesigned
- * the functions and macros. Not a complete rewrite but close to it.
- *
- * Revision 0.3 1998/01/03 02:00:02 crh
- * Added ubi_slCount() macro.
- *
- * Revision 0.2 1997/10/21 03:36:14 crh
- * Added parameter <After> in function Insert(). Made necessary changes
- * to macro AddHead() and added macro AddHere().
- *
- * Revision 0.1 1997/10/16 02:54:08 crh
- * Initial Revision.
- *
- * -------------------------------------------------------------------------- **
- * This module implements a singly-linked list which may also be used as a
- * queue or a stack. For a queue, entries are added at the tail and removed
- * from the head of the list. For a stack, the entries are entered and
- * removed from the head of the list. A traversal of the list will always
- * start at the head of the list and proceed toward the tail. This is all
- * mind-numbingly simple, but I'm surprised by the number of programs out
- * there which re-implement this a dozen or so times.
- *
- * Note: When the list header is initialized, the Tail pointer is set to
- * point to the Head pointer. This simplifies things a great deal,
- * except that you can't initialize a stack or queue by simply
- * zeroing it out. One sure way to initialize the header is to call
- * ubi_slInit(). Another option would be something like this:
- *
- * ubi_slNewList( MyList );
- *
- * Which translates to:
- *
- * ubi_slList MyList[1] = { NULL, (ubi_slNodePtr)MyList, 0 };
- *
- * See ubi_slInit(), ubi_slNewList(), and the ubi_slList structure
- * for more info.
- *
- * + Also, note that this module is similar to the ubi_dLinkList
- * module. There are three key differences:
- * - This is a singly-linked list, the other is a doubly-linked
- * list.
- * - In this module, if the list is empty, the tail pointer will
- * point back to the head of the list as described above. This
- * is not done in ubi_dLinkList.
- * - The ubi_slRemoveNext() function, by necessity, removes the
- * 'next' node. In ubi_dLinkList, the ubi_dlRemove() function
- * removes the 'current' node.
- *
- * ========================================================================== **
- */
-
-#include "sys_include.h" /* System-specific includes. */
-
-/* ========================================================================== **
- * Typedefs...
- *
- * ubi_slNode - This is the basic node structure.
- * ubi_slNodePtr - Pointer to a node.
- * ubi_slList - This is the list header structure.
- * ubi_slListPtr - Pointer to a List (i.e., a list header structure).
- *
- */
-
-typedef struct ubi_slListNode
- {
- struct ubi_slListNode *Next;
- } ubi_slNode;
-
-typedef ubi_slNode *ubi_slNodePtr;
-
-typedef struct
- {
- ubi_slNodePtr Head;
- ubi_slNodePtr Tail;
- unsigned long count;
- } ubi_slList;
-
-typedef ubi_slList *ubi_slListPtr;
-
-
-/* ========================================================================== **
- * Macros...
- *
- * ubi_slNewList - Macro used to declare and initialize a list header in
- * one step.
- *
- * ubi_slCount - Returns the current number of entries in the list.
- *
- * ubi_slAddHead - Add a new node at the head of the list.
- * ubi_slAddNext - Add a new node following the indicated node.
- * ubi_slAddTail - Add a new node to the tail of the list.
- * Note: AddTail evaluates the L parameter twice.
- *
- * ubi_slRemHead - Remove the node at the head of the list, if any.
- * ubi_slRemNext - Remove the node following the given node.
- *
- * ubi_slFirst - Return a pointer to the first node in the list, if any.
- * ubi_slNext - Given a node, return a pointer to the next node.
- * ubi_slLast - Return a pointer to the last node in the list, if any.
- *
- * ubi_slPush - Add a node at the head of the list (synonym of AddHead).
- * ubi_slPop - Remove a node at the head of the list (synonym of RemHead).
- * ubi_slEnqueue - Add a node at the tail of the list (sysnonym of AddTail).
- * ubi_slDequeue - Remove a node at the head of the list (synonym of RemHead).
- *
- * Note that all of these provide type casting of the parameters. The
- * Add and Rem macros are nothing more than nice front-ends to the
- * Insert and Remove functions.
- *
- * Also note that the First, Next and Last macros do no parameter checking!
- *
- */
-
-#define ubi_slNewList( L ) ubi_slList (L)[1] = {{ NULL, (ubi_slNodePtr)(L), 0 }}
-
-#define ubi_slCount( L ) (((ubi_slListPtr)(L))->count)
-
-#define ubi_slAddHead( L, N ) \
- ubi_slInsert( (ubi_slListPtr)(L), (ubi_slNodePtr)(N), NULL )
-
-#define ubi_slAddNext( L, N, A ) \
- ubi_slInsert( (ubi_slListPtr)(L), \
- (ubi_slNodePtr)(N), \
- (ubi_slNodePtr)(A) )
-
-#define ubi_slAddTail( L, N ) \
- ubi_slInsert( (ubi_slListPtr)(L), \
- (ubi_slNodePtr)(N), \
- ((ubi_slListPtr)(L))->Tail )
-
-#define ubi_slRemHead( L ) ubi_slRemoveNext( (ubi_slListPtr)(L), NULL )
-
-#define ubi_slRemNext( L, N ) \
- ubi_slRemoveNext( (ubi_slListPtr)(L), (ubi_slNodePtr)(N) )
-
-#define ubi_slFirst( L ) (((ubi_slListPtr)(L))->Head)
-
-#define ubi_slNext( N ) (((ubi_slNodePtr)(N))->Next)
-
-#define ubi_slLast( L ) (((ubi_slListPtr)(L))->Tail)
-
-#define ubi_slPush ubi_slAddHead
-#define ubi_slPop ubi_slRemHead
-#define ubi_slEnqueue ubi_slAddTail
-#define ubi_slDequeue ubi_slRemHead
-
-/* ========================================================================== **
- * Function prototypes...
- */
-
-ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr );
- /* ------------------------------------------------------------------------ **
- * Initialize a singly-linked list header.
- *
- * Input: ListPtr - A pointer to the list structure that is to be
- * initialized for use.
- *
- * Output: A pointer to the initialized list header (i.e., same as
- * <ListPtr>).
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr,
- ubi_slNodePtr New,
- ubi_slNodePtr After );
- /* ------------------------------------------------------------------------ **
- * Add a node to the list.
- *
- * Input: ListPtr - A pointer to the list into which the node is to
- * be inserted.
- * New - Pointer to the node that is to be added to the list.
- * After - Pointer to a list in a node after which the new node
- * will be inserted. If NULL, then the new node will
- * be added at the head of the list.
- *
- * Output: A pointer to the node that was inserted into the list (i.e.,
- * the same as <New>).
- *
- * ------------------------------------------------------------------------ **
- */
-
-ubi_slNodePtr ubi_slRemoveNext( ubi_slListPtr ListPtr, ubi_slNodePtr AfterMe );
- /* ------------------------------------------------------------------------ **
- * Remove the node followng <AfterMe>. If <AfterMe> is NULL, remove from
- * the head of the list.
- *
- * Input: ListPtr - A pointer to the list from which the node is to be
- * removed.
- * AfterMe - Pointer to the node preceeding the node to be
- * removed.
- *
- * Output: A pointer to the node that was removed, or NULL if the list is
- * empty.
- *
- * ------------------------------------------------------------------------ **
- */
-
-/* ================================ The End ================================= */
-#endif /* UBI_SLINKLIST_H */
diff --git a/source/ubiqx/debugparse.c b/source/utils/debugparse.c
index c5fe3e2ee85..c5fe3e2ee85 100644
--- a/source/ubiqx/debugparse.c
+++ b/source/utils/debugparse.c
diff --git a/source/utils/eventlogadm.c b/source/utils/eventlogadm.c
index eef7cde3771..8cf79fcf14b 100644
--- a/source/utils/eventlogadm.c
+++ b/source/utils/eventlogadm.c
@@ -170,7 +170,7 @@ int main( int argc, char *argv[] )
opt_debug = 0; /* todo set this from getopts */
- lp_load( dyn_CONFIGFILE, True, False, False );
+ lp_load( dyn_CONFIGFILE, True, False, False, True);
exename = argv[0];
srcname = NULL;
diff --git a/source/utils/net.c b/source/utils/net.c
index a2a9ac6a391..1389885ba17 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -132,6 +132,29 @@ int net_run_function(int argc, const char **argv, struct functable *table,
return usage_fn(argc, argv);
}
+/*
+ * run a function from a function table.
+ */
+int net_run_function2(int argc, const char **argv, const char *whoami,
+ struct functable2 *table)
+{
+ int i;
+
+ if (argc != 0) {
+ for (i=0; table[i].funcname; i++) {
+ if (StrCaseCmp(argv[0], table[i].funcname) == 0)
+ return table[i].fn(argc-1, argv+1);
+ }
+ }
+
+ for (i=0; table[i].funcname != NULL; i++) {
+ d_printf("%s %-15s %s\n", whoami, table[i].funcname,
+ table[i].helptext);
+ }
+
+ return -1;
+}
+
/****************************************************************************
connect to \\server\service
****************************************************************************/
@@ -226,12 +249,21 @@ NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **p
struct cli_state *cli_tmp = NULL;
struct rpc_pipe_client *pipe_hnd = NULL;
- if (opt_destination)
- server_name = SMB_STRDUP(opt_destination);
+ if (server_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (opt_destination) {
+ SAFE_FREE(server_name);
+ if ((server_name = SMB_STRDUP(opt_destination)) == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
/* make a connection to a named pipe */
nt_status = connect_to_ipc(&cli_tmp, NULL, server_name);
if (!NT_STATUS_IS_OK(nt_status)) {
+ SAFE_FREE(server_name);
return nt_status;
}
@@ -239,11 +271,13 @@ NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **p
if (!pipe_hnd) {
DEBUG(0, ("couldn't not initialize pipe\n"));
cli_shutdown(cli_tmp);
+ SAFE_FREE(server_name);
return nt_status;
}
*cli_dst = cli_tmp;
*pp_pipe_hnd = pipe_hnd;
+ SAFE_FREE(server_name);
return nt_status;
}
@@ -372,10 +406,17 @@ struct cli_state *net_make_ipc_connection(unsigned flags)
nt_status = connect_to_ipc(&cli, &server_ip, server_name);
}
+ /* store the server in the affinity cache if it was a PDC */
+
+ if ( (flags & NET_FLAGS_PDC) && NT_STATUS_IS_OK(nt_status) )
+ saf_store( cli->server_domain, cli->desthost );
+
SAFE_FREE(server_name);
if (NT_STATUS_IS_OK(nt_status)) {
return cli;
} else {
+ d_fprintf(stderr, "Connection failed: %s\n",
+ nt_errstr(nt_status));
return NULL;
}
}
@@ -705,6 +746,7 @@ static struct functable net_func[] = {
{"USER", net_user},
{"GROUP", net_group},
{"GROUPMAP", net_groupmap},
+ {"SAM", net_sam},
{"VALIDATE", net_rap_validate},
{"GROUPMEMBER", net_rap_groupmember},
{"ADMIN", net_rap_admin},
@@ -722,6 +764,7 @@ static struct functable net_func[] = {
{"MAXRID", net_maxrid},
{"IDMAP", net_idmap},
{"STATUS", net_status},
+ {"USERSHARE", net_usershare},
{"USERSIDLIST", net_usersidlist},
#ifdef WITH_FAKE_KASERVER
{"AFS", net_afs},
@@ -825,7 +868,7 @@ static struct functable net_func[] = {
* set by cmdline arg or remain default (0)
*/
AllowDebugChange = False;
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
argv_new = (const char **)poptGetArgs(pc);
diff --git a/source/utils/net.h b/source/utils/net.h
index 2df13cfb8f1..fc3167012d6 100644
--- a/source/utils/net.h
+++ b/source/utils/net.h
@@ -39,6 +39,29 @@ typedef struct copy_clistate {
uint16 attribute;
}copy_clistate;
+struct rpc_sh_ctx {
+ struct cli_state *cli;
+
+ DOM_SID *domain_sid;
+ char *domain_name;
+
+ const char *whoami;
+ const char *thiscmd;
+ struct rpc_sh_cmd *cmds;
+ struct rpc_sh_ctx *parent;
+};
+
+struct rpc_sh_cmd {
+ const char *name;
+ struct rpc_sh_cmd *(*sub)(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx);
+ int pipe_idx;
+ NTSTATUS (*fn)(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv);
+ const char *help;
+};
+
/* INCLUDE FILES */
#include "utils/net_proto.h"
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index f54896b3a82..6cd332fd3df 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -69,18 +69,20 @@ int net_ads_usage(int argc, const char **argv)
static int net_ads_lookup(int argc, const char **argv)
{
ADS_STRUCT *ads;
+ ADS_STATUS status;
ads = ads_init(NULL, opt_target_workgroup, opt_host);
if (ads) {
ads->auth.flags |= ADS_AUTH_NO_BIND;
}
- ads_connect(ads);
-
- if (!ads) {
+ status = ads_connect(ads);
+ if (!ADS_ERR_OK(status) || !ads) {
d_fprintf(stderr, "Didn't find the cldap server!\n");
return -1;
- } if (!ads->config.realm) {
+ }
+
+ if (!ads->config.realm) {
ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
ads->ldap_port = 389;
}
@@ -367,15 +369,15 @@ static int ads_user_info(int argc, const char **argv)
}
escaped_user = escape_ldap_string_alloc(argv[0]);
-
- if (!(ads = ads_startup())) {
- return -1;
- }
if (!escaped_user) {
d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]);
- ads_destroy(&ads);
- return -1;
+ return -1;
+ }
+
+ if (!(ads = ads_startup())) {
+ SAFE_FREE(escaped_user);
+ return -1;
}
asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
@@ -385,6 +387,7 @@ static int ads_user_info(int argc, const char **argv)
if (!ADS_ERR_OK(rc)) {
d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc));
ads_destroy(&ads);
+ SAFE_FREE(escaped_user);
return -1;
}
@@ -403,6 +406,7 @@ static int ads_user_info(int argc, const char **argv)
ads_msgfree(ads, res);
ads_destroy(&ads);
+ SAFE_FREE(escaped_user);
return 0;
}
@@ -717,6 +721,13 @@ int net_ads_join(int argc, const char **argv)
const char *short_domain_name = NULL;
TALLOC_CTX *ctx = NULL;
+ if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
+ (lp_server_role() != ROLE_DOMAIN_BDC)) {
+ d_printf("can only join as domain member or as BDC\n");
+ return -1;
+ }
+
+
if (argc > 0) {
org_unit = argv[0];
}
@@ -1041,6 +1052,13 @@ static int net_ads_printer_publish(int argc, const char **argv)
asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
+ if (!pipe_hnd) {
+ d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
+ servername);
+ ads_destroy(&ads);
+ return -1;
+ }
+
get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
printername);
diff --git a/source/utils/net_ads_gpo.c b/source/utils/net_ads_gpo.c
new file mode 100644
index 00000000000..fec6fb88fa2
--- /dev/null
+++ b/source/utils/net_ads_gpo.c
@@ -0,0 +1,436 @@
+/*
+ Samba Unix/Linux SMB client library
+ net ads commands for Group Policy
+ Copyright (C) 2005 Guenther Deschner (gd@samba.org)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "utils/net.h"
+
+#ifdef HAVE_ADS
+
+static int net_ads_gpo_usage(int argc, const char **argv)
+{
+ d_printf(
+ "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"\
+" GETGPO Lists specified GPO\n"\
+" GETLINK Lists gPLink of a containter\n"\
+" HELP Prints this help message\n"\
+" LIST Lists all GPOs\n"\
+"\n"
+ );
+ return -1;
+}
+
+static int net_ads_gpo_effective(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 *filter;
+ char *dn = NULL;
+ struct GROUP_POLICY_OBJECT *gpo_list;
+ uint32 uac = 0;
+ uint32 flags = 0;
+
+ if (argc < 1) {
+ return -1;
+ }
+
+ mem_ctx = talloc_init("net_ads_gpo_effective");
+ if (mem_ctx == NULL) {
+ return -1;
+ }
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", argv[0]);
+ if (filter == NULL) {
+ goto out;
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ status = ads_do_search_all(ads, ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ filter, attrs, &res);
+
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ printf("no result\n");
+ goto out;
+ }
+
+ dn = ads_get_dn(ads, res);
+ if (dn == NULL) {
+ goto out;
+ }
+
+ if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+ goto out;
+ }
+
+ if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
+ flags |= GPO_LIST_FLAG_MACHINE;
+ }
+
+ printf("%s: '%s' has dn: '%s'\n",
+ (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
+ argv[0], dn);
+
+ status = ads_get_gpo_list(ads, mem_ctx, dn, flags, &gpo_list);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ printf("unsorted full dump of all GPOs for this machine:\n");
+
+ {
+ struct GROUP_POLICY_OBJECT *gpo = gpo_list;
+
+ for (gpo = gpo_list; gpo; gpo = gpo->next) {
+ dump_gpo(mem_ctx, gpo);
+ }
+ }
+
+ printf("sorted full dump of all GPOs valid for this machine:\n");
+
+out:
+ ads_memfree(ads, dn);
+ ads_msgfree(ads, res);
+
+ ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
+ return 0;
+}
+
+static int net_ads_gpo_list(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ void *res = NULL;
+ int num_reply = 0;
+ void *msg = NULL;
+ struct GROUP_POLICY_OBJECT gpo;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_init("net_ads_gpo_list");
+ if (mem_ctx == NULL) {
+ return -1;
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ status = ads_do_search_all(ads, ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ "(objectclass=groupPolicyContainer)", NULL, &res);
+ if (!ADS_ERR_OK(status)) {
+ d_printf("search failed: %s\n", ads_errstr(status));
+ goto out;
+ }
+
+ num_reply = ads_count_replies(ads, res);
+
+ d_printf("Got %d replies\n\n", num_reply);
+
+ /* 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 (!ADS_ERR_OK(status)) {
+ d_printf("parse failed: %s\n", ads_errstr(status));
+ goto out;
+ }
+
+ dump_gpo(mem_ctx, &gpo);
+
+ }
+
+out:
+ ads_msgfree(ads, res);
+
+ talloc_destroy(mem_ctx);
+ ads_destroy(&ads);
+
+ return 0;
+}
+
+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;
+ const char *filter;
+ char *dn = NULL;
+ struct GROUP_POLICY_OBJECT *gpo_list;
+ uint32 uac = 0;
+ uint32 flags = 0;
+
+ if (argc < 1) {
+ return -1;
+ }
+
+ mem_ctx = talloc_init("net_ads_gpo_apply");
+ if (mem_ctx == NULL) {
+ goto out;
+ }
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", argv[0]);
+ if (filter == NULL) {
+ goto out;
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ status = ads_do_search_all(ads, ads->config.bind_path,
+ LDAP_SCOPE_SUBTREE,
+ filter, attrs, &res);
+
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ if (ads_count_replies(ads, res) != 1) {
+ printf("no result\n");
+ goto out;
+ }
+
+ dn = ads_get_dn(ads, res);
+ if (dn == NULL) {
+ goto out;
+ }
+
+ if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+ goto out;
+ }
+
+ if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
+ flags |= GPO_LIST_FLAG_MACHINE;
+ }
+
+ printf("%s: '%s' has dn: '%s'\n",
+ (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
+ argv[0], dn);
+
+ status = ads_get_gpo_list(ads, mem_ctx, dn, flags, &gpo_list);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+ /* FIXME: allow to process just a single extension */
+ status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list, NULL, flags);
+ if (!ADS_ERR_OK(status)) {
+ goto out;
+ }
+
+out:
+ ads_memfree(ads, dn);
+ ads_msgfree(ads, res);
+
+ ads_destroy(&ads);
+ talloc_destroy(mem_ctx);
+ return 0;
+}
+
+
+static int net_ads_gpo_get_link(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ TALLOC_CTX *mem_ctx;
+ struct GP_LINK gp_link;
+
+ if (argc < 1) {
+ return -1;
+ }
+
+ mem_ctx = talloc_init("add_gpo_link");
+ if (mem_ctx == NULL) {
+ return -1;
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ status = ads_get_gpo_link(ads, mem_ctx, argv[0], &gp_link);
+ if (!ADS_ERR_OK(status)) {
+ d_printf("get link for %s failed: %s\n", argv[0], ads_errstr(status));
+ goto out;
+ }
+
+ dump_gplink(ads, mem_ctx, &gp_link);
+
+out:
+ talloc_destroy(mem_ctx);
+ ads_destroy(&ads);
+
+ return 0;
+}
+
+static int net_ads_gpo_add_link(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ uint32 gpo_opt = 0;
+ TALLOC_CTX *mem_ctx;
+
+ if (argc < 2) {
+ return -1;
+ }
+
+ mem_ctx = talloc_init("add_gpo_link");
+ if (mem_ctx == NULL) {
+ return -1;
+ }
+
+ if (argc == 3) {
+ gpo_opt = atoi(argv[2]);
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ status = ads_add_gpo_link(ads, mem_ctx, argv[0], argv[1], gpo_opt);
+ if (!ADS_ERR_OK(status)) {
+ d_printf("add link failed: %s\n", ads_errstr(status));
+ goto out;
+ }
+
+out:
+ talloc_destroy(mem_ctx);
+ ads_destroy(&ads);
+
+ return 0;
+}
+
+static int net_ads_gpo_delete_link(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ TALLOC_CTX *mem_ctx;
+
+ if (argc < 2) {
+ return -1;
+ }
+
+ mem_ctx = talloc_init("delete_gpo_link");
+ if (mem_ctx == NULL) {
+ return -1;
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ status = ads_delete_gpo_link(ads, mem_ctx, argv[0], argv[1]);
+ if (!ADS_ERR_OK(status)) {
+ d_printf("delete link failed: %s\n", ads_errstr(status));
+ goto out;
+ }
+
+out:
+ talloc_destroy(mem_ctx);
+ ads_destroy(&ads);
+
+ return 0;
+}
+
+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) {
+ return -1;
+ }
+
+ mem_ctx = talloc_init("add_gpo_get_gpo");
+ if (mem_ctx == NULL) {
+ return -1;
+ }
+
+ if (!(ads = ads_startup())) {
+ goto out;
+ }
+
+ if (strnequal(argv[0], "CN={", strlen("CN={"))) {
+ status = ads_get_gpo(ads, mem_ctx, argv[0], NULL, NULL, &gpo);
+ } else {
+ status = ads_get_gpo(ads, mem_ctx, NULL, argv[0], NULL, &gpo);
+ }
+
+ if (!ADS_ERR_OK(status)) {
+ d_printf("get gpo for [%s] failed: %s\n", argv[0], ads_errstr(status));
+ 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);
+
+out:
+ talloc_destroy(mem_ctx);
+ ads_destroy(&ads);
+
+ return 0;
+}
+
+int net_ads_gpo(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"LIST", net_ads_gpo_list},
+ {"EFFECTIVE", net_ads_gpo_effective},
+ {"ADDLINK", net_ads_gpo_add_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},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, net_ads_gpo_usage);
+}
+
+#endif
diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c
index eb33c9d57ea..a96ac526bfc 100644
--- a/source/utils/net_groupmap.c
+++ b/source/utils/net_groupmap.c
@@ -2,7 +2,7 @@
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
- * Copyright (C) Jean François Micouleau 1998-2001.
+ * Copyright (C) Jean François Micouleau 1998-2001.
* Copyright (C) Gerald Carter 2003,
* Copyright (C) Volker Lendecke 2004
*
@@ -93,6 +93,7 @@ static void print_map_entry ( GROUP_MAP map, BOOL long_list )
else {
d_printf("%s\n", map.nt_name);
d_printf("\tSID : %s\n", sid_string_static(&map.sid));
+ d_printf("\tUnix gid : %d\n", map.gid);
d_printf("\tUnix group: %s\n", gidtoname(map.gid));
d_printf("\tGroup type: %s\n",
sid_type_lookup(map.sid_name_use));
@@ -162,7 +163,7 @@ static int net_groupmap_list(int argc, const char **argv)
else {
GROUP_MAP *map=NULL;
/* enumerate all group mappings */
- if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &entries, ENUM_ALL_MAPPED))
+ if (!pdb_enum_group_mapping(NULL, SID_NAME_UNKNOWN, &map, &entries, ENUM_ALL_MAPPED))
return -1;
for (i=0; i<entries; i++) {
@@ -261,10 +262,26 @@ static int net_groupmap_add(int argc, const char **argv)
d_fprintf(stderr, "Can't lookup UNIX group %s\n", unixgrp);
return -1;
}
+
+ {
+ 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));
+ return -1;
+ }
+ }
if ( (rid == 0) && (string_sid[0] == '\0') ) {
- d_printf("No rid or sid specified, choosing algorithmic mapping\n");
- rid = pdb_gid_to_group_rid(gid);
+ d_printf("No rid or sid specified, choosing a RID\n");
+ if (pdb_rid_algorithm()) {
+ rid = pdb_gid_to_group_rid(gid);
+ } else {
+ if (!pdb_new_rid(&rid)) {
+ d_printf("Could not get new RID\n");
+ }
+ }
+ d_printf("Got RID %d\n", rid);
}
/* append the rid to our own domain/machine SID if we don't have a full SID */
@@ -295,7 +312,7 @@ static int net_groupmap_add(int argc, const char **argv)
fstrcpy( ntgroup, unixgrp );
- if (!add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment)) {
+ if (!NT_STATUS_IS_OK(add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment))) {
d_fprintf(stderr, "adding entry for group %s failed!\n", ntgroup);
return -1;
}
@@ -423,7 +440,7 @@ static int net_groupmap_modify(int argc, const char **argv)
map.gid = gid;
}
- if ( !pdb_update_group_mapping_entry(&map) ) {
+ if ( !NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map)) ) {
d_fprintf(stderr, "Could not update group database\n");
return -1;
}
@@ -477,7 +494,7 @@ static int net_groupmap_delete(int argc, const char **argv)
return -1;
}
- if ( !pdb_delete_group_mapping_entry(sid) ) {
+ if ( !NT_STATUS_IS_OK(pdb_delete_group_mapping_entry(sid)) ) {
d_fprintf(stderr, "Failed to removing group %s from the mapping db!\n", ntgroup);
return -1;
}
@@ -548,7 +565,7 @@ static int net_groupmap_set(int argc, const char **argv)
fstrcpy(map.nt_name, ntgroup);
fstrcpy(map.comment, "");
- if (!pdb_add_group_mapping_entry(&map)) {
+ if (!NT_STATUS_IS_OK(pdb_add_group_mapping_entry(&map))) {
d_fprintf(stderr, "Could not add mapping entry for %s\n",
ntgroup);
return -1;
@@ -582,7 +599,7 @@ static int net_groupmap_set(int argc, const char **argv)
if (grp != NULL)
map.gid = grp->gr_gid;
- if (!pdb_update_group_mapping_entry(&map)) {
+ if (!NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map))) {
d_fprintf(stderr, "Could not update group mapping for %s\n", ntgroup);
return -1;
}
@@ -595,7 +612,7 @@ static int net_groupmap_cleanup(int argc, const char **argv)
GROUP_MAP *map = NULL;
size_t i, entries;
- if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &entries,
+ if (!pdb_enum_group_mapping(NULL, SID_NAME_UNKNOWN, &map, &entries,
ENUM_ALL_MAPPED)) {
d_fprintf(stderr, "Could not list group mappings\n");
return -1;
@@ -603,9 +620,6 @@ static int net_groupmap_cleanup(int argc, const char **argv)
for (i=0; i<entries; i++) {
- if (map[i].sid_name_use == SID_NAME_WKN_GRP)
- continue;
-
if (map[i].gid == -1)
printf("Group %s is not mapped\n", map[i].nt_name);
@@ -633,7 +647,7 @@ static int net_groupmap_addmem(int argc, const char **argv)
return -1;
}
- if (!pdb_add_aliasmem(&alias, &member)) {
+ if (!NT_STATUS_IS_OK(pdb_add_aliasmem(&alias, &member))) {
d_fprintf(stderr, "Could not add sid %s to alias %s\n",
argv[1], argv[0]);
return -1;
@@ -653,7 +667,7 @@ static int net_groupmap_delmem(int argc, const char **argv)
return -1;
}
- if (!pdb_del_aliasmem(&alias, &member)) {
+ if (!NT_STATUS_IS_OK(pdb_del_aliasmem(&alias, &member))) {
d_fprintf(stderr, "Could not delete sid %s from alias %s\n",
argv[1], argv[0]);
return -1;
@@ -677,7 +691,7 @@ static int net_groupmap_listmem(int argc, const char **argv)
members = NULL;
num = 0;
- if (!pdb_enum_aliasmem(&alias, &members, &num)) {
+ if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(&alias, &members, &num))) {
d_fprintf(stderr, "Could not list members for sid %s\n", argv[0]);
return -1;
}
@@ -701,8 +715,9 @@ static BOOL print_alias_memberships(TALLOC_CTX *mem_ctx,
alias_rids = NULL;
num_alias_rids = 0;
- if (!pdb_enum_alias_memberships(mem_ctx, domain_sid, member, 1,
- &alias_rids, &num_alias_rids)) {
+ if (!NT_STATUS_IS_OK(pdb_enum_alias_memberships(
+ mem_ctx, domain_sid, member, 1,
+ &alias_rids, &num_alias_rids))) {
d_fprintf(stderr, "Could not list memberships for sid %s\n",
sid_string_static(member));
return False;
@@ -800,7 +815,7 @@ int net_groupmap(int argc, const char **argv)
/* we shouldn't have silly checks like this */
if (getuid() != 0) {
- d_fprintf(stderr, "You must be root to edit group mappings.\nExiting...\n");
+ d_fprintf(stderr, "You must be root to edit group mappings.\n");
return -1;
}
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index c5188c3608e..79062345ab6 100644
--- a/source/utils/net_help.c
+++ b/source/utils/net_help.c
@@ -61,7 +61,7 @@ static int help_usage(int argc, const char **argv)
"Valid functions are:\n"\
" RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\
" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP GETLOCALSID SETLOCALSID\n"\
-" CHANGESCRETPW IDMAP\n");
+" CHANGESCRETPW LOOKUP SAM\n");
return -1;
}
@@ -223,8 +223,9 @@ static int net_usage(int argc, const char **argv)
" net lookup\t\tto lookup host name or ip address\n"\
" net user\t\tto manage users\n"\
" net group\t\tto manage groups\n"\
+ " net sam\t\tto edit the local user database directly\n"\
+ " net lookup\t\tto look up various things\n"\
" net groupmap\t\tto manage group mappings\n"\
- " net idmap\t\tto manage the idmap id mappings\n"\
" net join\t\tto join a domain\n"\
" net cache\t\tto operate on cache tdb file\n"\
" net getlocalsid [NAME]\tto get the SID for local name\n"\
@@ -233,6 +234,7 @@ static int net_usage(int argc, const char **argv)
" \tthis requires the -f flag as a safety barrier\n"\
" net status\t\tShow server status\n"\
" net usersidlist\tto get a list of all users with their SIDs\n"
+ " net usershare\t\tto add, delete and list locally user-modifiable shares\n"
"\n"\
" net ads <command>\tto run ADS commands\n"\
" net rap <command>\tto run RAP (pre-RPC) commands\n"\
@@ -270,11 +272,12 @@ int net_help(int argc, const char **argv)
{"PASSWORD", net_rap_password_usage},
{"TIME", net_time_usage},
{"LOOKUP", net_lookup_usage},
+ {"USERSHARE", net_usershare_usage},
{"USERSIDLIST", net_usersidlist_usage},
#ifdef WITH_FAKE_KASERVER
{"AFS", net_help_afs},
#endif
- {"IDMAP", net_help_idmap},
+
{"HELP", help_usage},
{NULL, NULL}};
diff --git a/source/utils/net_lookup.c b/source/utils/net_lookup.c
index 8ee63515d45..dd2d666d5a0 100644
--- a/source/utils/net_lookup.c
+++ b/source/utils/net_lookup.c
@@ -28,6 +28,8 @@ int net_lookup_usage(int argc, const char **argv)
" net lookup kdc [realm]\n\tgives IP of realm's kerberos KDC\n\n"
" net lookup dc [domain]\n\tgives IP of domains Domain Controllers\n\n"
" net lookup master [domain|wg]\n\tgive IP of master browser\n\n"
+" net lookup name [name]\n\tLookup name's sid and type\n\n"
+" net lookup sid [sid]\n\tGive sid's name and type\n\n"
);
return -1;
}
@@ -227,6 +229,54 @@ static int net_lookup_kdc(int argc, const char **argv)
return -1;
}
+static int net_lookup_name(int argc, const char **argv)
+{
+ const char *dom, *name;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+
+ if (argc != 1) {
+ d_printf("usage: net lookup name <name>\n");
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ALL,
+ &dom, &name, &sid, &type)) {
+ d_printf("Could not lookup name %s\n", argv[0]);
+ return -1;
+ }
+
+ d_printf("%s %d (%s) %s\\%s\n", sid_string_static(&sid),
+ type, sid_type_lookup(type), dom, name);
+ return 0;
+}
+
+static int net_lookup_sid(int argc, const char **argv)
+{
+ const char *dom, *name;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+
+ if (argc != 1) {
+ d_printf("usage: net lookup sid <sid>\n");
+ return -1;
+ }
+
+ if (!string_to_sid(&sid, argv[0])) {
+ d_printf("Could not convert %s to SID\n", argv[0]);
+ return -1;
+ }
+
+ if (!lookup_sid(tmp_talloc_ctx(), &sid,
+ &dom, &name, &type)) {
+ d_printf("Could not lookup name %s\n", argv[0]);
+ return -1;
+ }
+
+ d_printf("%s %d (%s) %s\\%s\n", sid_string_static(&sid),
+ type, sid_type_lookup(type), dom, name);
+ return 0;
+}
/* lookup hosts or IP addresses using internal samba lookup fns */
int net_lookup(int argc, const char **argv)
@@ -239,6 +289,8 @@ int net_lookup(int argc, const char **argv)
{"DC", net_lookup_dc},
{"MASTER", net_lookup_master},
{"KDC", net_lookup_kdc},
+ {"NAME", net_lookup_name},
+ {"SID", net_lookup_sid},
{NULL, NULL}
};
diff --git a/source/utils/net_rap.c b/source/utils/net_rap.c
index e80beb36456..ef5df435357 100644
--- a/source/utils/net_rap.c
+++ b/source/utils/net_rap.c
@@ -200,6 +200,10 @@ static int rap_share_add(int argc, const char **argv)
sharename = SMB_STRDUP(argv[0]);
p = strchr(sharename, '=');
+ if (p == NULL) {
+ d_printf("Server path not specified\n");
+ return net_rap_share_usage(argc, argv);
+ }
*p = 0;
strlcpy(sinfo.share_name, sharename, sizeof(sinfo.share_name));
sinfo.reserved1 = '\0';
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 0495a7b92c2..efc9bfbfafb 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -49,46 +49,42 @@ static int net_mode_share;
* @return The Domain SID of the remote machine.
**/
-static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, char **domain_name)
+NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ DOM_SID **domain_sid, char **domain_name)
{
struct rpc_pipe_client *lsa_pipe;
- DOM_SID *domain_sid;
POLICY_HND pol;
NTSTATUS result = NT_STATUS_OK;
uint32 info_class = 5;
lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
if (!lsa_pipe) {
- fprintf(stderr, "could not initialise lsa pipe\n");
- goto error;
+ d_fprintf(stderr, "Could not initialise lsa pipe\n");
+ return result;
}
result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False,
SEC_RIGHTS_MAXIMUM_ALLOWED,
&pol);
if (!NT_STATUS_IS_OK(result)) {
- goto error;
+ d_fprintf(stderr, "open_policy failed: %s\n",
+ nt_errstr(result));
+ return result;
}
- result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol, info_class,
- domain_name, &domain_sid);
+ result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol,
+ info_class, domain_name,
+ domain_sid);
if (!NT_STATUS_IS_OK(result)) {
- error:
- fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
-
- if (!NT_STATUS_IS_OK(result)) {
- fprintf(stderr, "error: %s\n", nt_errstr(result));
- }
-
- exit(1);
+ d_fprintf(stderr, "lsaquery failed: %s\n",
+ nt_errstr(result));
+ return result;
}
- if (lsa_pipe) {
- rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
- cli_rpc_pipe_close(lsa_pipe);
- }
+ rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
+ cli_rpc_pipe_close(lsa_pipe);
- return domain_sid;
+ return NT_STATUS_OK;
}
/**
@@ -136,7 +132,12 @@ int run_rpc_command(struct cli_state *cli_arg,
return -1;
}
- domain_sid = net_get_remote_domain_sid(cli, mem_ctx, &domain_name);
+ nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
+ &domain_name);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ cli_shutdown(cli);
+ return -1;
+ }
if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
@@ -388,6 +389,12 @@ static int rpc_join_usage(int argc, const char **argv)
int net_rpc_join(int argc, const char **argv)
{
+ if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
+ (lp_server_role() != ROLE_DOMAIN_BDC)) {
+ d_printf("can only join as domain member or as BDC\n");
+ return -1;
+ }
+
if ((net_rpc_perform_oldjoin(argc, argv) == 0))
return 0;
@@ -410,7 +417,7 @@ int net_rpc_join(int argc, const char **argv)
* @return Normal NTSTATUS return.
**/
-static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
+NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
const char *domain_name,
struct cli_state *cli,
struct rpc_pipe_client *pipe_hnd,
@@ -429,6 +436,7 @@ static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
&connect_pol);
if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
goto done;
}
@@ -437,6 +445,7 @@ static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
MAXIMUM_ALLOWED_ACCESS,
domain_sid, &domain_pol);
if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
goto done;
}
@@ -467,7 +476,7 @@ static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
int net_rpc_info(int argc, const char **argv)
{
- return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
+ return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_PDC,
rpc_info_internals,
argc, argv);
}
@@ -565,7 +574,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
POLICY_HND connect_pol, domain_pol, user_pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
const char *acct_name;
- uint16 acb_info;
+ uint32 acb_info;
uint32 unknown, user_rid;
if (argc != 1) {
@@ -1219,6 +1228,380 @@ int net_rpc_user(int argc, const char **argv)
return net_run_function(argc, argv, func, rpc_user_usage);
}
+static NTSTATUS rpc_sh_user_list(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_user_list_internals(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+static NTSTATUS rpc_sh_user_info(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_user_info_internals(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv,
+ NTSTATUS (*fn)(
+ TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ const POLICY_HND *user_hnd,
+ int argc, const char **argv))
+
+{
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ DOM_SID sid;
+ uint32 rid;
+ enum SID_NAME_USE type;
+
+ if (argc == 0) {
+ d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ZERO_STRUCT(connect_pol);
+ ZERO_STRUCT(domain_pol);
+ ZERO_STRUCT(user_pol);
+
+ result = net_rpc_lookup_name(mem_ctx, pipe_hnd->cli, argv[0],
+ NULL, NULL, &sid, &type);
+ if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
+ nt_errstr(result));
+ goto done;
+ }
+
+ if (type != SID_NAME_USER) {
+ d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+ sid_type_lookup(type));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
+ d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ result = rpccli_samr_connect(pipe_hnd, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS, &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ ctx->domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ rid, &user_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = fn(mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
+
+ done:
+ if (is_valid_policy_hnd(&user_pol)) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+ }
+ if (is_valid_policy_hnd(&domain_pol)) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+ }
+ if (is_valid_policy_hnd(&connect_pol)) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
+ }
+ return result;
+}
+
+static NTSTATUS rpc_sh_user_show_internals(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ const POLICY_HND *user_hnd,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ SAM_USERINFO_CTR *ctr;
+ SAM_USER_INFO_21 *info;
+
+ if (argc != 0) {
+ d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
+ 21, &ctr);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ info = ctr->info.id21;
+
+ d_printf("user rid: %d, group rid: %d\n", info->user_rid,
+ info->group_rid);
+
+ return result;
+}
+
+static NTSTATUS rpc_sh_user_show(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
+ rpc_sh_user_show_internals);
+}
+
+#define FETCHSTR(name, rec) \
+do { if (strequal(ctx->thiscmd, name)) { \
+ oldval = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_##rec); } \
+} while (0);
+
+#define SETSTR(name, rec, flag) \
+do { if (strequal(ctx->thiscmd, name)) { \
+ init_unistr2(&usr->uni_##rec, argv[0], STR_TERMINATE); \
+ init_uni_hdr(&usr->hdr_##rec, &usr->uni_##rec); \
+ usr->fields_present |= ACCT_##flag; } \
+} while (0);
+
+static NTSTATUS rpc_sh_user_str_edit_internals(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ const POLICY_HND *user_hnd,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ SAM_USERINFO_CTR *ctr;
+ SAM_USER_INFO_21 *usr;
+ const char *username;
+ const char *oldval = "";
+
+ if (argc > 1) {
+ d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
+ ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
+ 21, &ctr);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ usr = ctr->info.id21;
+
+ username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
+
+ FETCHSTR("fullname", full_name);
+ FETCHSTR("homedir", home_dir);
+ FETCHSTR("homedrive", dir_drive);
+ FETCHSTR("logonscript", logon_script);
+ FETCHSTR("profilepath", profile_path);
+ FETCHSTR("description", acct_desc);
+
+ if (argc == 0) {
+ d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
+ goto done;
+ }
+
+ ZERO_STRUCTP(usr);
+
+ if (strcmp(argv[0], "NULL") == 0) {
+ argv[0] = "";
+ }
+
+ SETSTR("fullname", full_name, FULL_NAME);
+ SETSTR("homedir", home_dir, HOME_DIR);
+ SETSTR("homedrive", dir_drive, HOME_DRIVE);
+ SETSTR("logonscript", logon_script, LOGON_SCRIPT);
+ SETSTR("profilepath", profile_path, PROFILE);
+ SETSTR("description", acct_desc, DESCRIPTION);
+
+ result = rpccli_samr_set_userinfo2(
+ pipe_hnd, mem_ctx, user_hnd, 21,
+ &pipe_hnd->cli->user_session_key, ctr);
+
+ d_printf("Set %s's %s from [%s] to [%s]\n", username,
+ ctx->thiscmd, oldval, argv[0]);
+
+ done:
+
+ return result;
+}
+
+#define HANDLEFLG(name, rec) \
+do { if (strequal(ctx->thiscmd, name)) { \
+ oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
+ if (newval) { \
+ newflags = oldflags | ACB_##rec; \
+ } else { \
+ newflags = oldflags & ~ACB_##rec; \
+ } } } while (0);
+
+static NTSTATUS rpc_sh_user_str_edit(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
+ rpc_sh_user_str_edit_internals);
+}
+
+static NTSTATUS rpc_sh_user_flag_edit_internals(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ const POLICY_HND *user_hnd,
+ int argc, const char **argv)
+{
+ NTSTATUS result;
+ SAM_USERINFO_CTR *ctr;
+ SAM_USER_INFO_21 *usr;
+ const char *username;
+ const char *oldval = "unknown";
+ uint32 oldflags, newflags;
+ BOOL newval;
+
+ if ((argc > 1) ||
+ ((argc == 1) && !strequal(argv[0], "yes") &&
+ !strequal(argv[0], "no"))) {
+ d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
+ ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ newval = strequal(argv[0], "yes");
+
+ result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
+ 21, &ctr);
+ if (!NT_STATUS_IS_OK(result)) {
+ return result;
+ }
+
+ usr = ctr->info.id21;
+
+ username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
+ oldflags = usr->acb_info;
+ newflags = usr->acb_info;
+
+ HANDLEFLG("disabled", DISABLED);
+ HANDLEFLG("pwnotreq", PWNOTREQ);
+ HANDLEFLG("autolock", AUTOLOCK);
+ HANDLEFLG("pwnoexp", PWNOEXP);
+
+ if (argc == 0) {
+ d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
+ goto done;
+ }
+
+ ZERO_STRUCTP(usr);
+
+ usr->acb_info = newflags;
+ usr->fields_present = ACCT_FLAGS;
+
+ result = rpccli_samr_set_userinfo2(
+ pipe_hnd, mem_ctx, user_hnd, 21,
+ &pipe_hnd->cli->user_session_key, ctr);
+
+ if (NT_STATUS_IS_OK(result)) {
+ d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
+ ctx->thiscmd, oldval, argv[0]);
+ }
+
+ done:
+
+ return result;
+}
+
+static NTSTATUS rpc_sh_user_flag_edit(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
+ rpc_sh_user_flag_edit_internals);
+}
+
+struct rpc_sh_cmd *net_rpc_user_edit_cmds(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx)
+{
+ static struct rpc_sh_cmd cmds[] = {
+
+ { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
+ "Show/Set a user's full name" },
+
+ { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
+ "Show/Set a user's home directory" },
+
+ { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
+ "Show/Set a user's home drive" },
+
+ { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
+ "Show/Set a user's logon script" },
+
+ { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
+ "Show/Set a user's profile path" },
+
+ { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
+ "Show/Set a user's description" },
+
+ { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+ "Show/Set whether a user is disabled" },
+
+ { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+ "Show/Set whether a user locked out" },
+
+ { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+ "Show/Set whether a user does not need a password" },
+
+ { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+ "Show/Set whether a user's password does not expire" },
+
+ { NULL, NULL, 0, NULL, NULL }
+ };
+
+ return cmds;
+}
+
+struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx)
+{
+ static struct rpc_sh_cmd cmds[] = {
+
+ { "list", NULL, PI_SAMR, rpc_sh_user_list,
+ "List available users" },
+
+ { "info", NULL, PI_SAMR, rpc_sh_user_info,
+ "List the domain groups a user is member of" },
+
+ { "show", NULL, PI_SAMR, rpc_sh_user_show,
+ "Show info about a user" },
+
+ { "edit", net_rpc_user_edit_cmds, 0, NULL,
+ "Show/Modify a user's fields" },
+
+ { NULL, NULL, 0, NULL, NULL }
+ };
+
+ return cmds;
+};
+
/****************************************************************************/
/**
@@ -1580,7 +1963,7 @@ static NTSTATUS get_sid_from_name(struct cli_state *cli,
}
result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
- &name, &sids, &types);
+ &name, NULL, &sids, &types);
if (NT_STATUS_IS_OK(result)) {
sid_copy(sid, &sids[0]);
@@ -2581,7 +2964,7 @@ static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
opt_comment, perms, opt_maxusers,
num_users, path, password,
level, NULL);
- return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ return werror_to_ntstatus(result);
}
static int rpc_share_add(int argc, const char **argv)
@@ -3719,6 +4102,9 @@ static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
return;
token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
+ if (!token->user_sids) {
+ return;
+ }
sid_copy(&token->user_sids[token->num_sids], sid);
@@ -3832,7 +4218,7 @@ static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *t
}
for (i = 0; i < response.data.num_entries; i++) {
- gid_t gid = ((gid_t *)response.extra_data)[i];
+ gid_t gid = ((gid_t *)response.extra_data.data)[i];
DOM_SID sid;
struct winbindd_request sidrequest;
@@ -3858,7 +4244,7 @@ static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *t
add_sid_to_token(token, &sid);
}
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
return True;
}
@@ -3894,10 +4280,10 @@ static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
/* Look through extra data */
- if (!response.extra_data)
+ if (!response.extra_data.data)
return False;
- extra_data = (const char *)response.extra_data;
+ extra_data = (const char *)response.extra_data.data;
*num_tokens = 0;
while(next_token(&extra_data, name, ",", sizeof(fstring))) {
@@ -3911,7 +4297,7 @@ static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
return False;
}
- extra_data = (const char *)response.extra_data;
+ extra_data = (const char *)response.extra_data.data;
i=0;
while(next_token(&extra_data, name, ",", sizeof(fstring))) {
@@ -3939,7 +4325,7 @@ static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
i+=1;
}
- SAFE_FREE(response.extra_data);
+ SAFE_FREE(response.extra_data.data);
*user_tokens = result;
@@ -4102,6 +4488,10 @@ static void collect_share(const char *name, uint32 m,
share_list->num_shares += 1;
share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
+ if (!share_list->shares) {
+ share_list->num_shares = 0;
+ return;
+ }
share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
}
@@ -4291,6 +4681,114 @@ int net_rpc_share(int argc, const char **argv)
return net_run_function(argc, argv, func, rpc_share_usage);
}
+static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ WERROR result;
+
+ if ((argc < 2) || (argc > 3)) {
+ d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
+ ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_srvsvc_net_share_add(
+ pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
+ (argc == 3) ? argv[2] : "",
+ 0, 0, 0, argv[1], NULL, 2, NULL);
+
+ return werror_to_ntstatus(result);
+}
+
+static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ WERROR result;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
+ return werror_to_ntstatus(result);
+}
+
+static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ SRV_SHARE_INFO info;
+ SRV_SHARE_INFO_2 *info2 = &info.share.info2;
+ WERROR result;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_srvsvc_net_share_get_info(
+ pipe_hnd, mem_ctx, argv[0], 2, &info);
+ if (!W_ERROR_IS_OK(result)) {
+ goto done;
+ }
+
+ d_printf("Name: %s\n",
+ rpcstr_pull_unistr2_talloc(mem_ctx,
+ &info2->info_2_str.uni_netname));
+ d_printf("Comment: %s\n",
+ rpcstr_pull_unistr2_talloc(mem_ctx,
+ &info2->info_2_str.uni_remark));
+
+ d_printf("Path: %s\n",
+ rpcstr_pull_unistr2_talloc(mem_ctx,
+ &info2->info_2_str.uni_path));
+ d_printf("Password: %s\n",
+ rpcstr_pull_unistr2_talloc(mem_ctx,
+ &info2->info_2_str.uni_passwd));
+
+ done:
+ return werror_to_ntstatus(result);
+}
+
+struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx)
+{
+ static struct rpc_sh_cmd cmds[] = {
+
+ { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
+ "List available shares" },
+
+ { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
+ "Add a share" },
+
+ { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
+ "Delete a share" },
+
+ { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
+ "Get information about a share" },
+
+ { NULL, NULL, 0, NULL, NULL }
+ };
+
+ return cmds;
+};
+
/****************************************************************************/
static int rpc_file_usage(int argc, const char **argv)
@@ -4747,7 +5245,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
POLICY_HND connect_pol, domain_pol, user_pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
char *acct_name;
- uint16 acb_info;
+ uint32 acb_info;
uint32 unknown, user_rid;
if (argc != 2) {
@@ -5011,7 +5509,6 @@ static int rpc_trustdom_establish(int argc, const char **argv)
TALLOC_CTX *mem_ctx;
NTSTATUS nt_status;
DOM_SID *domain_sid;
- smb_ucs2_t *uni_domain_name;
char* domain_name;
char* domain_name_pol;
@@ -5059,6 +5556,10 @@ static int rpc_trustdom_establish(int argc, const char **argv)
nt_errstr(nt_status)));
return -1;
}
+
+ /* store who we connected to */
+
+ saf_store( domain_name, pdc_name );
/*
* Connect to \\server\ipc$ again (this time anonymously)
@@ -5119,13 +5620,6 @@ static int rpc_trustdom_establish(int argc, const char **argv)
return -1;
}
- if (push_ucs2_talloc(mem_ctx, &uni_domain_name, domain_name_pol) == (size_t)-1) {
- DEBUG(0, ("Could not convert domain name %s to unicode\n",
- domain_name_pol));
- cli_shutdown(cli);
- return -1;
- }
-
/* There should be actually query info level 3 (following nt serv behaviour),
but I still don't know if it's _really_ necessary */
@@ -5134,10 +5628,8 @@ static int rpc_trustdom_establish(int argc, const char **argv)
*/
if (!secrets_store_trusted_domain_password(domain_name,
- uni_domain_name,
- strlen_w(uni_domain_name)+1,
opt_password,
- *domain_sid)) {
+ domain_sid)) {
DEBUG(0, ("Storing password for trusted domain failed.\n"));
cli_shutdown(cli);
return -1;
@@ -5253,7 +5745,6 @@ static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
LSA_TRUSTED_DOMAIN_INFO *info;
char *cleartextpwd = NULL;
DATA_BLOB data;
- smb_ucs2_t *uni_dom_name;
nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
@@ -5276,18 +5767,9 @@ static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
goto done;
}
- if (push_ucs2_talloc(mem_ctx, &uni_dom_name, trusted_dom_name) == (size_t)-1) {
- DEBUG(0, ("Could not convert domain name %s to unicode\n",
- trusted_dom_name));
- nt_status = NT_STATUS_UNSUCCESSFUL;
- goto done;
- }
-
if (!secrets_store_trusted_domain_password(trusted_dom_name,
- uni_dom_name,
- strlen_w(uni_dom_name)+1,
cleartextpwd,
- dom_sid)) {
+ &dom_sid)) {
DEBUG(0, ("Storing password for trusted domain failed.\n"));
nt_status = NT_STATUS_UNSUCCESSFUL;
goto done;
@@ -6163,7 +6645,6 @@ int net_rpc_help(int argc, const char **argv)
return (net_run_function(argc, argv, func, rpc_user_usage));
}
-
/**
* 'net rpc' entrypoint.
* @param argc Standard main() style argc
@@ -6174,6 +6655,7 @@ int net_rpc_help(int argc, const char **argv)
int net_rpc(int argc, const char **argv)
{
struct functable func[] = {
+ {"audit", net_rpc_audit},
{"info", net_rpc_info},
{"join", net_rpc_join},
{"oldjoin", net_rpc_oldjoin},
@@ -6194,6 +6676,7 @@ int net_rpc(int argc, const char **argv)
{"rights", net_rpc_rights},
{"service", net_rpc_service},
{"registry", net_rpc_registry},
+ {"shell", net_rpc_shell},
{"help", net_rpc_help},
{NULL, NULL}
};
diff --git a/source/utils/net_rpc_audit.c b/source/utils/net_rpc_audit.c
new file mode 100644
index 00000000000..5c81fe24d09
--- /dev/null
+++ b/source/utils/net_rpc_audit.c
@@ -0,0 +1,414 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2006 Guenther Deschner
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "includes.h"
+#include "utils/net.h"
+
+/********************************************************************
+********************************************************************/
+
+static int net_help_audit(int argc, const char **argv)
+{
+ d_printf("net rpc audit list View configured Auditing policies\n");
+ d_printf("net rpc audit enable Enable Auditing\n");
+ d_printf("net rpc audit disable Disable Auditing\n");
+ d_printf("net rpc audit get <category> View configured Auditing policy setting\n");
+ d_printf("net rpc audit set <category> <policy> Set Auditing policies\n\n");
+ d_printf("\tcategory can be one of: SYSTEM, LOGON, OBJECT, PRIVILEGE, PROCESS, POLICY, SAM, DIRECTORY or ACCOUNT\n");
+ d_printf("\tpolicy can be one of: SUCCESS, FAILURE, ALL or NONE\n\n");
+
+ return -1;
+}
+
+/********************************************************************
+********************************************************************/
+
+static void print_auditing_category(const char *policy, const char *value)
+{
+ fstring padding;
+ int pad_len, col_len = 30;
+
+ /* calculate padding space for d_printf to look nicer */
+ pad_len = col_len - strlen(policy);
+ padding[pad_len] = 0;
+ do padding[--pad_len] = ' '; while (pad_len > 0);
+
+ d_printf("\t%s%s%s\n", policy, padding, value);
+}
+
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_audit_get_internal(const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ LSA_INFO_CTR dom;
+ int i;
+
+ uint32 info_class = 2;
+ uint32 audit_category;
+
+ if (argc < 1 || argc > 2) {
+ d_printf("insufficient arguments\n");
+ net_help_audit(argc, argv);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!get_audit_category_from_param(argv[0], &audit_category)) {
+ d_printf("invalid auditing category: %s\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_query_info_policy_new(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ &dom);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ for (i=0; i < dom.info.id2.count1; i++) {
+
+ const char *val = NULL, *policy = NULL;
+
+ if (i != audit_category) {
+ continue;
+ }
+
+ val = audit_policy_str(mem_ctx, dom.info.id2.auditsettings[i]);
+ policy = audit_description_str(i);
+ print_auditing_category(policy, val);
+ }
+
+ done:
+ if (!NT_STATUS_IS_OK(result)) {
+ d_printf("failed to get auditing policy: %s\n", nt_errstr(result));
+ }
+
+ return result;
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_audit_set_internal(const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ LSA_INFO_CTR dom;
+
+ uint32 info_class = 2;
+ uint32 audit_policy, audit_category;
+
+ if (argc < 2 || argc > 3) {
+ d_printf("insufficient arguments\n");
+ net_help_audit(argc, argv);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!get_audit_category_from_param(argv[0], &audit_category)) {
+ d_printf("invalid auditing category: %s\n", argv[0]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ audit_policy = LSA_AUDIT_POLICY_CLEAR;
+
+ if (strequal(argv[1], "Success")) {
+ audit_policy |= LSA_AUDIT_POLICY_SUCCESS;
+ } else if (strequal(argv[1], "Failure")) {
+ audit_policy |= LSA_AUDIT_POLICY_FAILURE;
+ } else if (strequal(argv[1], "All")) {
+ audit_policy |= LSA_AUDIT_POLICY_ALL;
+ } else if (strequal(argv[1], "None")) {
+ audit_policy = LSA_AUDIT_POLICY_CLEAR;
+ } else {
+ d_printf("invalid auditing policy: %s\n", argv[1]);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_query_info_policy_new(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ &dom);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ dom.info.id2.auditsettings[audit_category] = audit_policy;
+
+ result = rpccli_lsa_set_info_policy(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ dom);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_query_info_policy_new(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ &dom);
+
+ {
+ const char *val = audit_policy_str(mem_ctx, dom.info.id2.auditsettings[audit_category]);
+ const char *policy = audit_description_str(audit_category);
+ print_auditing_category(policy, val);
+ }
+
+ done:
+ if (!NT_STATUS_IS_OK(result)) {
+ d_printf("failed to set audit policy: %s\n", nt_errstr(result));
+ }
+
+ return result;
+}
+
+static NTSTATUS rpc_audit_enable_internal_ext(struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv,
+ BOOL enable)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ LSA_INFO_CTR dom;
+
+ uint32 info_class = 2;
+
+ result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_query_info_policy_new(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ &dom);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ dom.info.id2.auditing_enabled = enable;
+
+ result = rpccli_lsa_set_info_policy(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ dom);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ if (!NT_STATUS_IS_OK(result)) {
+ d_printf("failed to %s audit policy: %s\n", enable ? "enable":"disable",
+ nt_errstr(result));
+ }
+
+ return result;
+}
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_audit_disable_internal(const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ return rpc_audit_enable_internal_ext(pipe_hnd, mem_ctx, argc, argv, False);
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_audit_enable_internal(const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ return rpc_audit_enable_internal_ext(pipe_hnd, mem_ctx, argc, argv, True);
+}
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_audit_list_internal(const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *pipe_hnd,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ LSA_INFO_CTR dom;
+ int i;
+
+ uint32 info_class = 2;
+
+ result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_lsa_query_info_policy_new(pipe_hnd, mem_ctx, &pol,
+ info_class,
+ &dom);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ printf("Auditing:\t\t");
+ switch (dom.info.id2.auditing_enabled) {
+ case True:
+ printf("Enabled");
+ break;
+ case False:
+ printf("Disabled");
+ break;
+ default:
+ printf("unknown (%d)", dom.info.id2.auditing_enabled);
+ break;
+ }
+ printf("\n");
+
+ printf("Auditing categories:\t%d\n", dom.info.id2.count1);
+ printf("Auditing settings:\n");
+
+ for (i=0; i < dom.info.id2.count1; i++) {
+ const char *val = audit_policy_str(mem_ctx, dom.info.id2.auditsettings[i]);
+ const char *policy = audit_description_str(i);
+ print_auditing_category(policy, val);
+ }
+
+ done:
+ if (!NT_STATUS_IS_OK(result)) {
+ d_printf("failed to list auditing policies: %s\n", nt_errstr(result));
+ }
+
+ return result;
+}
+
+
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_audit_get(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_LSARPC, 0,
+ rpc_audit_get_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_audit_set(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_LSARPC, 0,
+ rpc_audit_set_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_audit_enable(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_LSARPC, 0,
+ rpc_audit_enable_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_audit_disable(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_LSARPC, 0,
+ rpc_audit_disable_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_audit_list(int argc, const char **argv)
+{
+ return run_rpc_command(NULL, PI_LSARPC, 0,
+ rpc_audit_list_internal, argc, argv);
+}
+
+/********************************************************************
+********************************************************************/
+
+int net_rpc_audit(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"get", rpc_audit_get},
+ {"set", rpc_audit_set},
+ {"enable", rpc_audit_enable},
+ {"disable", rpc_audit_disable},
+ {"list", rpc_audit_list},
+ {NULL, NULL}
+ };
+
+ if (argc)
+ return net_run_function(argc, argv, func, net_help_audit);
+
+ return net_help_audit(argc, argv);
+}
diff --git a/source/utils/net_rpc_join.c b/source/utils/net_rpc_join.c
index 1f68da0d754..d611940e656 100644
--- a/source/utils/net_rpc_join.c
+++ b/source/utils/net_rpc_join.c
@@ -137,7 +137,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
NTSTATUS result;
int retval = 1;
- char *domain;
+ char *domain = NULL;
uint32 num_rids, *name_types, *user_rids;
uint32 flags = 0x3e8;
char *acct_name;
@@ -196,6 +196,12 @@ int net_rpc_join_newstyle(int argc, const char **argv)
rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
+ /* Bail out if domain didn't get set. */
+ if (!domain) {
+ DEBUG(0, ("Could not get domain name.\n"));
+ goto done;
+ }
+
/* Create domain user */
pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
if (!pipe_hnd) {
@@ -402,10 +408,12 @@ done:
/* Display success or failure */
- if (retval != 0) {
- fprintf(stderr,"Unable to join domain %s.\n",domain);
- } else {
- printf("Joined domain %s.\n",domain);
+ if (domain) {
+ if (retval != 0) {
+ fprintf(stderr,"Unable to join domain %s.\n",domain);
+ } else {
+ printf("Joined domain %s.\n",domain);
+ }
}
cli_shutdown(cli);
diff --git a/source/utils/net_rpc_printer.c b/source/utils/net_rpc_printer.c
index 5e282403a24..8808d549ac5 100644
--- a/source/utils/net_rpc_printer.c
+++ b/source/utils/net_rpc_printer.c
@@ -43,136 +43,6 @@ static const struct table_node archi_table[]= {
/**
- * The display-functions for Security-Descriptors were taken from rpcclient
- *
- * They reside here for debugging purpose and should
- * possibly be removed later on
- *
- **/
-
-/****************************************************************************
- Convert a security permissions into a string.
-****************************************************************************/
-
-char *get_sec_mask_str(uint32 type)
-{
- static fstring typestr="";
-
- typestr[0] = 0;
-
- if (type & GENERIC_ALL_ACCESS)
- fstrcat(typestr, "Generic all access ");
- if (type & GENERIC_EXECUTE_ACCESS)
- fstrcat(typestr, "Generic execute access ");
- if (type & GENERIC_WRITE_ACCESS)
- fstrcat(typestr, "Generic write access ");
- if (type & GENERIC_READ_ACCESS)
- fstrcat(typestr, "Generic read access ");
- if (type & MAXIMUM_ALLOWED_ACCESS)
- fstrcat(typestr, "MAXIMUM_ALLOWED_ACCESS ");
- if (type & SYSTEM_SECURITY_ACCESS)
- fstrcat(typestr, "SYSTEM_SECURITY_ACCESS ");
- if (type & SYNCHRONIZE_ACCESS)
- fstrcat(typestr, "SYNCHRONIZE_ACCESS ");
- if (type & WRITE_OWNER_ACCESS)
- fstrcat(typestr, "WRITE_OWNER_ACCESS ");
- if (type & WRITE_DAC_ACCESS)
- fstrcat(typestr, "WRITE_DAC_ACCESS ");
- if (type & READ_CONTROL_ACCESS)
- fstrcat(typestr, "READ_CONTROL_ACCESS ");
- if (type & DELETE_ACCESS)
- fstrcat(typestr, "DELETE_ACCESS ");
-
- printf("\t\tSpecific bits: 0x%lx\n", (unsigned long)type&SPECIFIC_RIGHTS_MASK);
-
- return typestr;
-}
-
-/****************************************************************************
- Display sec_ace structure.
- ****************************************************************************/
-
-void display_sec_ace(SEC_ACE *ace)
-{
- fstring sid_str;
-
- printf("\tACE\n\t\ttype: ");
- switch (ace->type) {
- case SEC_ACE_TYPE_ACCESS_ALLOWED:
- printf("ACCESS ALLOWED");
- break;
- case SEC_ACE_TYPE_ACCESS_DENIED:
- printf("ACCESS DENIED");
- break;
- case SEC_ACE_TYPE_SYSTEM_AUDIT:
- printf("SYSTEM AUDIT");
- break;
- case SEC_ACE_TYPE_SYSTEM_ALARM:
- printf("SYSTEM ALARM");
- break;
- default:
- printf("????");
- break;
- }
- printf(" (%d) flags: %d\n", ace->type, ace->flags);
- printf("\t\tPermissions: 0x%x: %s\n", ace->info.mask, get_sec_mask_str(ace->info.mask));
-
- sid_to_string(sid_str, &ace->trustee);
- printf("\t\tSID: %s\n\n", sid_str);
-}
-
-/****************************************************************************
- Display sec_acl structure.
- ****************************************************************************/
-
-void display_sec_acl(SEC_ACL *sec_acl)
-{
- int i;
-
- printf("\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
- sec_acl->num_aces, sec_acl->revision);
- printf("\t---\n");
-
- 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_desc structure.
- ****************************************************************************/
-
-void display_sec_desc(SEC_DESC *sec)
-{
- fstring sid_str;
-
- if (sec == NULL)
- return;
-
- if (sec->sacl) {
- printf("SACL\n");
- display_sec_acl(sec->sacl);
- }
-
- if (sec->dacl) {
- printf("DACL\n");
- display_sec_acl(sec->dacl);
- }
-
- if (sec->owner_sid) {
- sid_to_string(sid_str, sec->owner_sid);
- printf("\tOwner SID:\t%s\n", sid_str);
- }
-
- if (sec->grp_sid) {
- sid_to_string(sid_str, sec->grp_sid);
- printf("\tParent SID:\t%s\n", sid_str);
- }
-}
-
-
-/**
* This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
* It is here for debugging purpose and should be removed later on.
**/
@@ -2052,7 +1922,6 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
if (!NT_STATUS_IS_OK(nt_status))
return nt_status;
-
/* enum printers */
if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -2081,7 +1950,6 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
d_printf("migrating printer queue for: [%s] / [%s]\n",
printername, sharename);
-
/* open dst printer handle */
if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
@@ -2091,18 +1959,12 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
got_hnd_dst = True;
}
-
/* check for existing dst printer */
if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
printf ("could not get printer, creating printer.\n");
} else {
DEBUG(1,("printer already exists: %s\n", sharename));
- /* close printer handles here */
- if (got_hnd_src) {
- rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
- got_hnd_src = False;
- }
-
+ /* close printer handle here - dst only, not got src yet. */
if (got_hnd_dst) {
rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
got_hnd_dst = False;
@@ -2110,7 +1972,6 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
continue;
}
-
/* now get again src printer ctr via getprinter,
we first need a handle for that */
@@ -2125,7 +1986,6 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &ctr_src))
goto done;
-
/* copy each src printer to a dst printer 1:1,
maybe some values have to be changed though */
d_printf("creating printer: %s\n", printername);
diff --git a/source/utils/net_rpc_registry.c b/source/utils/net_rpc_registry.c
index 9852fe4a94f..33d5310698e 100644
--- a/source/utils/net_rpc_registry.c
+++ b/source/utils/net_rpc_registry.c
@@ -100,7 +100,7 @@ static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
if (argc != 1 ) {
d_printf("Usage: net rpc enumerate <path> [recurse]\n");
- d_printf("Example:: net rpc enumerate 'HKLM\\Software\\Samba'\n");
+ d_printf("Example: net rpc enumerate 'HKLM\\Software\\Samba'\n");
return NT_STATUS_OK;
}
diff --git a/source/utils/net_rpc_rights.c b/source/utils/net_rpc_rights.c
index 2c15fef5a09..2f02b409483 100644
--- a/source/utils/net_rpc_rights.c
+++ b/source/utils/net_rpc_rights.c
@@ -75,7 +75,8 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
if ( !NT_STATUS_IS_OK(result) )
return result;
- result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+ result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name,
+ NULL, &sids, &sid_types);
if ( NT_STATUS_IS_OK(result) )
sid_copy( sid, &sids[0] );
@@ -488,7 +489,7 @@ static NTSTATUS rpc_rights_revoke_internal(const DOM_SID *domain_sid,
done:
if ( !NT_STATUS_IS_OK(result) ) {
- d_fprintf(stderr, "Failed to revoke privileges for %s (%s)",
+ d_fprintf(stderr, "Failed to revoke privileges for %s (%s)\n",
argv[0], nt_errstr(result));
}
@@ -560,3 +561,53 @@ int net_rpc_rights(int argc, const char **argv)
return net_help_rights( argc, argv );
}
+
+static NTSTATUS rpc_sh_rights_list(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_rights_list_internal(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+static NTSTATUS rpc_sh_rights_grant(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_rights_grant_internal(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+static NTSTATUS rpc_sh_rights_revoke(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_rights_revoke_internal(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+struct rpc_sh_cmd *net_rpc_rights_cmds(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx)
+{
+ static struct rpc_sh_cmd cmds[] = {
+
+ { "list", NULL, PI_LSARPC, rpc_sh_rights_list,
+ "View available or assigned privileges" },
+
+ { "grant", NULL, PI_LSARPC, rpc_sh_rights_grant,
+ "Assign privilege[s]" },
+
+ { "revoke", NULL, PI_LSARPC, rpc_sh_rights_revoke,
+ "Revoke privilege[s]" },
+
+ { NULL, NULL, 0, NULL, NULL }
+ };
+
+ return cmds;
+};
+
diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c
index 09e62d9defa..b1807bb79b1 100644
--- a/source/utils/net_rpc_samsync.c
+++ b/source/utils/net_rpc_samsync.c
@@ -300,12 +300,16 @@ NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid,
return NT_STATUS_OK;
}
-/* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */
+/* Convert a struct samu_DELTA to a struct samu. */
#define STRING_CHANGED (old_string && !new_string) ||\
(!old_string && new_string) ||\
(old_string && new_string && (strcmp(old_string, new_string) != 0))
-static NTSTATUS sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)
+#define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
+ (!(s1) && (s2)) ||\
+ ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
+
+static NTSTATUS sam_account_from_delta(struct samu *account, SAM_ACCOUNT_INFO *delta)
{
const char *old_string, *new_string;
time_t unix_time, stored_time;
@@ -389,13 +393,15 @@ static NTSTATUS sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *d
if (delta->hdr_parameters.buffer) {
DATA_BLOB mung;
+ char *newstr;
old_string = pdb_get_munged_dial(account);
mung.length = delta->hdr_parameters.uni_str_len;
mung.data = (uint8 *) delta->uni_parameters.buffer;
- new_string = (mung.length == 0) ? NULL : base64_encode_data_blob(mung);
+ newstr = (mung.length == 0) ? NULL : base64_encode_data_blob(mung);
- if (STRING_CHANGED)
- pdb_set_munged_dial(account, new_string, PDB_CHANGED);
+ if (STRING_CHANGED_NC(old_string, newstr))
+ pdb_set_munged_dial(account, newstr, PDB_CHANGED);
+ SAFE_FREE(newstr);
}
/* User and group sid */
@@ -494,10 +500,10 @@ static NTSTATUS sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *d
static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
{
- NTSTATUS nt_ret;
+ NTSTATUS nt_ret = NT_STATUS_UNSUCCESSFUL;
fstring account;
pstring add_script;
- SAM_ACCOUNT *sam_account=NULL;
+ struct samu *sam_account=NULL;
GROUP_MAP map;
struct group *grp;
DOM_SID user_sid;
@@ -508,8 +514,9 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
fstrcpy(account, unistr2_static(&delta->uni_acct_name));
d_printf("Creating account: %s\n", account);
- if (!NT_STATUS_IS_OK(nt_ret = pdb_init_sam(&sam_account)))
- return nt_ret;
+ if ( !(sam_account = samu_new( NULL )) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
if (!(passwd = Get_Pwnam(account))) {
/* Create appropriate user */
@@ -550,7 +557,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
sam_account_from_delta(sam_account, delta);
DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
- if (!pdb_add_sam_account(sam_account)) {
+ if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account))) {
DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
account));
return NT_STATUS_ACCESS_DENIED;
@@ -559,10 +566,10 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
sam_account_from_delta(sam_account, delta);
DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
- if (!pdb_update_sam_account(sam_account)) {
+ if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account))) {
DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
account));
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return NT_STATUS_ACCESS_DENIED;
}
}
@@ -589,7 +596,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
}
done:
- pdb_free_sam(&sam_account);
+ TALLOC_FREE(sam_account);
return nt_ret;
}
@@ -690,13 +697,12 @@ static NTSTATUS fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
for (i=0; i<delta->num_members; i++) {
- NTSTATUS nt_status;
- SAM_ACCOUNT *member = NULL;
+ struct samu *member = NULL;
DOM_SID member_sid;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
+ if ( !(member = samu_new(t)) ) {
talloc_destroy(t);
- return nt_status;
+ return NT_STATUS_NO_MEMORY;
}
sid_copy(&member_sid, get_global_sam_sid());
@@ -705,19 +711,19 @@ static NTSTATUS fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
if (!pdb_getsampwsid(member, &member_sid)) {
DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n",
delta->rids[i], sid_string_static(&member_sid), grp->gr_name));
- pdb_free_sam(&member);
+ TALLOC_FREE(member);
continue;
}
if (pdb_get_group_rid(member) == rid) {
d_printf("%s(primary),", pdb_get_username(member));
- pdb_free_sam(&member);
+ TALLOC_FREE(member);
continue;
}
d_printf("%s,", pdb_get_username(member));
nt_members[i] = talloc_strdup(t, pdb_get_username(member));
- pdb_free_sam(&member);
+ TALLOC_FREE(member);
}
d_printf("\n");
@@ -835,145 +841,6 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,
static NTSTATUS fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
{
-#if 0 /*
- * commented out right now after talking to Volker. Can't
- * do much with the membership but seemed a shame to waste
- * somewhat working code. Needs testing because the membership
- * that shows up surprises me. Also can't do much with groups
- * in groups (e.g. Domain Admins being a member of Adminsitrators).
- * --jerry
- */
-
- int i;
- TALLOC_CTX *t = NULL;
- char **nt_members = NULL;
- char **unix_members;
- DOM_SID group_sid;
- GROUP_MAP map;
- struct group *grp;
- enum SID_NAME_USE sid_type;
-
- if (delta->num_members == 0) {
- return NT_STATUS_OK;
- }
-
- sid_copy(&group_sid, &dom_sid);
- sid_append_rid(&group_sid, rid);
-
- if (sid_equal(&dom_sid, &global_sid_Builtin)) {
- sid_type = SID_NAME_WKN_GRP;
- if (!get_builtin_group_from_sid(&group_sid, &map, False)) {
- DEBUG(0, ("Could not find builtin group %s\n", sid_string_static(&group_sid)));
- return NT_STATUS_NO_SUCH_GROUP;
- }
- } else {
- sid_type = SID_NAME_ALIAS;
- if (!get_local_group_from_sid(&group_sid, &map, False)) {
- DEBUG(0, ("Could not find local group %s\n", sid_string_static(&group_sid)));
- return NT_STATUS_NO_SUCH_GROUP;
- }
- }
-
- if (!(grp = getgrgid(map.gid))) {
- DEBUG(0, ("Could not find unix group %d\n", map.gid));
- return NT_STATUS_NO_SUCH_GROUP;
- }
-
- d_printf("Group members of %s: ", grp->gr_name);
-
- if (!(t = talloc_init("fetch_group_mem_info"))) {
- DEBUG(0, ("could not talloc_init\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
-
- for (i=0; i<delta->num_members; i++) {
- NTSTATUS nt_status;
- SAM_ACCOUNT *member = NULL;
- DOM_SID member_sid;
-
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
- talloc_destroy(t);
- return nt_status;
- }
-
- sid_copy(&member_sid, &delta->sids[i].sid);
-
- if (!pdb_getsampwsid(member, &member_sid)) {
- DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
- sid_string_static(&member_sid), grp->gr_name));
- pdb_free_sam(&member);
- continue;
- }
-
- if (pdb_get_group_rid(member) == rid) {
- d_printf("%s(primary),", pdb_get_username(member));
- pdb_free_sam(&member);
- continue;
- }
-
- d_printf("%s,", pdb_get_username(member));
- nt_members[i] = talloc_strdup(t, pdb_get_username(member));
- pdb_free_sam(&member);
- }
-
- d_printf("\n");
-
- unix_members = grp->gr_mem;
-
- while (*unix_members) {
- BOOL is_nt_member = False;
- for (i=0; i<delta->num_members; i++) {
- if (nt_members[i] == NULL) {
- /* This was a primary group */
- continue;
- }
-
- if (strcmp(*unix_members, nt_members[i]) == 0) {
- is_nt_member = True;
- break;
- }
- }
- if (!is_nt_member) {
- /* We look at a unix group member that is not
- an nt group member. So, remove it. NT is
- boss here. */
- smb_delete_user_group(grp->gr_name, *unix_members);
- }
- unix_members += 1;
- }
-
- for (i=0; i<delta->num_members; i++) {
- BOOL is_unix_member = False;
-
- if (nt_members[i] == NULL) {
- /* This was the primary group */
- continue;
- }
-
- unix_members = grp->gr_mem;
-
- while (*unix_members) {
- if (strcmp(*unix_members, nt_members[i]) == 0) {
- is_unix_member = True;
- break;
- }
- unix_members += 1;
- }
-
- if (!is_unix_member) {
- /* We look at a nt group member that is not a
- unix group member currently. So, add the nt
- group member. */
- smb_add_user_group(grp->gr_name, nt_members[i]);
- }
- }
-
- talloc_destroy(t);
-
-#endif /* end of fetch_alias_mem() */
-
return NT_STATUS_OK;
}
@@ -1209,11 +1076,15 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
if (machine_suffix && *machine_suffix &&
strcmp(machine_suffix, user_suffix) &&
strcmp(machine_suffix, suffix)) {
- fprintf(add_fd, "# %s\n", lp_ldap_machine_suffix());
- fprintf(add_fd, "dn: %s\n", lp_ldap_machine_suffix());
+ char *machine_ou = NULL;
+ fprintf(add_fd, "# %s\n", machine_suffix);
+ fprintf(add_fd, "dn: %s\n", machine_suffix);
fprintf(add_fd, "objectClass: organizationalUnit\n");
- fprintf(add_fd, "ou: %s\n",
- sstring_sub(lp_ldap_machine_suffix(), '=', ','));
+ /* this isn't totally correct as it assumes that
+ there _must_ be an ou. just fixing memleak now. jmcd */
+ machine_ou = sstring_sub(lp_ldap_machine_suffix(), '=', ',');
+ fprintf(add_fd, "ou: %s\n", machine_ou);
+ SAFE_FREE(machine_ou);
fprintf(add_fd, "\n");
fflush(add_fd);
}
@@ -1224,11 +1095,13 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
if (idmap_suffix && *idmap_suffix &&
strcmp(idmap_suffix, user_suffix) &&
strcmp(idmap_suffix, suffix)) {
+ char *s;
fprintf(add_fd, "# %s\n", idmap_suffix);
fprintf(add_fd, "dn: %s\n", idmap_suffix);
fprintf(add_fd, "ObjectClass: organizationalUnit\n");
- fprintf(add_fd, "ou: %s\n",
- sstring_sub(lp_ldap_idmap_suffix(), '=', ','));
+ s = sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
+ fprintf(add_fd, "ou: %s\n", s);
+ SAFE_FREE(s);
fprintf(add_fd, "\n");
fflush(add_fd);
}
@@ -1289,7 +1162,7 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
fprintf(add_fd, "gidNumber: 514\n");
fprintf(add_fd, "uid: nobody\n");
fprintf(add_fd, "uidNumber: 999\n");
- fprintf(add_fd, "homeDirectory: /dev/null\n");
+ fprintf(add_fd, "homeDirectory: /nobodyshomedir\n");
fprintf(add_fd, "sambaPwdLastSet: 0\n");
fprintf(add_fd, "sambaLogonTime: 0\n");
fprintf(add_fd, "sambaLogoffTime: 2147483647\n");
@@ -1436,7 +1309,9 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
fflush(add_fd);
/* Deallocate memory, and return */
- if (suffix_attr != NULL) SAFE_FREE(suffix_attr);
+ SAFE_FREE(suffix_attr);
+ SAFE_FREE(user_attr);
+ SAFE_FREE(group_attr);
return NT_STATUS_OK;
}
@@ -1509,6 +1384,7 @@ static NTSTATUS map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap,
group_attr, suffix);
accountmap[7].rid = 551;
pstr_sprintf(accountmap[7].cn, "%s", "Replicators");
+ SAFE_FREE(group_attr);
return NT_STATUS_OK;
}
@@ -1536,6 +1412,7 @@ static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
strcmp(groupname, "Print Operators") == 0 ||
strcmp(groupname, "Backup Operators") == 0 ||
strcmp(groupname, "Replicators") == 0) {
+ SAFE_FREE(group_attr);
return NT_STATUS_OK;
} else {
/* Increment the gid for the new group */
@@ -1565,6 +1442,7 @@ static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
fprintf(add_fd, "\n");
fflush(add_fd);
+ SAFE_FREE(group_attr);
/* Return */
return NT_STATUS_OK;
}
@@ -1573,12 +1451,11 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
ACCOUNTMAP *accountmap, FILE *add_fd,
fstring sid, char *suffix, int alloced)
{
- fstring username, homedir, logonscript, homedrive, homepath;
+ fstring username, logonscript, homedrive, homepath = "", homedir = "";
fstring hex_nt_passwd, hex_lm_passwd;
fstring description, fullname, sambaSID;
uchar lm_passwd[16], nt_passwd[16];
- char *flags;
- const char *blank = "", *shell = "/bin/bash";
+ char *flags, *user_rdn;
const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
static uchar zero_buf[16];
uint32 rid = 0, group_rid = 0, gidNumber = 0;
@@ -1598,12 +1475,14 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
pstr_sprintf(accountmap->cn, "%s", username);
/* Get the home directory */
- unistr2_to_ascii(homedir, &(delta->account_info.uni_home_dir),
- sizeof(homedir)-1);
- if (strcmp(homedir, blank) == 0) {
- pstr_sprintf(homedir, "/home/%s", username);
- } else {
- strncpy(homepath, homedir, sizeof(homepath));
+ if (delta->account_info.acb_info & ACB_NORMAL) {
+ unistr2_to_ascii(homedir, &(delta->account_info.uni_home_dir),
+ sizeof(homedir)-1);
+ if (!*homedir) {
+ pstr_sprintf(homedir, "/home/%s", username);
+ } else {
+ pstr_sprintf(homedir, "/nobodyshomedir");
+ }
}
/* Get the logon script */
@@ -1617,7 +1496,7 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
/* Get the description */
unistr2_to_ascii(description, &(delta->account_info.uni_acct_desc),
sizeof(description)-1);
- if (strcmp(description, blank) == 0) {
+ if (!*description) {
pstr_sprintf(description, "System User");
}
@@ -1672,10 +1551,11 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
NEW_PW_FORMAT_SPACE_PADDED_LEN);
/* Add the user to the temporary add ldif file */
- fprintf(add_fd, "# %s, %s, %s\n", username,
- sstring_sub(lp_ldap_user_suffix(), '=', ','), suffix);
- fprintf(add_fd, "dn: uid=%s,ou=%s,%s\n", username,
- sstring_sub(lp_ldap_user_suffix(), '=', ','), suffix);
+ /* this isn't quite right...we can't assume there's just OU=. jmcd */
+ user_rdn = sstring_sub(lp_ldap_user_suffix(), '=', ',');
+ 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);
+ SAFE_FREE(user_rdn);
fprintf(add_fd, "ObjectClass: top\n");
fprintf(add_fd, "objectClass: inetOrgPerson\n");
fprintf(add_fd, "objectClass: posixAccount\n");
@@ -1687,18 +1567,20 @@ static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *group
fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
fprintf(add_fd, "gidNumber: %d\n", gidNumber);
fprintf(add_fd, "homeDirectory: %s\n", homedir);
- if (strcmp(homepath, blank) != 0)
+ if (*homepath)
fprintf(add_fd, "SambaHomePath: %s\n", homepath);
- if (strcmp(homedrive, blank) != 0)
+ if (*homedrive)
fprintf(add_fd, "SambaHomeDrive: %s\n", homedrive);
- if (strcmp(logonscript, blank) != 0)
+ if (*logonscript)
fprintf(add_fd, "SambaLogonScript: %s\n", logonscript);
- fprintf(add_fd, "loginShell: %s\n", shell);
+ 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);
fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
- if(strcmp(fullname, blank) != 0)
+ if(*fullname)
fprintf(add_fd, "displayName: %s\n", fullname);
if (strcmp(nopasswd, hex_lm_passwd) != 0)
fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
@@ -1755,6 +1637,7 @@ static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
strcmp(aliasname, "Print Operators") == 0 ||
strcmp(aliasname, "Backup Operators") == 0 ||
strcmp(aliasname, "Replicator") == 0) {
+ SAFE_FREE(group_attr);
return NT_STATUS_OK;
} else {
/* Increment the gid for the new group */
@@ -1782,6 +1665,7 @@ static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupma
fprintf(add_fd, "\n");
fflush(add_fd);
+ SAFE_FREE(group_attr);
/* Return */
return NT_STATUS_OK;
}
@@ -1835,19 +1719,19 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
{
char *suffix;
const char *builtin_sid = "S-1-5-32";
- char *ldif_file;
+ char *add_name = NULL, *mod_name = NULL;
+ const char *add_template = "/tmp/add.ldif.XXXXXX";
+ const char *mod_template = "/tmp/mod.ldif.XXXXXX";
fstring sid, domainname;
uint32 sync_context = 0;
- NTSTATUS result;
+ NTSTATUS ret = NT_STATUS_OK, result;
int k;
TALLOC_CTX *mem_ctx;
SAM_DELTA_HDR *hdr_deltas;
SAM_DELTA_CTR *deltas;
uint32 num_deltas;
- const char *add_ldif = "/tmp/add.ldif", *mod_ldif = "/tmp/mod.ldif";
- FILE *add_fd, *mod_fd, *ldif_fd;
- char sys_cmd[1024];
- int num_alloced = 0, g_index = 0, a_index = 0, sys_cmd_result;
+ FILE *add_file = NULL, *mod_file = NULL, *ldif_file = NULL;
+ int num_alloced = 0, g_index = 0, a_index = 0;
/* Set up array for mapping accounts to groups */
/* Array element is the group rid */
@@ -1863,28 +1747,36 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
/* Ensure we have an output file */
if (user_file)
- ldif_file = talloc_strdup(mem_ctx, user_file);
+ ldif_file = fopen(user_file, "a");
else
- ldif_file = talloc_strdup(mem_ctx, "/tmp/tmp.ldif");
-
- if (ldif_file == NULL)
- return NT_STATUS_NO_MEMORY;
+ ldif_file = stdout;
- /* Open the add and mod ldif files */
- add_fd = fopen(add_ldif, "a");
- mod_fd = fopen(mod_ldif, "a");
- if (add_fd == NULL || mod_fd == NULL) {
- DEBUG(1, ("Could not open %s\n", add_ldif));
- return NT_STATUS_UNSUCCESSFUL;
- }
+ if (!ldif_file) {
+ fprintf(stderr, "Could not open %s\n", user_file);
+ DEBUG(1, ("Could not open %s\n", user_file));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
- /* Open the user's ldif file */
- ldif_fd = fopen(ldif_file, "a");
- if (ldif_fd == NULL) {
- DEBUG(1, ("Could not open %s\n", ldif_file));
- return NT_STATUS_UNSUCCESSFUL;
+ add_name = talloc_strdup(mem_ctx, add_template);
+ mod_name = talloc_strdup(mem_ctx, mod_template);
+ if (!add_name || !mod_name) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
}
+ /* Open the add and mod ldif files */
+ if (!(add_file = fdopen(smb_mkstemp(add_name),"w"))) {
+ DEBUG(1, ("Could not open %s\n", add_name));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ if (!(mod_file = fdopen(smb_mkstemp(mod_name),"w"))) {
+ DEBUG(1, ("Could not open %s\n", mod_name));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
/* Get the sid */
sid_to_string(sid, &dom_sid);
@@ -1907,7 +1799,8 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
accountmap = SMB_MALLOC_ARRAY(ACCOUNTMAP, 8);
if (groupmap == NULL || accountmap == NULL) {
DEBUG(1,("GROUPMAP malloc failed\n"));
- return NT_STATUS_NO_MEMORY;
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
}
/* Initialize the arrays */
@@ -1918,7 +1811,7 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
num_alloced = 8;
/* Initial database population */
- populate_ldap_for_ldif(sid, suffix, builtin_sid, add_fd);
+ populate_ldap_for_ldif(sid, suffix, builtin_sid, add_file);
map_populate_groups(groupmap, accountmap, sid, suffix,
builtin_sid);
@@ -1929,16 +1822,18 @@ 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_printf("Fetching DOMAIN database\n");
+ d_fprintf(stderr, "Fetching DOMAIN database\n");
break;
case SAM_DATABASE_BUILTIN:
- d_printf("Fetching BUILTIN database\n");
+ d_fprintf(stderr, "Fetching BUILTIN database\n");
break;
case SAM_DATABASE_PRIVS:
- d_printf("Fetching PRIVS databases\n");
+ d_fprintf(stderr, "Fetching PRIVS databases\n");
break;
default:
- d_printf("Fetching unknown database type %u\n", db_type );
+ d_fprintf(stderr,
+ "Fetching unknown database type %u\n",
+ db_type );
break;
}
@@ -1949,7 +1844,8 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
&deltas);
if (!NT_STATUS_IS_OK(result) &&
!NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
- return NT_STATUS_OK;
+ ret = NT_STATUS_OK;
+ goto done; /* is this correct? jmcd */
}
/* Re-allocate memory for groupmap and accountmap arrays */
@@ -1959,7 +1855,8 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
num_deltas+num_alloced);
if (groupmap == NULL || accountmap == NULL) {
DEBUG(1,("GROUPMAP malloc failed\n"));
- return NT_STATUS_NO_MEMORY;
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
}
/* Initialize the new records */
@@ -1984,14 +1881,14 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
case SAM_DELTA_GROUP_INFO:
fetch_group_info_to_ldif(
&deltas[k], &groupmap[g_index],
- add_fd, sid, suffix);
+ add_file, sid, suffix);
g_index++;
break;
case SAM_DELTA_ACCOUNT_INFO:
fetch_account_info_to_ldif(
&deltas[k], groupmap,
- &accountmap[a_index], add_fd,
+ &accountmap[a_index], add_file,
sid, suffix, num_alloced);
a_index++;
break;
@@ -1999,7 +1896,7 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
case SAM_DELTA_ALIAS_INFO:
fetch_alias_info_to_ldif(
&deltas[k], &groupmap[g_index],
- add_fd, sid, suffix, db_type);
+ add_file, sid, suffix, db_type);
g_index++;
break;
@@ -2007,7 +1904,7 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
fetch_groupmem_info_to_ldif(
&deltas[k], &hdr_deltas[k],
groupmap, accountmap,
- mod_fd, num_alloced);
+ mod_file, num_alloced);
break;
case SAM_DELTA_ALIAS_MEM:
@@ -2049,63 +1946,63 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
- /* Close the ldif files */
- fclose(add_fd);
- fclose(mod_fd);
-
/* Write ldif data to the user's file */
if (db_type == SAM_DATABASE_DOMAIN) {
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# =================================\n\n");
- fflush(ldif_fd);
+ fflush(ldif_file);
} else if (db_type == SAM_DATABASE_BUILTIN) {
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# ==================================\n\n");
- fflush(ldif_fd);
- }
- pstr_sprintf(sys_cmd, "cat %s >> %s", add_ldif, ldif_file);
- sys_cmd_result = system(sys_cmd);
- if (sys_cmd_result) {
- d_fprintf(stderr, "%s failed. Error was (%s)\n",
- sys_cmd, strerror(errno));
- return NT_STATUS_UNSUCCESSFUL;
+ fflush(ldif_file);
}
+ fseek(add_file, 0, SEEK_SET);
+ transfer_file(fileno(add_file), fileno(ldif_file), (size_t) -1);
+
if (db_type == SAM_DATABASE_DOMAIN) {
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# ====================================\n\n");
- fflush(ldif_fd);
+ fflush(ldif_file);
} else if (db_type == SAM_DATABASE_BUILTIN) {
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
- fprintf(ldif_fd,
+ fprintf(ldif_file,
"# =====================================\n\n");
- fflush(ldif_fd);
+ fflush(ldif_file);
}
- pstr_sprintf(sys_cmd, "cat %s >> %s", mod_ldif, ldif_file);
- sys_cmd_result = system(sys_cmd);
- if (sys_cmd_result) {
- d_fprintf(stderr, "%s failed. Error was (%s)\n",
- sys_cmd, strerror(errno));
- return NT_STATUS_UNSUCCESSFUL;
+ fseek(mod_file, 0, SEEK_SET);
+ transfer_file(fileno(mod_file), fileno(ldif_file), (size_t) -1);
+
+
+ done:
+ /* Close and delete the ldif files */
+ if (add_file) {
+ fclose(add_file);
}
- /* Delete the temporary ldif files */
- pstr_sprintf(sys_cmd, "rm -f %s %s", add_ldif, mod_ldif);
- sys_cmd_result = system(sys_cmd);
- if (sys_cmd_result) {
- d_fprintf(stderr, "%s failed. Error was (%s)\n",
- sys_cmd, strerror(errno));
- return NT_STATUS_UNSUCCESSFUL;
+ 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)));
}
- /* Close the ldif file */
- fclose(ldif_fd);
+ if (mod_file) {
+ fclose(mod_file);
+ }
+
+ 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)));
+ }
+
+ if (ldif_file && (ldif_file != stdout)) {
+ fclose(ldif_file);
+ }
/* Deallocate memory for the mapping arrays */
SAFE_FREE(groupmap);
@@ -2113,7 +2010,7 @@ static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
/* Return */
talloc_destroy(mem_ctx);
- return NT_STATUS_OK;
+ return ret;
}
/**
diff --git a/source/utils/net_rpc_sh_acct.c b/source/utils/net_rpc_sh_acct.c
new file mode 100644
index 00000000000..5d0ce736648
--- /dev/null
+++ b/source/utils/net_rpc_sh_acct.c
@@ -0,0 +1,411 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2006 Volker Lendecke (vl@samba.org)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "includes.h"
+#include "utils/net.h"
+
+/*
+ * Do something with the account policies. Read them all, run a function on
+ * them and possibly write them back. "fn" has to return the container index
+ * it has modified, it can return 0 for no change.
+ */
+
+static NTSTATUS rpc_sh_acct_do(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv,
+ BOOL (*fn)(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1,
+ SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv))
+{
+ POLICY_HND connect_pol, domain_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ SAM_UNK_CTR ctr1, ctr3, ctr12;
+ int store;
+
+ ZERO_STRUCT(connect_pol);
+ ZERO_STRUCT(domain_pol);
+
+ /* Get sam policy handle */
+
+ result = rpccli_samr_connect(pipe_hnd, mem_ctx,
+ MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ ctx->domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
+ 1, &ctr1);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "query_domain_info level 1 failed: %s\n",
+ nt_errstr(result));
+ goto done;
+ }
+
+ result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
+ 3, &ctr3);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "query_domain_info level 3 failed: %s\n",
+ nt_errstr(result));
+ goto done;
+ }
+
+ result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
+ 12, &ctr12);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "query_domain_info level 12 failed: %s\n",
+ nt_errstr(result));
+ goto done;
+ }
+
+ store = fn(mem_ctx, ctx, &ctr1.info.inf1, &ctr3.info.inf3,
+ &ctr12.info.inf12, argc, argv);
+
+ if (store <= 0) {
+ /* Don't save anything */
+ goto done;
+ }
+
+ switch (store) {
+ case 1:
+ result = rpccli_samr_set_domain_info(pipe_hnd, mem_ctx,
+ &domain_pol, 1, &ctr1);
+ break;
+ case 3:
+ result = rpccli_samr_set_domain_info(pipe_hnd, mem_ctx,
+ &domain_pol, 3, &ctr3);
+ break;
+ case 12:
+ result = rpccli_samr_set_domain_info(pipe_hnd, mem_ctx,
+ &domain_pol, 12, &ctr12);
+ break;
+ default:
+ d_fprintf(stderr, "Got unexpected info level %d\n", store);
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ done:
+ if (is_valid_policy_hnd(&domain_pol)) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+ }
+ if (is_valid_policy_hnd(&connect_pol)) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
+ }
+
+ return result;
+}
+
+static int account_show(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 0) {
+ d_fprintf(stderr, "usage: %s\n", ctx->whoami);
+ return -1;
+ }
+
+ d_printf("Minimum password length: %d\n", i1->min_length_password);
+ d_printf("Password history length: %d\n", i1->password_history);
+
+ d_printf("Minimum password age: ");
+ if (!nt_time_is_zero(&i1->min_passwordage)) {
+ time_t t = nt_time_to_unix_abs(&i1->min_passwordage);
+ d_printf("%d seconds\n", (int)t);
+ } else {
+ d_printf("not set\n");
+ }
+
+ d_printf("Maximum password age: ");
+ if (nt_time_is_set(&i1->expire)) {
+ time_t t = nt_time_to_unix_abs(&i1->expire);
+ d_printf("%d seconds\n", (int)t);
+ } else {
+ d_printf("not set\n");
+ }
+
+ d_printf("Bad logon attempts: %d\n", i12->bad_attempt_lockout);
+
+ if (i12->bad_attempt_lockout != 0) {
+
+ d_printf("Account lockout duration: ");
+ if (nt_time_is_set(&i12->duration)) {
+ time_t t = nt_time_to_unix_abs(&i12->duration);
+ d_printf("%d seconds\n", (int)t);
+ } else {
+ d_printf("not set\n");
+ }
+
+ d_printf("Bad password count reset after: ");
+ if (nt_time_is_set(&i12->reset_count)) {
+ time_t t = nt_time_to_unix_abs(&i12->reset_count);
+ d_printf("%d seconds\n", (int)t);
+ } else {
+ d_printf("not set\n");
+ }
+ }
+
+ d_printf("Disconnect users when logon hours expire: %s\n",
+ nt_time_is_zero(&i3->logout) ? "yes" : "no");
+
+ d_printf("User must logon to change password: %s\n",
+ (i1->password_properties & 0x2) ? "yes" : "no");
+
+ return 0; /* Don't save */
+}
+
+static NTSTATUS rpc_sh_acct_pol_show(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv) {
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_show);
+}
+
+static int account_set_badpw(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ i12->bad_attempt_lockout = atoi(argv[0]);
+ d_printf("Setting bad password count to %d\n",
+ i12->bad_attempt_lockout);
+
+ return 12;
+}
+
+static NTSTATUS rpc_sh_acct_set_badpw(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_badpw);
+}
+
+static int account_set_lockduration(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ unix_to_nt_time_abs(&i12->duration, atoi(argv[0]));
+ d_printf("Setting lockout duration to %d seconds\n",
+ (int)nt_time_to_unix_abs(&i12->duration));
+
+ return 12;
+}
+
+static NTSTATUS rpc_sh_acct_set_lockduration(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_lockduration);
+}
+
+static int account_set_resetduration(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ unix_to_nt_time_abs(&i12->reset_count, atoi(argv[0]));
+ d_printf("Setting bad password reset duration to %d seconds\n",
+ (int)nt_time_to_unix_abs(&i12->reset_count));
+
+ return 12;
+}
+
+static NTSTATUS rpc_sh_acct_set_resetduration(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_resetduration);
+}
+
+static int account_set_minpwage(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ unix_to_nt_time_abs(&i1->min_passwordage, atoi(argv[0]));
+ d_printf("Setting minimum password age to %d seconds\n",
+ (int)nt_time_to_unix_abs(&i1->min_passwordage));
+
+ return 1;
+}
+
+static NTSTATUS rpc_sh_acct_set_minpwage(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_minpwage);
+}
+
+static int account_set_maxpwage(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ unix_to_nt_time_abs(&i1->expire, atoi(argv[0]));
+ d_printf("Setting maximum password age to %d seconds\n",
+ (int)nt_time_to_unix_abs(&i1->expire));
+
+ return 1;
+}
+
+static NTSTATUS rpc_sh_acct_set_maxpwage(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_maxpwage);
+}
+
+static int account_set_minpwlen(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ i1->min_length_password = atoi(argv[0]);
+ d_printf("Setting minimum password length to %d\n",
+ i1->min_length_password);
+
+ return 1;
+}
+
+static NTSTATUS rpc_sh_acct_set_minpwlen(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_minpwlen);
+}
+
+static int account_set_pwhistlen(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ SAM_UNK_INFO_1 *i1, SAM_UNK_INFO_3 *i3,
+ SAM_UNK_INFO_12 *i12,
+ int argc, const char **argv)
+{
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: %s <count>\n", ctx->whoami);
+ return -1;
+ }
+
+ i1->password_history = atoi(argv[0]);
+ d_printf("Setting password history length to %d\n",
+ i1->password_history);
+
+ return 1;
+}
+
+static NTSTATUS rpc_sh_acct_set_pwhistlen(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_sh_acct_do(mem_ctx, ctx, pipe_hnd, argc, argv,
+ account_set_pwhistlen);
+}
+
+struct rpc_sh_cmd *net_rpc_acct_cmds(TALLOC_CTX *mem_ctx,
+ struct rpc_sh_ctx *ctx)
+{
+ static struct rpc_sh_cmd cmds[9] = {
+ { "show", NULL, PI_SAMR, rpc_sh_acct_pol_show,
+ "Show current account policy settings" },
+ { "badpw", NULL, PI_SAMR, rpc_sh_acct_set_badpw,
+ "Set bad password count before lockout" },
+ { "lockduration", NULL, PI_SAMR, rpc_sh_acct_set_lockduration,
+ "Set account lockout duration" },
+ { "resetduration", NULL, PI_SAMR,
+ rpc_sh_acct_set_resetduration,
+ "Set bad password count reset duration" },
+ { "minpwage", NULL, PI_SAMR, rpc_sh_acct_set_minpwage,
+ "Set minimum password age" },
+ { "maxpwage", NULL, PI_SAMR, rpc_sh_acct_set_maxpwage,
+ "Set maximum password age" },
+ { "minpwlen", NULL, PI_SAMR, rpc_sh_acct_set_minpwlen,
+ "Set minimum password length" },
+ { "pwhistlen", NULL, PI_SAMR, rpc_sh_acct_set_pwhistlen,
+ "Set the password history length" },
+ { NULL, NULL, 0, NULL, NULL }
+ };
+
+ return cmds;
+}
diff --git a/source/utils/net_rpc_shell.c b/source/utils/net_rpc_shell.c
new file mode 100644
index 00000000000..4a4eadeef2b
--- /dev/null
+++ b/source/utils/net_rpc_shell.c
@@ -0,0 +1,274 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Shell around net rpc subcommands
+ * 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 "utils/net.h"
+
+static NTSTATUS rpc_sh_info(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+ struct rpc_pipe_client *pipe_hnd,
+ int argc, const char **argv)
+{
+ return rpc_info_internals(ctx->domain_sid, ctx->domain_name,
+ ctx->cli, pipe_hnd, mem_ctx,
+ argc, argv);
+}
+
+static struct rpc_sh_ctx *this_ctx;
+
+static char **completion_fn(const char *text, int start, int end)
+{
+ char **cmds = NULL;
+ int n_cmds = 0;
+ struct rpc_sh_cmd *c;
+
+ if (start != 0) {
+ return NULL;
+ }
+
+ ADD_TO_ARRAY(NULL, char *, SMB_STRDUP(text), &cmds, &n_cmds);
+
+ for (c = this_ctx->cmds; c->name != NULL; c++) {
+ BOOL match = (strncmp(text, c->name, strlen(text)) == 0);
+
+ if (match) {
+ ADD_TO_ARRAY(NULL, char *, SMB_STRDUP(c->name),
+ &cmds, &n_cmds);
+ }
+ }
+
+ if (n_cmds == 2) {
+ SAFE_FREE(cmds[0]);
+ cmds[0] = cmds[1];
+ n_cmds -= 1;
+ }
+
+ ADD_TO_ARRAY(NULL, char *, NULL, &cmds, &n_cmds);
+ return cmds;
+}
+
+static NTSTATUS net_sh_run(struct rpc_sh_ctx *ctx, struct rpc_sh_cmd *cmd,
+ int argc, const char **argv)
+{
+ TALLOC_CTX *mem_ctx;
+ struct rpc_pipe_client *pipe_hnd;
+ NTSTATUS status;
+
+ mem_ctx = talloc_new(ctx);
+ if (mem_ctx == NULL) {
+ d_fprintf(stderr, "talloc_new failed\n");
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pipe_hnd = cli_rpc_pipe_open_noauth(ctx->cli, cmd->pipe_idx, &status);
+ if (pipe_hnd == NULL) {
+ d_fprintf(stderr, "Could not open pipe: %s\n",
+ nt_errstr(status));
+ return status;
+ }
+
+ status = cmd->fn(mem_ctx, ctx, pipe_hnd, argc, argv);
+
+ cli_rpc_pipe_close(pipe_hnd);
+
+ talloc_destroy(mem_ctx);
+
+ return status;
+}
+
+static BOOL net_sh_process(struct rpc_sh_ctx *ctx,
+ int argc, const char **argv)
+{
+ struct rpc_sh_cmd *c;
+ struct rpc_sh_ctx *new_ctx;
+ NTSTATUS status;
+
+ if (argc == 0) {
+ return True;
+ }
+
+ if (ctx == this_ctx) {
+
+ /* We've been called from the cmd line */
+ if (strequal(argv[0], "..") &&
+ (this_ctx->parent != NULL)) {
+ new_ctx = this_ctx->parent;
+ TALLOC_FREE(this_ctx);
+ this_ctx = new_ctx;
+ return True;
+ }
+ }
+
+ if (strequal(argv[0], "help") || strequal(argv[0], "?")) {
+ for (c = ctx->cmds; c->name != NULL; c++) {
+ if (ctx != this_ctx) {
+ d_printf("%s ", ctx->whoami);
+ }
+ d_printf("%-15s %s\n", c->name, c->help);
+ }
+ return True;
+ }
+
+ for (c = ctx->cmds; c->name != NULL; c++) {
+ if (strequal(c->name, argv[0])) {
+ break;
+ }
+ }
+
+ if (c->name == NULL) {
+ /* None found */
+ d_fprintf(stderr, "%s: unknown cmd\n", argv[0]);
+ return True;
+ }
+
+ new_ctx = TALLOC_P(ctx, struct rpc_sh_ctx);
+ if (new_ctx == NULL) {
+ d_fprintf(stderr, "talloc failed\n");
+ return False;
+ }
+ new_ctx->cli = ctx->cli;
+ new_ctx->whoami = talloc_asprintf(new_ctx, "%s %s",
+ ctx->whoami, c->name);
+ new_ctx->thiscmd = talloc_strdup(new_ctx, c->name);
+
+ if (c->sub != NULL) {
+ new_ctx->cmds = c->sub(new_ctx, ctx);
+ } else {
+ new_ctx->cmds = NULL;
+ }
+
+ new_ctx->parent = ctx;
+ new_ctx->domain_name = ctx->domain_name;
+ new_ctx->domain_sid = ctx->domain_sid;
+
+ argc -= 1;
+ argv += 1;
+
+ if (c->sub != NULL) {
+ if (argc == 0) {
+ this_ctx = new_ctx;
+ return True;
+ }
+ return net_sh_process(new_ctx, argc, argv);
+ }
+
+ status = net_sh_run(new_ctx, c, argc, argv);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "%s failed: %s\n", new_ctx->whoami,
+ nt_errstr(status));
+ }
+
+ return True;
+}
+
+static struct rpc_sh_cmd sh_cmds[6] = {
+
+ { "info", NULL, PI_SAMR, rpc_sh_info,
+ "Print information about the domain connected to" },
+
+ { "rights", net_rpc_rights_cmds, 0, NULL,
+ "List/Grant/Revoke user rights" },
+
+ { "share", net_rpc_share_cmds, 0, NULL,
+ "List/Add/Remove etc shares" },
+
+ { "user", net_rpc_user_cmds, 0, NULL,
+ "List/Add/Remove user info" },
+
+ { "account", net_rpc_acct_cmds, 0, NULL,
+ "Show/Change account policy settings" },
+
+ { NULL, NULL, 0, NULL, NULL }
+};
+
+int net_rpc_shell(int argc, const char **argv)
+{
+ NTSTATUS status;
+ struct rpc_sh_ctx *ctx;
+
+ if (argc != 0) {
+ d_fprintf(stderr, "usage: net rpc shell\n");
+ return -1;
+ }
+
+ ctx = TALLOC_P(NULL, struct rpc_sh_ctx);
+ if (ctx == NULL) {
+ d_fprintf(stderr, "talloc failed\n");
+ return -1;
+ }
+
+ ctx->cli = net_make_ipc_connection(0);
+ if (ctx->cli == NULL) {
+ d_fprintf(stderr, "Could not open connection\n");
+ return -1;
+ }
+
+ ctx->cmds = sh_cmds;
+ ctx->whoami = "net rpc";
+ ctx->parent = NULL;
+
+ status = net_get_remote_domain_sid(ctx->cli, ctx, &ctx->domain_sid,
+ &ctx->domain_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return -1;
+ }
+
+ d_printf("Talking to domain %s (%s)\n", ctx->domain_name,
+ sid_string_static(ctx->domain_sid));
+
+ this_ctx = ctx;
+
+ while(1) {
+ char *prompt;
+ char *line;
+ int ret;
+
+ asprintf(&prompt, "%s> ", this_ctx->whoami);
+
+ line = smb_readline(prompt, NULL, completion_fn);
+ SAFE_FREE(prompt);
+
+ if (line == NULL) {
+ break;
+ }
+
+ ret = poptParseArgvString(line, &argc, &argv);
+ if (ret == POPT_ERROR_NOARG) {
+ continue;
+ }
+ if (ret != 0) {
+ d_fprintf(stderr, "cmdline invalid: %s\n",
+ poptStrerror(ret));
+ return False;
+ }
+
+ if ((line[0] != '\n') &&
+ (!net_sh_process(this_ctx, argc, argv))) {
+ break;
+ }
+ }
+
+ cli_shutdown(ctx->cli);
+
+ TALLOC_FREE(ctx);
+
+ return 0;
+}
diff --git a/source/utils/net_sam.c b/source/utils/net_sam.c
new file mode 100644
index 00000000000..945afb3a210
--- /dev/null
+++ b/source/utils/net_sam.c
@@ -0,0 +1,1249 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Local SAM access routines
+ * 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 "utils/net.h"
+
+/*
+ * Set a user's data
+ */
+
+static int net_sam_userset(int argc, const char **argv, const char *field,
+ BOOL (*fn)(struct samu *, const char *,
+ enum pdb_value_state))
+{
+ struct samu *sam_acct = NULL;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ const char *dom, *name;
+ NTSTATUS status;
+
+ if (argc != 2) {
+ d_fprintf(stderr, "usage: net sam set %s <user> <value>\n",
+ field);
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &dom, &name, &sid, &type)) {
+ d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+ return -1;
+ }
+
+ if (type != SID_NAME_USER) {
+ d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+ sid_type_lookup(type));
+ return -1;
+ }
+
+ if ( !(sam_acct = samu_new( NULL )) ) {
+ d_fprintf(stderr, "Internal error\n");
+ return -1;
+ }
+
+ if (!pdb_getsampwsid(sam_acct, &sid)) {
+ d_fprintf(stderr, "Loading user %s failed\n", argv[0]);
+ return -1;
+ }
+
+ if (!fn(sam_acct, argv[1], PDB_CHANGED)) {
+ d_fprintf(stderr, "Internal error\n");
+ return -1;
+ }
+
+ status = pdb_update_sam_account(sam_acct);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Updating sam account %s failed with %s\n",
+ argv[0], nt_errstr(status));
+ return -1;
+ }
+
+ TALLOC_FREE(sam_acct);
+
+ d_printf("Updated %s for %s\\%s to %s\n", field, dom, name, argv[1]);
+ return 0;
+}
+
+static int net_sam_set_fullname(int argc, const char **argv)
+{
+ return net_sam_userset(argc, argv, "fullname",
+ pdb_set_fullname);
+}
+
+static int net_sam_set_logonscript(int argc, const char **argv)
+{
+ return net_sam_userset(argc, argv, "logonscript",
+ pdb_set_logon_script);
+}
+
+static int net_sam_set_profilepath(int argc, const char **argv)
+{
+ return net_sam_userset(argc, argv, "profilepath",
+ pdb_set_profile_path);
+}
+
+static int net_sam_set_homedrive(int argc, const char **argv)
+{
+ return net_sam_userset(argc, argv, "homedrive",
+ pdb_set_dir_drive);
+}
+
+static int net_sam_set_homedir(int argc, const char **argv)
+{
+ return net_sam_userset(argc, argv, "homedir",
+ pdb_set_homedir);
+}
+
+static int net_sam_set_workstations(int argc, const char **argv)
+{
+ return net_sam_userset(argc, argv, "workstations",
+ pdb_set_workstations);
+}
+
+/*
+ * Set account flags
+ */
+
+static int net_sam_set_userflag(int argc, const char **argv, const char *field,
+ uint16 flag)
+{
+ struct samu *sam_acct = NULL;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ const char *dom, *name;
+ NTSTATUS status;
+ uint16 acct_flags;
+
+ if ((argc != 2) || (!strequal(argv[1], "yes") &&
+ !strequal(argv[1], "no"))) {
+ d_fprintf(stderr, "usage: net sam set %s <user> [yes|no]\n",
+ field);
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &dom, &name, &sid, &type)) {
+ d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+ return -1;
+ }
+
+ if (type != SID_NAME_USER) {
+ d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+ sid_type_lookup(type));
+ return -1;
+ }
+
+ if ( !(sam_acct = samu_new( NULL )) ) {
+ d_fprintf(stderr, "Internal error\n");
+ return -1;
+ }
+
+ if (!pdb_getsampwsid(sam_acct, &sid)) {
+ d_fprintf(stderr, "Loading user %s failed\n", argv[0]);
+ return -1;
+ }
+
+ acct_flags = pdb_get_acct_ctrl(sam_acct);
+
+ if (strequal(argv[1], "yes")) {
+ acct_flags |= flag;
+ } else {
+ acct_flags &= ~flag;
+ }
+
+ pdb_set_acct_ctrl(sam_acct, acct_flags, PDB_CHANGED);
+
+ status = pdb_update_sam_account(sam_acct);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Updating sam account %s failed with %s\n",
+ argv[0], nt_errstr(status));
+ return -1;
+ }
+
+ TALLOC_FREE(sam_acct);
+
+ d_fprintf(stderr, "Updated flag %s for %s\\%s to %s\n", field, dom,
+ name, argv[1]);
+ return 0;
+}
+
+static int net_sam_set_disabled(int argc, const char **argv)
+{
+ return net_sam_set_userflag(argc, argv, "disabled", ACB_DISABLED);
+}
+
+static int net_sam_set_pwnotreq(int argc, const char **argv)
+{
+ return net_sam_set_userflag(argc, argv, "pwnotreq", ACB_PWNOTREQ);
+}
+
+static int net_sam_set_autolock(int argc, const char **argv)
+{
+ return net_sam_set_userflag(argc, argv, "autolock", ACB_AUTOLOCK);
+}
+
+static int net_sam_set_pwnoexp(int argc, const char **argv)
+{
+ return net_sam_set_userflag(argc, argv, "pwnoexp", ACB_PWNOEXP);
+}
+
+/*
+ * Set a user's time field
+ */
+
+static int net_sam_set_time(int argc, const char **argv, const char *field,
+ BOOL (*fn)(struct samu *, time_t,
+ enum pdb_value_state))
+{
+ struct samu *sam_acct = NULL;
+ DOM_SID sid;
+ enum SID_NAME_USE 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);
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &dom, &name, &sid, &type)) {
+ d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+ return -1;
+ }
+
+ if (type != SID_NAME_USER) {
+ d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+ sid_type_lookup(type));
+ 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;
+ }
+
+ if (!pdb_getsampwsid(sam_acct, &sid)) {
+ d_fprintf(stderr, "Loading user %s failed\n", argv[0]);
+ return -1;
+ }
+
+ if (!fn(sam_acct, new_time, PDB_CHANGED)) {
+ d_fprintf(stderr, "Internal error\n");
+ return -1;
+ }
+
+ status = pdb_update_sam_account(sam_acct);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Updating sam account %s failed with %s\n",
+ argv[0], nt_errstr(status));
+ return -1;
+ }
+
+ TALLOC_FREE(sam_acct);
+
+ d_printf("Updated %s for %s\\%s to %s\n", field, 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
+ */
+
+static int net_sam_set_comment(int argc, const char **argv)
+{
+ GROUP_MAP map;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ const char *dom, *name;
+ NTSTATUS status;
+
+ if (argc != 2) {
+ d_fprintf(stderr, "usage: net sam set comment <name> "
+ "<comment>\n");
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &dom, &name, &sid, &type)) {
+ d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+ return -1;
+ }
+
+ if (type == SID_NAME_USER) {
+ return net_sam_userset(argc, argv, "comment",
+ pdb_set_acct_desc);
+ }
+
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP)) {
+ d_fprintf(stderr, "%s is a %s, not a group\n", argv[0],
+ sid_type_lookup(type));
+ return -1;
+ }
+
+ if (!pdb_getgrsid(&map, sid)) {
+ d_fprintf(stderr, "Could not load group %s\n", argv[0]);
+ return -1;
+ }
+
+ fstrcpy(map.comment, argv[1]);
+
+ status = pdb_update_group_mapping_entry(&map);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Updating group mapping entry failed with "
+ "%s\n", nt_errstr(status));
+ return -1;
+ }
+
+ d_printf("Updated comment of group %s\\%s to %s\n", dom, name,
+ argv[1]);
+
+ return 0;
+}
+
+static int net_sam_set(int argc, const char **argv)
+{
+ struct functable2 func[] = {
+ { "homedir", net_sam_set_homedir,
+ "Change a user's home directory" },
+ { "profilepath", net_sam_set_profilepath,
+ "Change a user's profile path" },
+ { "comment", net_sam_set_comment,
+ "Change a users or groups description" },
+ { "fullname", net_sam_set_fullname,
+ "Change a user's full name" },
+ { "logonscript", net_sam_set_logonscript,
+ "Change a user's logon script" },
+ { "homedrive", net_sam_set_homedrive,
+ "Change a user's home drive" },
+ { "workstations", net_sam_set_workstations,
+ "Change a user's allowed workstations" },
+ { "disabled", net_sam_set_disabled,
+ "Disable/Enable a user" },
+ { "pwnotreq", net_sam_set_pwnotreq,
+ "Disable/Enable the password not required flag" },
+ { "autolock", net_sam_set_autolock,
+ "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" },
+ {NULL, NULL}
+ };
+
+ return net_run_function2(argc, argv, "net sam set", func);
+}
+
+/*
+ * Map a unix group to a domain group
+ */
+
+static int net_sam_mapunixgroup(int argc, const char **argv)
+{
+ NTSTATUS status;
+ GROUP_MAP map;
+ struct group *grp;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: net sam mapunixgroup <name>\n");
+ return -1;
+ }
+
+ grp = getgrnam(argv[0]);
+ if (grp == NULL) {
+ d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+ return -1;
+ }
+
+ status = map_unix_group(grp, &map);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Mapping group %s failed with %s\n",
+ argv[0], nt_errstr(status));
+ return -1;
+ }
+
+ d_printf("Mapped unix group %s to SID %s\n", argv[0],
+ sid_string_static(&map.sid));
+
+ return 0;
+}
+
+/*
+ * Create a local group
+ */
+
+static int net_sam_createlocalgroup(int argc, const char **argv)
+{
+ NTSTATUS status;
+ uint32 rid;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: net sam createlocalgroup <name>\n");
+ return -1;
+ }
+
+ if (!winbind_ping()) {
+ d_fprintf(stderr, "winbind seems not to run. createlocalgroup "
+ "only works when winbind runs.\n");
+ return -1;
+ }
+
+ status = pdb_create_alias(argv[0], &rid);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Creating %s failed with %s\n",
+ argv[0], nt_errstr(status));
+ return -1;
+ }
+
+ d_printf("Created local group %s with RID %d\n", argv[0], rid);
+
+ return 0;
+}
+
+/*
+ * Create a local group
+ */
+
+static int net_sam_createbuiltingroup(int argc, const char **argv)
+{
+ NTSTATUS status;
+ uint32 rid;
+ TALLOC_CTX *ctx;
+ enum SID_NAME_USE type;
+ fstring groupname;
+ DOM_SID sid;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: net sam createbuiltingroup <name>\n");
+ return -1;
+ }
+
+ if (!winbind_ping()) {
+ d_fprintf(stderr, "winbind seems not to run. createlocalgroup "
+ "only works when winbind runs.\n");
+ return -1;
+ }
+
+ if ( (ctx = talloc_init("net_sam_createbuiltingroup")) == NULL ) {
+ d_fprintf( stderr, "Memory allocation error\n");
+ return -1;
+ }
+
+ /* validate the name and get the group */
+
+ fstrcpy( groupname, "BUILTIN\\" );
+ fstrcat( groupname, argv[0] );
+
+ if ( !lookup_name(ctx, groupname, LOOKUP_NAME_ALL, NULL, NULL, &sid, &type)) {
+ d_fprintf(stderr, "%s is not a BUILTIN group\n", argv[0]);
+ return -1;
+ }
+
+ if ( !sid_peek_rid( &sid, &rid ) ) {
+ d_fprintf(stderr, "Failed to get RID for %s\n", argv[0]);
+ return -1;
+ }
+
+ status = pdb_create_builtin_alias( rid );
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Creating %s failed with %s\n",
+ argv[0], nt_errstr(status));
+ return -1;
+ }
+
+ d_printf("Created BUILTIN group %s with RID %d\n", argv[0], rid);
+
+ return 0;
+}
+
+/*
+ * Add a group member
+ */
+
+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;
+ NTSTATUS status;
+
+ if (argc != 2) {
+ d_fprintf(stderr, "usage: net sam addmem <group> <member>\n");
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &groupdomain, &groupname, &group, &grouptype)) {
+ d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+ return -1;
+ }
+
+ /* check to see if the member to be added is a name or a SID */
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_ISOLATED,
+ &memberdomain, &membername, &member, &membertype))
+ {
+ /* try it as a SID */
+
+ if ( !string_to_sid( &member, argv[1] ) ) {
+ d_fprintf(stderr, "Could not find member %s\n", argv[1]);
+ return -1;
+ }
+
+ if ( !lookup_sid(tmp_talloc_ctx(), &member, &memberdomain,
+ &membername, &membertype) )
+ {
+ d_fprintf(stderr, "Could not resolve SID %s\n", argv[1]);
+ return -1;
+ }
+ }
+
+ if ((grouptype == SID_NAME_ALIAS) || (grouptype == SID_NAME_WKN_GRP)) {
+ if ((membertype != SID_NAME_USER) &&
+ (membertype != SID_NAME_DOM_GRP)) {
+ d_fprintf(stderr, "%s is a local group, only users "
+ "and domain groups can be added.\n"
+ "%s is a %s\n", argv[0], argv[1],
+ sid_type_lookup(membertype));
+ return -1;
+ }
+ status = pdb_add_aliasmem(&group, &member);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Adding local group member failed "
+ "with %s\n", nt_errstr(status));
+ return -1;
+ }
+ } else {
+ d_fprintf(stderr, "Can only add members to local groups so "
+ "far, %s is a %s\n", argv[0],
+ sid_type_lookup(grouptype));
+ return -1;
+ }
+
+ d_printf("Added %s\\%s to %s\\%s\n", memberdomain, membername,
+ groupdomain, groupname);
+
+ return 0;
+}
+
+/*
+ * Delete a group member
+ */
+
+static int net_sam_delmem(int argc, const char **argv)
+{
+ const char *groupdomain, *groupname;
+ const char *memberdomain = NULL;
+ const char *membername = NULL;
+ DOM_SID group, member;
+ enum SID_NAME_USE grouptype;
+ NTSTATUS status;
+
+ if (argc != 2) {
+ d_fprintf(stderr, "usage: net sam delmem <group> <member>\n");
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &groupdomain, &groupname, &group, &grouptype)) {
+ d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_ISOLATED,
+ &memberdomain, &membername, &member, NULL)) {
+ if (!string_to_sid(&member, argv[1])) {
+ d_fprintf(stderr, "Could not find member %s\n",
+ argv[1]);
+ return -1;
+ }
+ }
+
+ if ((grouptype == SID_NAME_ALIAS) ||
+ (grouptype == SID_NAME_WKN_GRP)) {
+ status = pdb_del_aliasmem(&group, &member);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Deleting local group member failed "
+ "with %s\n", nt_errstr(status));
+ return -1;
+ }
+ } else {
+ d_fprintf(stderr, "Can only delete members from local groups "
+ "so far, %s is a %s\n", argv[0],
+ sid_type_lookup(grouptype));
+ return -1;
+ }
+
+ if (membername != NULL) {
+ d_printf("Deleted %s\\%s from %s\\%s\n",
+ memberdomain, membername, groupdomain, groupname);
+ } else {
+ d_printf("Deleted %s from %s\\%s\n",
+ sid_string_static(&member), groupdomain, groupname);
+ }
+
+ return 0;
+}
+
+/*
+ * List group members
+ */
+
+static int net_sam_listmem(int argc, const char **argv)
+{
+ const char *groupdomain, *groupname;
+ DOM_SID group;
+ enum SID_NAME_USE grouptype;
+ NTSTATUS status;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: net sam listmem <group>\n");
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &groupdomain, &groupname, &group, &grouptype)) {
+ d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+ return -1;
+ }
+
+ if ((grouptype == SID_NAME_ALIAS) ||
+ (grouptype == SID_NAME_WKN_GRP)) {
+ DOM_SID *members = NULL;
+ size_t i, num_members = 0;
+
+ status = pdb_enum_aliasmem(&group, &members, &num_members);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, "Listing group members failed with "
+ "%s\n", nt_errstr(status));
+ return -1;
+ }
+
+ d_printf("%s\\%s has %d members\n", groupdomain, groupname,
+ num_members);
+ for (i=0; i<num_members; i++) {
+ const char *dom, *name;
+ if (lookup_sid(tmp_talloc_ctx(), &members[i],
+ &dom, &name, NULL)) {
+ d_printf(" %s\\%s\n", dom, name);
+ } else {
+ d_printf(" %s\n",
+ sid_string_static(&members[i]));
+ }
+ }
+ } else {
+ d_fprintf(stderr, "Can only list local group members so far.\n"
+ "%s is a %s\n", argv[0], sid_type_lookup(grouptype));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Do the listing
+ */
+static int net_sam_do_list(int argc, const char **argv,
+ struct pdb_search *search, const char *what)
+{
+ BOOL verbose = (argc == 1);
+
+ if ((argc > 1) ||
+ ((argc == 1) && !strequal(argv[0], "verbose"))) {
+ d_fprintf(stderr, "usage: net sam list %s [verbose]\n", what);
+ return -1;
+ }
+
+ if (search == NULL) {
+ d_fprintf(stderr, "Could not start search\n");
+ return -1;
+ }
+
+ while (True) {
+ struct samr_displayentry entry;
+ if (!search->next_entry(search, &entry)) {
+ break;
+ }
+ if (verbose) {
+ d_printf("%s:%d:%s\n",
+ entry.account_name,
+ entry.rid,
+ entry.description);
+ } else {
+ d_printf("%s\n", entry.account_name);
+ }
+ }
+
+ search->search_end(search);
+ return 0;
+}
+
+static int net_sam_list_users(int argc, const char **argv)
+{
+ return net_sam_do_list(argc, argv, pdb_search_users(ACB_NORMAL),
+ "users");
+}
+
+static int net_sam_list_groups(int argc, const char **argv)
+{
+ return net_sam_do_list(argc, argv, pdb_search_groups(), "groups");
+}
+
+static int net_sam_list_localgroups(int argc, const char **argv)
+{
+ return net_sam_do_list(argc, argv,
+ pdb_search_aliases(get_global_sam_sid()),
+ "localgroups");
+}
+
+static int net_sam_list_builtin(int argc, const char **argv)
+{
+ return net_sam_do_list(argc, argv,
+ pdb_search_aliases(&global_sid_Builtin),
+ "builtin");
+}
+
+static int net_sam_list_workstations(int argc, const char **argv)
+{
+ return net_sam_do_list(argc, argv,
+ pdb_search_users(ACB_WSTRUST),
+ "workstations");
+}
+
+/*
+ * List stuff
+ */
+
+static int net_sam_list(int argc, const char **argv)
+{
+ struct functable2 func[] = {
+ { "users", net_sam_list_users,
+ "List SAM users" },
+ { "groups", net_sam_list_groups,
+ "List SAM groups" },
+ { "localgroups", net_sam_list_localgroups,
+ "List SAM local groups" },
+ { "builtin", net_sam_list_builtin,
+ "List builtin groups" },
+ { "workstations", net_sam_list_workstations,
+ "List domain member workstations" },
+ {NULL, NULL}
+ };
+
+ return net_run_function2(argc, argv, "net sam list", func);
+}
+
+/*
+ * Show details of SAM entries
+ */
+
+static int net_sam_show(int argc, const char **argv)
+{
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+ const char *dom, *name;
+
+ if (argc != 1) {
+ d_fprintf(stderr, "usage: net sam show <name>\n");
+ return -1;
+ }
+
+ if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+ &dom, &name, &sid, &type)) {
+ d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+ return -1;
+ }
+
+ d_printf("%s\\%s is a %s with SID %s\n", dom, name,
+ sid_type_lookup(type), sid_string_static(&sid));
+
+ return 0;
+}
+
+#ifdef HAVE_LDAP
+
+/*
+ * Init an LDAP tree with default users and Groups
+ * if ldapsam:editposix is enabled
+ */
+
+static int net_sam_provision(int argc, const char **argv)
+{
+ TALLOC_CTX *tc;
+ char *ldap_bk;
+ char *ldap_uri = NULL;
+ char *p;
+ struct smbldap_state *ls;
+ GROUP_MAP gmap;
+ DOM_SID gsid;
+ gid_t domusers_gid = -1;
+ gid_t domadmins_gid = -1;
+ struct samu *samuser;
+ struct passwd *pwd;
+
+ tc = talloc_new(NULL);
+ if (!tc) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ return -1;
+ }
+
+ ldap_bk = talloc_strdup(tc, lp_passdb_backend());
+ p = strchr(ldap_bk, ':');
+ if (p) {
+ *p = 0;
+ ldap_uri = talloc_strdup(tc, p+1);
+ trim_char(ldap_uri, ' ', ' ');
+ }
+
+ trim_char(ldap_bk, ' ', ' ');
+
+ if (strcmp(ldap_bk, "ldapsam") != 0) {
+ d_fprintf(stderr, "Provisioning works only with ldapsam backend\n");
+ goto failed;
+ }
+
+ if (!lp_parm_bool(-1, "ldapsam", "trusted", False) ||
+ !lp_parm_bool(-1, "ldapsam", "editposix", False)) {
+
+ d_fprintf(stderr, "Provisioning works only if ldapsam:trusted"
+ " and ldapsam:editposix are enabled.\n");
+ goto failed;
+ }
+
+ if (!winbind_ping()) {
+ d_fprintf(stderr, "winbind seems not to run. Provisioning "
+ "LDAP only works when winbind runs.\n");
+ goto failed;
+ }
+
+ if (!NT_STATUS_IS_OK(smbldap_init(tc, ldap_uri, &ls))) {
+ d_fprintf(stderr, "Unable to connect to the LDAP server.\n");
+ goto failed;
+ }
+
+ d_printf("Checking for Domain Users group.\n");
+
+ sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS);
+
+ if (!pdb_getgrsid(&gmap, gsid)) {
+ LDAPMod **mods = NULL;
+ char *dn;
+ char *uname;
+ char *wname;
+ char *gidstr;
+ char *gtype;
+ int rc;
+
+ d_printf("Adding the Domain Users group.\n");
+
+ /* lets allocate a new groupid for this group */
+ if (!winbind_allocate_gid(&domusers_gid)) {
+ d_fprintf(stderr, "Unable to allocate a new gid to create Domain Users group!\n");
+ goto domu_done;
+ }
+
+ uname = talloc_strdup(tc, "domusers");
+ wname = talloc_strdup(tc, "Domain Users");
+ dn = talloc_asprintf(tc, "cn=%s,%s", "domusers", lp_ldap_group_suffix());
+ gidstr = talloc_asprintf(tc, "%d", domusers_gid);
+ gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
+
+ if (!uname || !wname || !dn || !gidstr || !gtype) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
+
+ talloc_autofree_ldapmod(tc, mods);
+
+ rc = smbldap_add(ls, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
+ }
+ } else {
+ d_printf("found!\n");
+ }
+
+domu_done:
+
+ d_printf("Checking for Domain Admins group.\n");
+
+ sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_ADMINS);
+
+ if (!pdb_getgrsid(&gmap, gsid)) {
+ LDAPMod **mods = NULL;
+ char *dn;
+ char *uname;
+ char *wname;
+ char *gidstr;
+ char *gtype;
+ int rc;
+
+ d_printf("Adding the Domain Admins group.\n");
+
+ /* lets allocate a new groupid for this group */
+ if (!winbind_allocate_gid(&domadmins_gid)) {
+ d_fprintf(stderr, "Unable to allocate a new gid to create Domain Admins group!\n");
+ goto doma_done;
+ }
+
+ uname = talloc_strdup(tc, "domadmins");
+ wname = talloc_strdup(tc, "Domain Admins");
+ dn = talloc_asprintf(tc, "cn=%s,%s", "domadmins", lp_ldap_group_suffix());
+ gidstr = talloc_asprintf(tc, "%d", domadmins_gid);
+ gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
+
+ if (!uname || !wname || !dn || !gidstr || !gtype) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
+
+ talloc_autofree_ldapmod(tc, mods);
+
+ rc = smbldap_add(ls, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
+ }
+ } else {
+ d_printf("found!\n");
+ }
+
+doma_done:
+
+ d_printf("Check for Administrator account.\n");
+
+ samuser = samu_new(tc);
+ if (!samuser) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ if (!pdb_getsampwnam(samuser, "Administrator")) {
+ LDAPMod **mods = NULL;
+ DOM_SID sid;
+ char *dn;
+ char *name;
+ char *uidstr;
+ char *gidstr;
+ char *shell;
+ char *dir;
+ uid_t uid;
+ int rc;
+
+ d_printf("Adding the Administrator user.\n");
+
+ if (domadmins_gid == -1) {
+ d_fprintf(stderr, "Can't create Administrtor user, Domain Admins group not available!\n");
+ goto done;
+ }
+ if (!winbind_allocate_uid(&uid)) {
+ d_fprintf(stderr, "Unable to allocate a new uid to create the Administrator user!\n");
+ goto done;
+ }
+ name = talloc_strdup(tc, "Administrator");
+ dn = talloc_asprintf(tc, "uid=Administrator,%s", lp_ldap_user_suffix());
+ uidstr = talloc_asprintf(tc, "%d", uid);
+ gidstr = talloc_asprintf(tc, "%d", domadmins_gid);
+ dir = talloc_sub_specified(tc, lp_template_homedir(),
+ "Administrator",
+ get_global_sam_name(),
+ uid, domadmins_gid);
+ shell = talloc_sub_specified(tc, lp_template_shell(),
+ "Administrator",
+ get_global_sam_name(),
+ uid, domadmins_gid);
+
+ if (!name || !dn || !uidstr || !gidstr || !dir || !shell) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ sid_compose(&sid, get_global_sam_sid(), DOMAIN_USER_RID_ADMIN);
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", dir);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
+ pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
+ NEW_PW_FORMAT_SPACE_PADDED_LEN));
+
+ talloc_autofree_ldapmod(tc, mods);
+
+ rc = smbldap_add(ls, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ d_fprintf(stderr, "Failed to add Administrator user to ldap directory\n");
+ }
+ } else {
+ d_printf("found!\n");
+ }
+
+ d_printf("Checking for Guest user.\n");
+
+ samuser = samu_new(tc);
+ if (!samuser) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ if (!pdb_getsampwnam(samuser, lp_guestaccount())) {
+ LDAPMod **mods = NULL;
+ DOM_SID sid;
+ char *dn;
+ char *uidstr;
+ char *gidstr;
+ int rc;
+
+ d_printf("Adding the Guest user.\n");
+
+ pwd = getpwnam_alloc(tc, lp_guestaccount());
+
+ if (!pwd) {
+ if (domusers_gid == -1) {
+ d_fprintf(stderr, "Can't create Guest user, Domain Users group not available!\n");
+ goto done;
+ }
+ pwd = talloc(tc, struct passwd);
+ pwd->pw_name = talloc_strdup(pwd, lp_guestaccount());
+ if (!winbind_allocate_uid(&(pwd->pw_uid))) {
+ d_fprintf(stderr, "Unable to allocate a new uid to create the Guest user!\n");
+ goto done;
+ }
+ pwd->pw_gid = domusers_gid;
+ pwd->pw_dir = talloc_strdup(tc, "/");
+ pwd->pw_shell = talloc_strdup(tc, "/bin/false");
+ if (!pwd->pw_dir || !pwd->pw_shell) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+ }
+
+ sid_compose(&sid, get_global_sam_sid(), DOMAIN_USER_RID_GUEST);
+
+ dn = talloc_asprintf(tc, "uid=%s,%s", pwd->pw_name, lp_ldap_user_suffix ());
+ uidstr = talloc_asprintf(tc, "%d", pwd->pw_uid);
+ gidstr = talloc_asprintf(tc, "%d", pwd->pw_gid);
+ if (!dn || !uidstr || !gidstr) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "uid", pwd->pw_name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", pwd->pw_name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
+ pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
+ NEW_PW_FORMAT_SPACE_PADDED_LEN));
+
+ talloc_autofree_ldapmod(tc, mods);
+
+ rc = smbldap_add(ls, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ d_fprintf(stderr, "Failed to add Guest user to ldap directory\n");
+ }
+ } else {
+ d_printf("found!\n");
+ }
+
+ d_printf("Checking Guest's group.\n");
+
+ pwd = getpwnam_alloc(NULL, lp_guestaccount());
+ if (!pwd) {
+ d_fprintf(stderr, "Failed to find just created Guest account!\n"
+ " Is nssswitch properly configured?!\n");
+ goto failed;
+ }
+
+ if (pwd->pw_gid == domusers_gid) {
+ d_printf("found!\n");
+ goto done;
+ }
+
+ if (!pdb_getgrgid(&gmap, pwd->pw_gid)) {
+ LDAPMod **mods = NULL;
+ char *dn;
+ char *uname;
+ char *wname;
+ char *gidstr;
+ char *gtype;
+ int rc;
+
+ d_printf("Adding the Domain Guests group.\n");
+
+ uname = talloc_strdup(tc, "domguests");
+ wname = talloc_strdup(tc, "Domain Guests");
+ dn = talloc_asprintf(tc, "cn=%s,%s", "domguests", lp_ldap_group_suffix());
+ gidstr = talloc_asprintf(tc, "%d", pwd->pw_gid);
+ gtype = talloc_asprintf(tc, "%d", SID_NAME_DOM_GRP);
+
+ if (!uname || !wname || !dn || !gidstr || !gtype) {
+ d_fprintf(stderr, "Out of Memory!\n");
+ goto failed;
+ }
+
+ sid_compose(&gsid, get_global_sam_sid(), DOMAIN_GROUP_RID_GUESTS);
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", uname);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", wname);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", sid_string_static(&gsid));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", gtype);
+
+ talloc_autofree_ldapmod(tc, mods);
+
+ rc = smbldap_add(ls, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ d_fprintf(stderr, "Failed to add Domain Guests group to ldap directory\n");
+ }
+ } else {
+ d_printf("found!\n");
+ }
+
+
+done:
+ talloc_free(tc);
+ return 0;
+
+failed:
+ talloc_free(tc);
+ return -1;
+}
+
+#endif
+
+/***********************************************************
+ migrated functionality from smbgroupedit
+ **********************************************************/
+int net_sam(int argc, const char **argv)
+{
+ struct functable2 func[] = {
+ { "createbuiltingroup", net_sam_createbuiltingroup,
+ "Create a new BUILTIN group" },
+ { "createlocalgroup", net_sam_createlocalgroup,
+ "Create a new local group" },
+ { "mapunixgroup", net_sam_mapunixgroup,
+ "Map a unix group to a domain group" },
+ { "addmem", net_sam_addmem,
+ "Add a member to a group" },
+ { "delmem", net_sam_delmem,
+ "Delete a member from a group" },
+ { "listmem", net_sam_listmem,
+ "List group members" },
+ { "list", net_sam_list,
+ "List users, groups and local groups" },
+ { "show", net_sam_show,
+ "Show details of a SAM entry" },
+ { "set", net_sam_set,
+ "Set details of a SAM account" },
+#ifdef HAVE_LDAP
+ { "provision", net_sam_provision,
+ "Provision a clean User Database" },
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ /* we shouldn't have silly checks like this */
+ if (getuid() != 0) {
+ d_fprintf(stderr, "You must be root to edit the SAM "
+ "directly.\n");
+ return -1;
+ }
+
+ return net_run_function2(argc, argv, "net sam", func);
+}
+
diff --git a/source/utils/net_status.c b/source/utils/net_status.c
index d3b1bae276d..d85bd27b16d 100644
--- a/source/utils/net_status.c
+++ b/source/utils/net_status.c
@@ -130,6 +130,10 @@ static int collect_pid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
ids->num_entries += 1;
ids->entries = SMB_REALLOC_ARRAY(ids->entries, struct sessionid, ids->num_entries);
+ if (!ids->entries) {
+ ids->num_entries = 0;
+ return 0;
+ }
ids->entries[ids->num_entries-1] = sessionid;
return 0;
diff --git a/source/utils/net_usershare.c b/source/utils/net_usershare.c
new file mode 100644
index 00000000000..1a5c0777211
--- /dev/null
+++ b/source/utils/net_usershare.c
@@ -0,0 +1,842 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+
+ Copyright (C) Jeremy Allison (jra@samba.org) 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "includes.h"
+#include "utils/net.h"
+
+struct {
+ const char *us_errstr;
+ enum usershare_err us_err;
+} us_errs [] = {
+ {"",USERSHARE_OK},
+ {"Malformed usershare file", USERSHARE_MALFORMED_FILE},
+ {"Bad version number", USERSHARE_BAD_VERSION},
+ {"Malformed path entry", USERSHARE_MALFORMED_PATH},
+ {"Malformed comment entryfile", USERSHARE_MALFORMED_COMMENT_DEF},
+ {"Malformed acl definition", USERSHARE_MALFORMED_ACL_DEF},
+ {"Acl parse error", USERSHARE_ACL_ERR},
+ {"Path not absolute", USERSHARE_PATH_NOT_ABSOLUTE},
+ {"Path is denied", USERSHARE_PATH_IS_DENIED},
+ {"Path not allowed", USERSHARE_PATH_NOT_ALLOWED},
+ {"Path is not a directory", USERSHARE_PATH_NOT_DIRECTORY},
+ {"System error", USERSHARE_POSIX_ERR},
+ {NULL,(enum usershare_err)-1}
+};
+
+static const char *get_us_error_code(enum usershare_err us_err)
+{
+ static pstring out;
+ int idx = 0;
+
+ while (us_errs[idx].us_errstr != NULL) {
+ if (us_errs[idx].us_err == us_err) {
+ return us_errs[idx].us_errstr;
+ }
+ idx++;
+ }
+
+ slprintf(out, sizeof(out), "Usershare error code (0x%x)", (unsigned int)us_err);
+ return out;
+}
+
+/* The help subsystem for the USERSHARE subcommand */
+
+static int net_usershare_add_usage(int argc, const char **argv)
+{
+ char c = *lp_winbind_separator();
+ d_printf(
+ "net usershare add [-l|--long] <sharename> <path> [<comment>] [<acl>]\n"
+ "\tAdds the specified share name for this user.\n"
+ "\t<sharename> is the new share name.\n"
+ "\t<path> is the path on the filesystem to export.\n"
+ "\t<comment> is the optional comment for the new share.\n"
+ "\t<acl> is an optional share acl in the format \"DOMAIN%cname:X,DOMAIN%cname:X,....\"\n"
+ "\t\t\"X\" represents a permission and can be any one of the characters f, r or d\n"
+ "\t\twhere \"f\" means full control, \"r\" means read-only, \"d\" means deny access.\n"
+ "\t\tname may be a domain user or group. For local users use the local server name "
+ "instead of \"DOMAIN\"\n"
+ "\t\tThe default acl is \"Everyone:r\" which allows everyone read-only access.\n"
+ "\tAdd -l or --long to print the info on the newly added share.\n",
+ c, c );
+ return -1;
+}
+
+static int net_usershare_delete_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net usershare delete <sharename>\n"\
+ "\tdeletes the specified share name for this user.\n");
+ return -1;
+}
+
+static int net_usershare_info_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net usershare info [-l|--long] [wildcard sharename]\n"\
+ "\tPrints out the path, comment and acl elements of shares that match the wildcard.\n"
+ "\tBy default only gives info on shares owned by the current user\n"
+ "\tAdd -l or --long to apply this to all shares\n"
+ "\tOmit the sharename or use a wildcard of '*' to see all shares\n");
+ return -1;
+}
+
+static int net_usershare_list_usage(int argc, const char **argv)
+{
+ d_printf(
+ "net usershare list [-l|--long] [wildcard sharename]\n"\
+ "\tLists the names of all shares that match the wildcard.\n"
+ "\tBy default only lists shares owned by the current user\n"
+ "\tAdd -l or --long to apply this to all shares\n"
+ "\tOmit the sharename or use a wildcard of '*' to see all shares\n");
+ return -1;
+}
+
+int net_usershare_usage(int argc, const char **argv)
+{
+ d_printf("net usershare add <sharename> <path> [<comment>] [<acl>] to add or change a user defined share.\n"
+ "net usershare delete <sharename> to delete a user defined share.\n"
+ "net usershare info [-l|--long] [wildcard sharename] to print info about a user defined share.\n"
+ "net usershare list [-l|--long] [wildcard sharename] to list user defined shares.\n"
+ "net usershare help\n"\
+ "\nType \"net usershare help <option>\" to get more information on that option\n\n");
+
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+/***************************************************************************
+***************************************************************************/
+
+static void get_basepath(pstring basepath)
+{
+ pstrcpy(basepath, lp_usershare_path());
+ if (basepath[strlen(basepath)-1] == '/') {
+ basepath[strlen(basepath)-1] = '\0';
+ }
+}
+
+/***************************************************************************
+ Delete a single userlevel share.
+***************************************************************************/
+
+static int net_usershare_delete(int argc, const char **argv)
+{
+ pstring us_path;
+ char *sharename;
+
+ if (argc != 1) {
+ return net_usershare_delete_usage(argc, argv);
+ }
+
+ sharename = strdup_lower(argv[0]);
+
+ if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
+ d_fprintf(stderr, "net usershare delete: share name %s contains "
+ "invalid characters (any of %s)\n",
+ sharename, INVALID_SHARENAME_CHARS);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ pstrcpy(us_path, lp_usershare_path());
+ pstrcat(us_path, "/");
+ pstrcat(us_path, sharename);
+
+ if (unlink(us_path) != 0) {
+ d_fprintf(stderr, "net usershare delete: unable to remove usershare %s. "
+ "Error was %s\n",
+ us_path, strerror(errno));
+ SAFE_FREE(sharename);
+ return -1;
+ }
+ SAFE_FREE(sharename);
+ return 0;
+}
+
+/***************************************************************************
+ Data structures to handle a list of usershare files.
+***************************************************************************/
+
+struct file_list {
+ struct file_list *next, *prev;
+ const char *pathname;
+};
+
+static struct file_list *flist;
+
+/***************************************************************************
+***************************************************************************/
+
+static int get_share_list(TALLOC_CTX *ctx, const char *wcard, BOOL only_ours)
+{
+ SMB_STRUCT_DIR *dp;
+ SMB_STRUCT_DIRENT *de;
+ uid_t myuid = geteuid();
+ struct file_list *fl = NULL;
+ pstring basepath;
+
+ get_basepath(basepath);
+ dp = sys_opendir(basepath);
+ if (!dp) {
+ d_fprintf(stderr, "get_share_list: cannot open usershare directory %s. Error %s\n",
+ basepath, strerror(errno) );
+ return -1;
+ }
+
+ while((de = sys_readdir(dp)) != 0) {
+ SMB_STRUCT_STAT sbuf;
+ pstring path;
+ const char *n = de->d_name;
+
+ /* Ignore . and .. */
+ if (*n == '.') {
+ if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
+ continue;
+ }
+ }
+
+ if (!validate_net_name(n, INVALID_SHARENAME_CHARS, strlen(n))) {
+ d_fprintf(stderr, "get_share_list: ignoring bad share name %s\n",n);
+ continue;
+ }
+ pstrcpy(path, basepath);
+ pstrcat(path, "/");
+ pstrcat(path, n);
+
+ if (sys_lstat(path, &sbuf) != 0) {
+ d_fprintf(stderr, "get_share_list: can't lstat file %s. Error was %s\n",
+ path, strerror(errno) );
+ continue;
+ }
+
+ if (!S_ISREG(sbuf.st_mode)) {
+ d_fprintf(stderr, "get_share_list: file %s is not a regular file. Ignoring.\n",
+ path );
+ continue;
+ }
+
+ if (only_ours && sbuf.st_uid != myuid) {
+ continue;
+ }
+
+ if (!unix_wild_match(wcard, n)) {
+ continue;
+ }
+
+ /* (Finally) - add to list. */
+ fl = TALLOC_P(ctx, struct file_list);
+ if (!fl) {
+ return -1;
+ }
+ fl->pathname = talloc_strdup(ctx, n);
+ if (!fl->pathname) {
+ return -1;
+ }
+
+ DLIST_ADD(flist, fl);
+ }
+
+ sys_closedir(dp);
+ return 0;
+}
+
+enum priv_op { US_LIST_OP, US_INFO_OP};
+
+struct priv_info {
+ TALLOC_CTX *ctx;
+ enum priv_op op;
+};
+
+/***************************************************************************
+ Call a function for every share on the list.
+***************************************************************************/
+
+static int process_share_list(int (*fn)(struct file_list *, void *), void *priv)
+{
+ struct file_list *fl;
+ int ret = 0;
+
+ for (fl = flist; fl; fl = fl->next) {
+ ret = (*fn)(fl, priv);
+ }
+
+ return ret;
+}
+
+/***************************************************************************
+ Info function.
+***************************************************************************/
+
+static int info_fn(struct file_list *fl, void *priv)
+{
+ SMB_STRUCT_STAT sbuf;
+ char **lines = NULL;
+ struct priv_info *pi = (struct priv_info *)priv;
+ TALLOC_CTX *ctx = pi->ctx;
+ int fd = -1;
+ int numlines = 0;
+ SEC_DESC *psd = NULL;
+ pstring basepath;
+ pstring sharepath;
+ pstring comment;
+ pstring acl_str;
+ int num_aces;
+ char sep_str[2];
+ enum usershare_err us_err;
+
+ sep_str[0] = *lp_winbind_separator();
+ sep_str[1] = '\0';
+
+ get_basepath(basepath);
+ pstrcat(basepath, "/");
+ pstrcat(basepath, fl->pathname);
+
+#ifdef O_NOFOLLOW
+ fd = sys_open(basepath, O_RDONLY|O_NOFOLLOW, 0);
+#else
+ fd = sys_open(basepath, O_RDONLY, 0);
+#endif
+
+ if (fd == -1) {
+ d_fprintf(stderr, "info_fn: unable to open %s. %s\n",
+ basepath, strerror(errno) );
+ return -1;
+ }
+
+ /* Paranoia... */
+ if (sys_fstat(fd, &sbuf) != 0) {
+ d_fprintf(stderr, "info_fn: can't fstat file %s. Error was %s\n",
+ basepath, strerror(errno) );
+ close(fd);
+ return -1;
+ }
+
+ if (!S_ISREG(sbuf.st_mode)) {
+ d_fprintf(stderr, "info_fn: file %s is not a regular file. Ignoring.\n",
+ basepath );
+ close(fd);
+ return -1;
+ }
+
+ lines = fd_lines_load(fd, &numlines, 10240);
+ close(fd);
+
+ if (lines == NULL) {
+ return -1;
+ }
+
+ /* Ensure it's well formed. */
+ us_err = parse_usershare_file(ctx, &sbuf, fl->pathname, -1, lines, numlines,
+ sharepath,
+ comment,
+ &psd);
+
+ file_lines_free(lines);
+
+ if (us_err != USERSHARE_OK) {
+ d_fprintf(stderr, "info_fn: file %s is not a well formed usershare file.\n",
+ basepath );
+ d_fprintf(stderr, "info_fn: Error was %s.\n",
+ get_us_error_code(us_err) );
+ return -1;
+ }
+
+ pstrcpy(acl_str, "usershare_acl=");
+
+ for (num_aces = 0; num_aces < psd->dacl->num_aces; num_aces++) {
+ char access_str[2];
+ const char *domain;
+ const char *name;
+ NTSTATUS ntstatus;
+
+ access_str[1] = '\0';
+
+ ntstatus = net_lookup_name_from_sid(ctx, &psd->dacl->ace[num_aces].trustee, &domain, &name);
+
+ if (NT_STATUS_IS_OK(ntstatus)) {
+ if (domain && *domain) {
+ pstrcat(acl_str, domain);
+ pstrcat(acl_str, sep_str);
+ }
+ pstrcat(acl_str,name);
+ } else {
+ fstring sidstr;
+ sid_to_string(sidstr, &psd->dacl->ace[num_aces].trustee);
+ pstrcat(acl_str,sidstr);
+ }
+ pstrcat(acl_str, ":");
+
+ if (psd->dacl->ace[num_aces].type == SEC_ACE_TYPE_ACCESS_DENIED) {
+ pstrcat(acl_str, "D,");
+ } else {
+ if (psd->dacl->ace[num_aces].info.mask & GENERIC_ALL_ACCESS) {
+ pstrcat(acl_str, "F,");
+ } else {
+ pstrcat(acl_str, "R,");
+ }
+ }
+ }
+
+ acl_str[strlen(acl_str)-1] = '\0';
+
+ if (pi->op == US_INFO_OP) {
+ d_printf("[%s]\n", fl->pathname );
+ d_printf("path=%s\n", sharepath );
+ d_printf("comment=%s\n", comment);
+ d_printf("%s\n\n", acl_str);
+ } else if (pi->op == US_LIST_OP) {
+ d_printf("%s\n", fl->pathname);
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ Print out info (internal detail) on userlevel shares.
+***************************************************************************/
+
+static int net_usershare_info(int argc, const char **argv)
+{
+ fstring wcard;
+ BOOL only_ours = True;
+ int ret = -1;
+ struct priv_info pi;
+ TALLOC_CTX *ctx;
+
+ fstrcpy(wcard, "*");
+
+ if (opt_long_list_entries) {
+ only_ours = False;
+ }
+
+ switch (argc) {
+ case 0:
+ break;
+ case 1:
+ fstrcpy(wcard, argv[0]);
+ break;
+ default:
+ return net_usershare_info_usage(argc, argv);
+ }
+
+ strlower_m(wcard);
+
+ ctx = talloc_init("share_info");
+ ret = get_share_list(ctx, wcard, only_ours);
+ if (ret) {
+ return ret;
+ }
+
+ pi.ctx = ctx;
+ pi.op = US_INFO_OP;
+
+ ret = process_share_list(info_fn, &pi);
+ talloc_destroy(ctx);
+ return ret;
+}
+
+/***************************************************************************
+ Add a single userlevel share.
+***************************************************************************/
+
+static int net_usershare_add(int argc, const char **argv)
+{
+ TALLOC_CTX *ctx = NULL;
+ SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_STAT lsbuf;
+ char *sharename;
+ pstring full_path;
+ pstring full_path_tmp;
+ const char *us_path;
+ const char *us_comment;
+ const char *arg_acl;
+ char *us_acl;
+ char *file_img;
+ int num_aces = 0;
+ int i;
+ int tmpfd;
+ const char *pacl;
+ size_t to_write;
+ uid_t myeuid = geteuid();
+
+ us_comment = "";
+ arg_acl = "S-1-1-0:R";
+
+ switch (argc) {
+ case 0:
+ case 1:
+ default:
+ return net_usershare_add_usage(argc, argv);
+ case 2:
+ sharename = strdup_lower(argv[0]);
+ us_path = argv[1];
+ break;
+ case 3:
+ sharename = strdup_lower(argv[0]);
+ us_path = argv[1];
+ us_comment = argv[2];
+ break;
+ case 4:
+ sharename = strdup_lower(argv[0]);
+ us_path = argv[1];
+ us_comment = argv[2];
+ arg_acl = argv[3];
+ break;
+ }
+
+ if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
+ d_fprintf(stderr, "net usershare add: share name %s contains "
+ "invalid characters (any of %s)\n",
+ sharename, INVALID_SHARENAME_CHARS);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Disallow shares the same as users. */
+ if (getpwnam(sharename)) {
+ d_fprintf(stderr, "net usershare add: share name %s is already a valid system user name\n",
+ sharename );
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Construct the full path for the usershare file. */
+ get_basepath(full_path);
+ pstrcat(full_path, "/");
+ pstrcpy(full_path_tmp, full_path);
+ pstrcat(full_path, sharename);
+ pstrcat(full_path_tmp, ":tmpXXXXXX");
+
+ /* The path *must* be absolute. */
+ if (us_path[0] != '/') {
+ d_fprintf(stderr,"net usershare add: path %s is not an absolute path.\n",
+ us_path);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Check the directory to be shared exists. */
+ if (sys_stat(us_path, &sbuf) != 0) {
+ d_fprintf(stderr, "net usershare add: cannot stat path %s to ensure "
+ "this is a directory. Error was %s\n",
+ us_path, strerror(errno) );
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ if (!S_ISDIR(sbuf.st_mode)) {
+ d_fprintf(stderr, "net usershare add: path %s is not a directory.\n",
+ us_path );
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* If we're not root, check if we're restricted to sharing out directories
+ that we own only. */
+
+ if ((myeuid != 0) && lp_usershare_owner_only() && (myeuid != sbuf.st_uid)) {
+ d_fprintf(stderr, "net usershare add: cannot share path %s as "
+ "we are restricted to only sharing directories we own.\n"
+ "\tAsk the administrator to add the line \"usershare owner only = False\" \n"
+ "\tto the [global] section of the smb.conf to allow this.\n",
+ us_path );
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* No validation needed on comment. Now go through and validate the
+ acl string. Convert names to SID's as needed. Then run it through
+ parse_usershare_acl to ensure it's valid. */
+
+ ctx = talloc_init("share_info");
+
+ /* Start off the string we'll append to. */
+ us_acl = talloc_strdup(ctx, "");
+
+ pacl = arg_acl;
+ num_aces = 1;
+
+ /* Add the number of ',' characters to get the number of aces. */
+ num_aces += count_chars(pacl,',');
+
+ for (i = 0; i < num_aces; i++) {
+ DOM_SID sid;
+ const char *pcolon = strchr_m(pacl, ':');
+ const char *name;
+
+ if (pcolon == NULL) {
+ d_fprintf(stderr, "net usershare add: malformed acl %s (missing ':').\n",
+ pacl );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ switch(pcolon[1]) {
+ case 'f':
+ case 'F':
+ case 'd':
+ case 'r':
+ case 'R':
+ break;
+ default:
+ d_fprintf(stderr, "net usershare add: malformed acl %s "
+ "(access control must be 'r', 'f', or 'd')\n",
+ pacl );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ if (pcolon[2] != ',' && pcolon[2] != '\0') {
+ d_fprintf(stderr, "net usershare add: malformed terminating character for acl %s\n",
+ pacl );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Get the name */
+ name = talloc_strndup(ctx, pacl, pcolon - pacl);
+ if (!string_to_sid(&sid, name)) {
+ /* Convert to a SID */
+ NTSTATUS ntstatus = net_lookup_sid_from_name(ctx, name, &sid);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ d_fprintf(stderr, "net usershare add: cannot convert name \"%s\" to a SID. %s.",
+ name, get_friendly_nt_error_msg(ntstatus) );
+ if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_CONNECTION_REFUSED)) {
+ d_fprintf(stderr, " Maybe smbd is not running.\n");
+ } else {
+ d_fprintf(stderr, "\n");
+ }
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+ }
+ us_acl = talloc_asprintf_append(us_acl, "%s:%c,", sid_string_static(&sid), pcolon[1]);
+
+ /* Move to the next ACL entry. */
+ if (pcolon[2] == ',') {
+ pacl = &pcolon[3];
+ }
+ }
+
+ /* Remove the last ',' */
+ us_acl[strlen(us_acl)-1] = '\0';
+
+ /* Create a temporary filename for this share. */
+ tmpfd = smb_mkstemp(full_path_tmp);
+
+ if (tmpfd == -1) {
+ d_fprintf(stderr, "net usershare add: cannot create tmp file %s\n",
+ full_path_tmp );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Ensure we opened the file we thought we did. */
+ if (sys_lstat(full_path_tmp, &lsbuf) != 0) {
+ d_fprintf(stderr, "net usershare add: cannot lstat tmp file %s\n",
+ full_path_tmp );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Check this is the same as the file we opened. */
+ if (sys_fstat(tmpfd, &sbuf) != 0) {
+ d_fprintf(stderr, "net usershare add: cannot fstat tmp file %s\n",
+ full_path_tmp );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ if (!S_ISREG(sbuf.st_mode) || sbuf.st_dev != lsbuf.st_dev || sbuf.st_ino != lsbuf.st_ino) {
+ d_fprintf(stderr, "net usershare add: tmp file %s is not a regular file ?\n",
+ full_path_tmp );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ if (fchmod(tmpfd, 0644) == -1) {
+ d_fprintf(stderr, "net usershare add: failed to fchmod tmp file %s to 0644n",
+ full_path_tmp );
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Create the in-memory image of the file. */
+ file_img = talloc_strdup(ctx, "#VERSION 1\npath=");
+ file_img = talloc_asprintf_append(file_img, "%s\ncomment=%s\nusershare_acl=%s\n",
+ us_path, us_comment, us_acl );
+
+ to_write = strlen(file_img);
+
+ if (write(tmpfd, file_img, to_write) != to_write) {
+ d_fprintf(stderr, "net usershare add: failed to write %u bytes to file %s. Error was %s\n",
+ (unsigned int)to_write, full_path_tmp, strerror(errno));
+ unlink(full_path_tmp);
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ /* Attempt to replace any existing share by this name. */
+ if (rename(full_path_tmp, full_path) != 0) {
+ unlink(full_path_tmp);
+ d_fprintf(stderr, "net usershare add: failed to add share %s. Error was %s\n",
+ sharename, strerror(errno));
+ talloc_destroy(ctx);
+ close(tmpfd);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
+ close(tmpfd);
+ talloc_destroy(ctx);
+
+ if (opt_long_list_entries) {
+ const char *my_argv[2];
+ my_argv[0] = sharename;
+ my_argv[1] = NULL;
+ net_usershare_info(1, argv);
+ }
+
+ SAFE_FREE(sharename);
+ return 0;
+}
+
+#if 0
+/***************************************************************************
+ List function.
+***************************************************************************/
+
+static int list_fn(struct file_list *fl, void *priv)
+{
+ d_printf("%s\n", fl->pathname);
+ return 0;
+}
+#endif
+
+/***************************************************************************
+ List userlevel shares.
+***************************************************************************/
+
+static int net_usershare_list(int argc, const char **argv)
+{
+ fstring wcard;
+ BOOL only_ours = True;
+ int ret = -1;
+ struct priv_info pi;
+ TALLOC_CTX *ctx;
+
+ fstrcpy(wcard, "*");
+
+ if (opt_long_list_entries) {
+ only_ours = False;
+ }
+
+ switch (argc) {
+ case 0:
+ break;
+ case 1:
+ fstrcpy(wcard, argv[0]);
+ break;
+ default:
+ return net_usershare_list_usage(argc, argv);
+ }
+
+ strlower_m(wcard);
+
+ ctx = talloc_init("share_list");
+ ret = get_share_list(ctx, wcard, only_ours);
+ if (ret) {
+ return ret;
+ }
+
+ pi.ctx = ctx;
+ pi.op = US_LIST_OP;
+
+ ret = process_share_list(info_fn, &pi);
+ talloc_destroy(ctx);
+ return ret;
+}
+
+/***************************************************************************
+ Handle "net usershare help *" subcommands.
+***************************************************************************/
+
+int net_usershare_help(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"ADD", net_usershare_add_usage},
+ {"DELETE", net_usershare_delete_usage},
+ {"INFO", net_usershare_info_usage},
+ {"LIST", net_usershare_list_usage},
+ {NULL, NULL}};
+
+ return net_run_function(argc, argv, func, net_usershare_usage);
+}
+
+/***************************************************************************
+ Entry-point for all the USERSHARE functions.
+***************************************************************************/
+
+int net_usershare(int argc, const char **argv)
+{
+ SMB_STRUCT_DIR *dp;
+
+ struct functable func[] = {
+ {"ADD", net_usershare_add},
+ {"DELETE", net_usershare_delete},
+ {"INFO", net_usershare_info},
+ {"LIST", net_usershare_list},
+ {"HELP", net_usershare_help},
+ {NULL, NULL}
+ };
+
+ if (lp_usershare_max_shares() == 0) {
+ d_fprintf(stderr, "net usershare: usershares are currently disabled\n");
+ return -1;
+ }
+
+ dp = sys_opendir(lp_usershare_path());
+ if (!dp) {
+ int err = errno;
+ d_fprintf(stderr, "net usershare: cannot open usershare directory %s. Error %s\n",
+ lp_usershare_path(), strerror(err) );
+ if (err == EACCES) {
+ d_fprintf(stderr, "You do not have permission to create a usershare. Ask your "
+ "administrator to grant you permissions to create a share.\n");
+ } else if (err == ENOENT) {
+ d_fprintf(stderr, "Please ask your system administrator to "
+ "enable user sharing.\n");
+ }
+ return -1;
+ }
+ sys_closedir(dp);
+
+ return net_run_function(argc, argv, func, net_usershare_usage);
+}
diff --git a/source/utils/net_util.c b/source/utils/net_util.c
new file mode 100644
index 00000000000..805104cefa1
--- /dev/null
+++ b/source/utils/net_util.c
@@ -0,0 +1,89 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Helper routines for net
+ * 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 "utils/net.h"
+
+BOOL is_valid_policy_hnd(const POLICY_HND *hnd)
+{
+ POLICY_HND tmp;
+ ZERO_STRUCT(tmp);
+ return (memcmp(&tmp, hnd, sizeof(tmp)) != 0);
+}
+
+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)
+{
+ struct rpc_pipe_client *lsa_pipe;
+ POLICY_HND pol;
+ NTSTATUS result = NT_STATUS_OK;
+ const char **dom_names;
+ DOM_SID *sids;
+ uint32_t *types;
+
+ ZERO_STRUCT(pol);
+
+ lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
+ if (lsa_pipe == NULL) {
+ d_fprintf(stderr, "Could not initialise lsa pipe\n");
+ return result;
+ }
+
+ result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ d_fprintf(stderr, "open_policy failed: %s\n",
+ nt_errstr(result));
+ return result;
+ }
+
+ result = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1,
+ &name, &dom_names, &sids, &types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ /* This can happen easily, don't log an error */
+ goto done;
+ }
+
+ if (ret_domain != NULL) {
+ *ret_domain = dom_names[0];
+ }
+ if (ret_name != NULL) {
+ *ret_name = talloc_strdup(mem_ctx, name);
+ }
+ if (ret_sid != NULL) {
+ sid_copy(ret_sid, &sids[0]);
+ }
+ if (ret_type != NULL) {
+ *ret_type = types[0];
+ }
+
+ done:
+ if (is_valid_policy_hnd(&pol)) {
+ rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
+ }
+ cli_rpc_pipe_close(lsa_pipe);
+
+ return result;
+}
diff --git a/source/utils/netlookup.c b/source/utils/netlookup.c
new file mode 100644
index 00000000000..df0fe0c8437
--- /dev/null
+++ b/source/utils/netlookup.c
@@ -0,0 +1,220 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Name lookup.
+
+ 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"
+#include "utils/net.h"
+
+/********************************************************
+ Connection cachine struct. Goes away when ctx destroyed.
+********************************************************/
+
+struct con_struct {
+ BOOL failed_connect;
+ NTSTATUS err;
+ struct cli_state *cli;
+ struct rpc_pipe_client *lsapipe;
+ POLICY_HND pol;
+};
+
+static struct con_struct *cs;
+
+/********************************************************
+ Close connection on context destruction.
+********************************************************/
+
+static int cs_destructor(void *p)
+{
+ if (cs->cli) {
+ cli_shutdown(cs->cli);
+ }
+ cs = NULL;
+ return 0;
+}
+
+/********************************************************
+ Create the connection to localhost.
+********************************************************/
+
+static struct con_struct *create_cs(TALLOC_CTX *ctx, NTSTATUS *perr)
+{
+ NTSTATUS nt_status;
+ struct in_addr loopback_ip = *interpret_addr2("127.0.0.1");;
+
+ *perr = NT_STATUS_OK;
+
+ if (cs) {
+ if (cs->failed_connect) {
+ *perr = cs->err;
+ return NULL;
+ }
+ return cs;
+ }
+
+ cs = TALLOC_P(ctx, struct con_struct);
+ if (!cs) {
+ *perr = NT_STATUS_NO_MEMORY;
+ return NULL;
+ }
+
+ ZERO_STRUCTP(cs);
+ talloc_set_destructor(cs, cs_destructor);
+
+ /* Connect to localhost with given username/password. */
+ /* JRA. Pretty sure we can just do this anonymously.... */
+#if 0
+ if (!opt_password && !opt_machine_pass) {
+ char *pass = getpass("Password:");
+ if (pass) {
+ opt_password = SMB_STRDUP(pass);
+ }
+ }
+#endif
+
+ nt_status = cli_full_connection(&cs->cli, global_myname(), global_myname(),
+ &loopback_ip, 0,
+ "IPC$", "IPC",
+#if 0
+ opt_user_name,
+ opt_workgroup,
+ opt_password,
+#else
+ "",
+ opt_workgroup,
+ "",
+#endif
+ 0,
+ Undefined,
+ NULL);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(2,("create_cs: Connect failed. Error was %s\n", nt_errstr(nt_status)));
+ cs->failed_connect = True;
+ cs->err = nt_status;
+ *perr = nt_status;
+ return NULL;
+ }
+
+ cs->lsapipe = cli_rpc_pipe_open_noauth(cs->cli,
+ PI_LSARPC,
+ &nt_status);
+
+ if (cs->lsapipe == NULL) {
+ DEBUG(2,("create_cs: open LSA pipe failed. Error was %s\n", nt_errstr(nt_status)));
+ cs->failed_connect = True;
+ cs->err = nt_status;
+ *perr = nt_status;
+ return NULL;
+ }
+
+ nt_status = rpccli_lsa_open_policy(cs->lsapipe, ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &cs->pol);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(2,("create_cs: rpccli_lsa_open_policy failed. Error was %s\n", nt_errstr(nt_status)));
+ cs->failed_connect = True;
+ cs->err = nt_status;
+ *perr = nt_status;
+ return NULL;
+ }
+
+ return cs;
+}
+
+/********************************************************
+ Do a lookup_sids call to localhost.
+ Check if the local machine is authoritative for this sid. We can't
+ check if this is our SID as that's stored in the root-read-only
+ secrets.tdb.
+ The local smbd will also ask winbindd for us, so we don't have to.
+********************************************************/
+
+NTSTATUS net_lookup_name_from_sid(TALLOC_CTX *ctx,
+ DOM_SID *psid,
+ const char **ppdomain,
+ const char **ppname)
+{
+ NTSTATUS nt_status;
+ struct con_struct *csp = NULL;
+ char **domains;
+ char **names;
+ uint32 *types;
+
+ *ppdomain = NULL;
+ *ppname = NULL;
+
+ csp = create_cs(ctx, &nt_status);
+ if (csp == NULL) {
+ return nt_status;
+ }
+
+ nt_status = rpccli_lsa_lookup_sids(csp->lsapipe, ctx,
+ &csp->pol,
+ 1, psid,
+ &domains,
+ &names,
+ &types);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ *ppdomain = domains[0];
+ *ppname = names[0];
+ /* Don't care about type here. */
+
+ /* Converted OK */
+ return NT_STATUS_OK;
+}
+
+/********************************************************
+ Do a lookup_names call to localhost.
+********************************************************/
+
+NTSTATUS net_lookup_sid_from_name(TALLOC_CTX *ctx, const char *full_name, DOM_SID *pret_sid)
+{
+ NTSTATUS nt_status;
+ struct con_struct *csp = NULL;
+ DOM_SID *sids = NULL;
+ uint32 *types = NULL;
+
+ csp = create_cs(ctx, &nt_status);
+ if (csp == NULL) {
+ return nt_status;
+ }
+
+ nt_status = rpccli_lsa_lookup_names(csp->lsapipe, ctx,
+ &csp->pol,
+ 1,
+ &full_name,
+ NULL, &sids,
+ &types);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ *pret_sid = sids[0];
+
+ /* Converted OK */
+ return NT_STATUS_OK;
+}
diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c
index acc8a74dc22..15f2eda3921 100644
--- a/source/utils/nmblookup.c
+++ b/source/utils/nmblookup.c
@@ -247,7 +247,7 @@ int main(int argc,char *argv[])
exit(1);
}
- if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
}
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index 65dbfb71650..2e879cc1132 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -380,7 +380,7 @@ NTSTATUS contact_winbind_auth_crap(const char *username,
}
if (flags & WBFLAG_PAM_UNIX_NAME) {
- *unix_name = SMB_STRDUP((char *)response.extra_data);
+ *unix_name = SMB_STRDUP((char *)response.extra_data.data);
if (!*unix_name) {
free_response(&response);
return NT_STATUS_NO_MEMORY;
@@ -698,6 +698,7 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
} 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);
DEBUG(10, ("NTLMSSP OK!\n"));
if (ntlmssp_state)
ntlmssp_end(&ntlmssp_state);
@@ -1173,7 +1174,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);
+ retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
if (retval) {
@@ -1190,13 +1191,12 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
- if ((retval = kerberos_kinit_password(user, opt_password,
- 0, NULL, NULL))) {
+ if ((retval = kerberos_kinit_password(user, opt_password, 0, NULL))) {
DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
return False;
}
- retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0);
+ retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
if (retval) {
DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
@@ -1481,7 +1481,7 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod
(const unsigned char *)lm_key,
sizeof(lm_key));
x_fprintf(x_stdout, "LANMAN-Session-Key: %s\n", hex_lm_key);
- talloc_free(hex_lm_key);
+ TALLOC_FREE(hex_lm_key);
}
if (ntlm_server_1_user_session_key
@@ -1491,7 +1491,7 @@ static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mod
(const unsigned char *)user_session_key,
sizeof(user_session_key));
x_fprintf(x_stdout, "User-Session-Key: %s\n", hex_user_session_key);
- talloc_free(hex_user_session_key);
+ TALLOC_FREE(hex_user_session_key);
}
}
}
@@ -1682,7 +1682,7 @@ static BOOL check_auth_crap(void)
hex_lm_key = hex_encode(NULL, (const unsigned char *)lm_key,
sizeof(lm_key));
x_fprintf(x_stdout, "LM_KEY: %s\n", hex_lm_key);
- talloc_free(hex_lm_key);
+ TALLOC_FREE(hex_lm_key);
}
if (request_user_session_key
&& (memcmp(zeros, user_session_key,
@@ -1690,7 +1690,7 @@ static BOOL check_auth_crap(void)
hex_user_session_key = hex_encode(NULL, (const unsigned char *)user_session_key,
sizeof(user_session_key));
x_fprintf(x_stdout, "NT_KEY: %s\n", hex_user_session_key);
- talloc_free(hex_user_session_key);
+ TALLOC_FREE(hex_user_session_key);
}
return True;
@@ -1758,7 +1758,7 @@ enum {
/* Samba client initialisation */
- if (!lp_load(dyn_CONFIGFILE, True, False, False)) {
+ if (!lp_load(dyn_CONFIGFILE, True, False, False, True)) {
d_fprintf(stderr, "ntlm_auth: error opening config file %s. Error was %s\n",
dyn_CONFIGFILE, strerror(errno));
exit(1);
diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c
index 874a993124f..7d95d15bf27 100644
--- a/source/utils/pdbedit.c
+++ b/source/utils/pdbedit.c
@@ -28,7 +28,7 @@
#define BIT_SPSTYLE 0x00000010
#define BIT_CAN_CHANGE 0x00000020
#define BIT_MUST_CHANGE 0x00000040
-#define BIT_RESERV_3 0x00000080
+#define BIT_USERSIDS 0x00000080
#define BIT_FULLNAME 0x00000100
#define BIT_HOMEDIR 0x00000200
#define BIT_HDIRDRIVE 0x00000400
@@ -52,44 +52,79 @@
#define BIT_LOGONHOURS 0x10000000
#define MASK_ALWAYS_GOOD 0x0000001F
-#define MASK_USER_GOOD 0x00405F60
+#define MASK_USER_GOOD 0x00405FE0
/*********************************************************
Add all currently available users to another db
********************************************************/
-static int export_database (struct pdb_context *in, struct pdb_context
- *out, const char *username) {
- SAM_ACCOUNT *user = NULL;
+static int export_database (struct pdb_methods *in,
+ struct pdb_methods *out,
+ const char *username)
+{
+ struct samu *user = NULL;
+ NTSTATUS status;
- DEBUG(3, ("called with username=\"%s\"\n", username));
+ DEBUG(3, ("export_database: username=\"%s\"\n", username ? username : "(NULL)"));
- if (NT_STATUS_IS_ERR(in->pdb_setsampwent(in, 0, 0))) {
- fprintf(stderr, "Can't sampwent!\n");
+ status = in->setsampwent(in, 0, 0);
+ if ( NT_STATUS_IS_ERR(status) ) {
+ fprintf(stderr, "Unable to set account database iterator for %s!\n",
+ in->name);
return 1;
}
- if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
- fprintf(stderr, "Can't initialize new SAM_ACCOUNT!\n");
+ if ( ( user = samu_new( NULL ) ) == NULL ) {
+ fprintf(stderr, "export_database: Memory allocation failure!\n");
return 1;
}
- while (NT_STATUS_IS_OK(in->pdb_getsampwent(in, user))) {
- DEBUG(4, ("Processing account %s\n",
- user->private_u.username));
- if (!username ||
- (strcmp(username, user->private_u.username)
- == 0)) {
- out->pdb_add_sam_account(out, user);
- if (!NT_STATUS_IS_OK(pdb_reset_sam(user))) {
- fprintf(stderr,
- "Can't reset SAM_ACCOUNT!\n");
+ while ( NT_STATUS_IS_OK(in->getsampwent(in, user)) )
+ {
+ DEBUG(4, ("Processing account %s\n", user->username));
+
+ /* If we don't have a specific user or if we do and
+ the login name matches */
+
+ if ( !username || (strcmp(username, user->username) == 0)) {
+ struct samu *account;
+
+ if ( (account = samu_new( NULL )) == NULL ) {
+ fprintf(stderr, "export_database: Memory allocation failure!\n");
+ TALLOC_FREE( user );
+ in->endsampwent( in );
return 1;
}
+
+ printf("Importing accout for %s...", user->username);
+ if ( !NT_STATUS_IS_OK(out->getsampwnam( out, account, user->username )) ) {
+ status = out->add_sam_account(out, user);
+ } else {
+ status = out->update_sam_account( out, user );
+ }
+
+ if ( NT_STATUS_IS_OK(status) ) {
+ printf( "ok\n");
+ } else {
+ printf( "failed\n");
+ }
+
+ TALLOC_FREE( account );
+ }
+
+ /* clean up and get ready for another run */
+
+ TALLOC_FREE( user );
+
+ if ( ( user = samu_new( NULL ) ) == NULL ) {
+ fprintf(stderr, "export_database: Memory allocation failure!\n");
+ return 1;
}
}
- in->pdb_endsampwent(in);
+ TALLOC_FREE( user );
+
+ in->endsampwent(in);
return 0;
}
@@ -98,22 +133,25 @@ static int export_database (struct pdb_context *in, struct pdb_context
Add all currently available group mappings to another db
********************************************************/
-static int export_groups (struct pdb_context *in, struct pdb_context *out) {
+static int export_groups (struct pdb_methods *in, struct pdb_methods *out)
+{
GROUP_MAP *maps = NULL;
size_t i, entries = 0;
+ NTSTATUS status;
+
+ status = in->enum_group_mapping(in, get_global_sam_sid(),
+ SID_NAME_DOM_GRP, &maps, &entries, False);
- if (NT_STATUS_IS_ERR(in->pdb_enum_group_mapping(in, SID_NAME_UNKNOWN,
- &maps, &entries,
- False))) {
- fprintf(stderr, "Can't get group mappings!\n");
+ if ( NT_STATUS_IS_ERR(status) ) {
+ fprintf(stderr, "Unable to enumerate group map entries.\n");
return 1;
}
for (i=0; i<entries; i++) {
- out->pdb_add_group_mapping_entry(out, &(maps[i]));
+ out->add_group_mapping_entry(out, &(maps[i]));
}
- SAFE_FREE(maps);
+ SAFE_FREE( maps );
return 0;
}
@@ -151,24 +189,31 @@ static int reinit_account_policies (void)
Add all currently available account policy from tdb to one backend
********************************************************/
-static int export_account_policies (struct pdb_context *in, struct pdb_context *out)
+static int export_account_policies (struct pdb_methods *in, struct pdb_methods *out)
{
int i;
if (!account_policy_migrated(True)) {
- fprintf(stderr, "Can't set account policy marker in tdb\n");
+ fprintf(stderr, "Unable to set account policy marker in tdb\n");
return -1;
}
- for (i=1; decode_account_policy_name(i) != NULL; i++) {
+ for ( i=1; decode_account_policy_name(i) != NULL; i++ ) {
uint32 policy_value;
- if (NT_STATUS_IS_ERR(in->pdb_get_account_policy(in, i, &policy_value))) {
- fprintf(stderr, "Can't get account policy from tdb\n");
+ NTSTATUS status;
+
+ status = in->get_account_policy(in, i, &policy_value);
+
+ if ( NT_STATUS_IS_ERR(status) ) {
+ fprintf(stderr, "Unable to get account policy from %s\n", in->name);
remove_account_policy_migrated();
return -1;
}
- if (NT_STATUS_IS_ERR(out->pdb_set_account_policy(out, i, policy_value))) {
- fprintf(stderr, "Can't set account policy in passdb\n");
+
+ status = out->set_account_policy(out, i, policy_value);
+
+ if ( NT_STATUS_IS_ERR(status) ) {
+ fprintf(stderr, "Unable to migrate account policy to %s\n", out->name);
remove_account_policy_migrated();
return -1;
}
@@ -182,7 +227,7 @@ static int export_account_policies (struct pdb_context *in, struct pdb_context *
Print info from sam structure
**********************************************************/
-static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdstyle)
+static int print_sam_info (struct samu *sam_pwent, BOOL verbosity, BOOL smbpwdstyle)
{
uid_t uid;
time_t tmp;
@@ -266,25 +311,25 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst
Get an Print User Info
**********************************************************/
-static int print_user_info (struct pdb_context *in, const char *username, BOOL verbosity, BOOL smbpwdstyle)
+static int print_user_info (struct pdb_methods *in, const char *username, BOOL verbosity, BOOL smbpwdstyle)
{
- SAM_ACCOUNT *sam_pwent=NULL;
+ struct samu *sam_pwent=NULL;
BOOL ret;
- if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
return -1;
}
- ret = NT_STATUS_IS_OK(in->pdb_getsampwnam (in, sam_pwent, username));
+ ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username));
if (ret==False) {
fprintf (stderr, "Username not found!\n");
- pdb_free_sam(&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return -1;
}
ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle);
- pdb_free_sam(&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return ret;
}
@@ -292,64 +337,75 @@ static int print_user_info (struct pdb_context *in, const char *username, BOOL v
/*********************************************************
List Users
**********************************************************/
-static int print_users_list (struct pdb_context *in, BOOL verbosity, BOOL smbpwdstyle)
+static int print_users_list (struct pdb_methods *in, BOOL verbosity, BOOL smbpwdstyle)
{
- SAM_ACCOUNT *sam_pwent=NULL;
+ struct samu *sam_pwent=NULL;
BOOL check;
- check = NT_STATUS_IS_OK(in->pdb_setsampwent(in, False, 0));
+ check = NT_STATUS_IS_OK(in->setsampwent(in, False, 0));
if (!check) {
return 1;
}
check = True;
- if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1;
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ return 1;
+ }
- while (check && NT_STATUS_IS_OK(in->pdb_getsampwent (in, sam_pwent))) {
+ while (check && NT_STATUS_IS_OK(in->getsampwent (in, sam_pwent))) {
if (verbosity)
printf ("---------------\n");
print_sam_info (sam_pwent, verbosity, smbpwdstyle);
- pdb_free_sam(&sam_pwent);
- check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent));
+ TALLOC_FREE(sam_pwent);
+
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ check = False;
+ }
}
- if (check) pdb_free_sam(&sam_pwent);
+ if (check)
+ TALLOC_FREE(sam_pwent);
- in->pdb_endsampwent(in);
+ in->endsampwent(in);
return 0;
}
/*********************************************************
Fix a list of Users for uninitialised passwords
**********************************************************/
-static int fix_users_list (struct pdb_context *in)
+static int fix_users_list (struct pdb_methods *in)
{
- SAM_ACCOUNT *sam_pwent=NULL;
+ struct samu *sam_pwent=NULL;
BOOL check;
- check = NT_STATUS_IS_OK(in->pdb_setsampwent(in, False, 0));
+ check = NT_STATUS_IS_OK(in->setsampwent(in, False, 0));
if (!check) {
return 1;
}
check = True;
- if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1;
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ return 1;
+ }
- while (check && NT_STATUS_IS_OK(in->pdb_getsampwent (in, sam_pwent))) {
+ while (check && NT_STATUS_IS_OK(in->getsampwent (in, sam_pwent))) {
printf("Updating record for user %s\n", pdb_get_username(sam_pwent));
- if (!pdb_update_sam_account(sam_pwent)) {
+ if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
printf("Update of user %s failed!\n", pdb_get_username(sam_pwent));
}
- pdb_free_sam(&sam_pwent);
- check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent));
+ TALLOC_FREE(sam_pwent);
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ check = False;
+ }
if (!check) {
- fprintf(stderr, "Failed to initialise new SAM_ACCOUNT structure (out of memory?)\n");
+ fprintf(stderr, "Failed to initialise new struct samu structure (out of memory?)\n");
}
}
- if (check) pdb_free_sam(&sam_pwent);
+ if (check)
+ TALLOC_FREE(sam_pwent);
- in->pdb_endsampwent(in);
+ in->endsampwent(in);
return 0;
}
@@ -357,26 +413,27 @@ static int fix_users_list (struct pdb_context *in)
Set User Info
**********************************************************/
-static int set_user_info (struct pdb_context *in, const char *username,
+static int set_user_info (struct pdb_methods *in, const char *username,
const char *fullname, const char *homedir,
const char *acct_desc,
const char *drive, const char *script,
const char *profile, const char *account_control,
- const char *user_sid, const char *group_sid,
- const char *user_domain,
+ const char *user_sid, const char *user_domain,
const BOOL badpw, const BOOL hours,
time_t pwd_can_change, time_t pwd_must_change)
{
BOOL updated_autolock = False, updated_badpw = False;
- SAM_ACCOUNT *sam_pwent=NULL;
+ struct samu *sam_pwent=NULL;
BOOL ret;
- pdb_init_sam(&sam_pwent);
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ return 1;
+ }
- ret = NT_STATUS_IS_OK(in->pdb_getsampwnam (in, sam_pwent, username));
+ ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username));
if (ret==False) {
fprintf (stderr, "Username not found!\n");
- pdb_free_sam(&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return -1;
}
@@ -422,14 +479,14 @@ static int set_user_info (struct pdb_context *in, const char *username,
pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED);
if (account_control) {
- uint16 not_settable = ~(ACB_DISABLED|ACB_HOMDIRREQ|ACB_PWNOTREQ|
+ uint32 not_settable = ~(ACB_DISABLED|ACB_HOMDIRREQ|ACB_PWNOTREQ|
ACB_PWNOEXP|ACB_AUTOLOCK);
- uint16 newflag = pdb_decode_acct_ctrl(account_control);
+ uint32 newflag = pdb_decode_acct_ctrl(account_control);
if (newflag & not_settable) {
fprintf(stderr, "Can only set [NDHLX] flags\n");
- pdb_free_sam(&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return -1;
}
@@ -452,55 +509,51 @@ static int set_user_info (struct pdb_context *in, const char *username,
}
pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED);
}
- if (group_sid) {
- DOM_SID g_sid;
- if (!string_to_sid(&g_sid, group_sid)) {
- /* not a complete sid, may be a RID, try building a SID */
- int g_rid;
-
- if (sscanf(group_sid, "%d", &g_rid) != 1) {
- fprintf(stderr, "Error passed string is not a complete group SID or RID!\n");
- return -1;
- }
- sid_copy(&g_sid, get_global_sam_sid());
- sid_append_rid(&g_sid, g_rid);
- }
- pdb_set_group_sid (sam_pwent, &g_sid, PDB_CHANGED);
- }
if (badpw) {
pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED);
pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED);
}
- if (NT_STATUS_IS_OK(in->pdb_update_sam_account (in, sam_pwent)))
+ if (NT_STATUS_IS_OK(in->update_sam_account (in, sam_pwent)))
print_user_info (in, username, True, False);
else {
fprintf (stderr, "Unable to modify entry!\n");
- pdb_free_sam(&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return -1;
}
- pdb_free_sam(&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return 0;
}
/*********************************************************
Add New User
**********************************************************/
-static int new_user (struct pdb_context *in, const char *username,
+static int new_user (struct pdb_methods *in, const char *username,
const char *fullname, const char *homedir,
const char *drive, const char *script,
- const char *profile, char *user_sid, char *group_sid,
- BOOL stdin_get)
+ const char *profile, char *user_sid, BOOL stdin_get)
{
- SAM_ACCOUNT *sam_pwent=NULL;
-
+ struct samu *sam_pwent;
char *password1, *password2;
int rc_pwd_cmp;
+ struct passwd *pwd;
get_global_sam_sid();
- if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pwent, username, 0))) {
+ if ( !(pwd = getpwnam_alloc( NULL, username )) ) {
+ DEBUG(0,("Cannot locate Unix account for %s\n", username));
+ return -1;
+ }
+
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ DEBUG(0, ("Memory allocation failure!\n"));
+ return -1;
+ }
+
+ if (!NT_STATUS_IS_OK(samu_alloc_rid_unix(sam_pwent, pwd ))) {
+ TALLOC_FREE( sam_pwent );
+ TALLOC_FREE( pwd );
DEBUG(0, ("could not create account to add new user %s\n", username));
return -1;
}
@@ -509,7 +562,7 @@ static int new_user (struct pdb_context *in, const char *username,
password2 = get_pass( "retype new password:", stdin_get);
if ((rc_pwd_cmp = strcmp (password1, password2))) {
fprintf (stderr, "Passwords do not match!\n");
- pdb_free_sam (&sam_pwent);
+ TALLOC_FREE(sam_pwent);
} else {
pdb_set_plaintext_passwd(sam_pwent, password1);
}
@@ -548,32 +601,17 @@ static int new_user (struct pdb_context *in, const char *username,
}
pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED);
}
- if (group_sid) {
- DOM_SID g_sid;
- if (!string_to_sid(&g_sid, group_sid)) {
- /* not a complete sid, may be a RID, try building a SID */
- int g_rid;
-
- if (sscanf(group_sid, "%d", &g_rid) != 1) {
- fprintf(stderr, "Error passed string is not a complete group SID or RID!\n");
- return -1;
- }
- sid_copy(&g_sid, get_global_sam_sid());
- sid_append_rid(&g_sid, g_rid);
- }
- pdb_set_group_sid (sam_pwent, &g_sid, PDB_CHANGED);
- }
pdb_set_acct_ctrl (sam_pwent, ACB_NORMAL, PDB_CHANGED);
- if (NT_STATUS_IS_OK(in->pdb_add_sam_account (in, sam_pwent))) {
+ if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) {
print_user_info (in, username, True, False);
} else {
fprintf (stderr, "Unable to add user! (does it already exist?)\n");
- pdb_free_sam (&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return -1;
}
- pdb_free_sam (&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return 0;
}
@@ -581,9 +619,9 @@ static int new_user (struct pdb_context *in, const char *username,
Add New Machine
**********************************************************/
-static int new_machine (struct pdb_context *in, const char *machine_in)
+static int new_machine (struct pdb_methods *in, const char *machine_in)
{
- SAM_ACCOUNT *sam_pwent=NULL;
+ struct samu *sam_pwent=NULL;
fstring machinename;
fstring machineaccount;
struct passwd *pwd = NULL;
@@ -601,36 +639,40 @@ static int new_machine (struct pdb_context *in, const char *machine_in)
fstrcpy(machineaccount, machinename);
fstrcat(machineaccount, "$");
- if ((pwd = getpwnam_alloc(machineaccount))) {
- if (!NT_STATUS_IS_OK(pdb_init_sam_pw( &sam_pwent, pwd))) {
+ if ((pwd = getpwnam_alloc(NULL, machineaccount))) {
+
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+ fprintf(stderr, "Memory allocation error!\n");
+ TALLOC_FREE(pwd);
+ return -1;
+ }
+
+ if ( !NT_STATUS_IS_OK(samu_set_unix(sam_pwent, pwd )) ) {
fprintf(stderr, "Could not init sam from pw\n");
- passwd_free(&pwd);
+ TALLOC_FREE(pwd);
return -1;
}
- passwd_free(&pwd);
+
+ TALLOC_FREE(pwd);
} else {
- if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
+ if ( (sam_pwent = samu_new( NULL )) == NULL ) {
fprintf(stderr, "Could not init sam from pw\n");
return -1;
}
}
pdb_set_plaintext_passwd (sam_pwent, machinename);
-
- pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED);
-
+ pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED);
pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST, PDB_CHANGED);
- pdb_set_group_sid_from_rid(sam_pwent, DOMAIN_GROUP_RID_COMPUTERS, PDB_CHANGED);
-
- if (NT_STATUS_IS_OK(in->pdb_add_sam_account (in, sam_pwent))) {
+ if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) {
print_user_info (in, machineaccount, True, False);
} else {
fprintf (stderr, "Unable to add machine! (does it already exist?)\n");
- pdb_free_sam (&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return -1;
}
- pdb_free_sam (&sam_pwent);
+ TALLOC_FREE(sam_pwent);
return 0;
}
@@ -638,20 +680,20 @@ static int new_machine (struct pdb_context *in, const char *machine_in)
Delete user entry
**********************************************************/
-static int delete_user_entry (struct pdb_context *in, const char *username)
+static int delete_user_entry (struct pdb_methods *in, const char *username)
{
- SAM_ACCOUNT *samaccount = NULL;
+ struct samu *samaccount = NULL;
- if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
+ if ( (samaccount = samu_new( NULL )) == NULL ) {
return -1;
}
- if (!NT_STATUS_IS_OK(in->pdb_getsampwnam(in, samaccount, username))) {
+ if (!NT_STATUS_IS_OK(in->getsampwnam(in, samaccount, username))) {
fprintf (stderr, "user %s does not exist in the passdb\n", username);
return -1;
}
- if (!NT_STATUS_IS_OK(in->pdb_delete_sam_account (in, samaccount))) {
+ if (!NT_STATUS_IS_OK(in->delete_sam_account (in, samaccount))) {
fprintf (stderr, "Unable to delete user %s\n", username);
return -1;
}
@@ -662,26 +704,26 @@ static int delete_user_entry (struct pdb_context *in, const char *username)
Delete machine entry
**********************************************************/
-static int delete_machine_entry (struct pdb_context *in, const char *machinename)
+static int delete_machine_entry (struct pdb_methods *in, const char *machinename)
{
fstring name;
- SAM_ACCOUNT *samaccount = NULL;
+ struct samu *samaccount = NULL;
fstrcpy(name, machinename);
name[15] = '\0';
if (name[strlen(name)-1] != '$')
fstrcat (name, "$");
- if (!NT_STATUS_IS_OK(pdb_init_sam (&samaccount))) {
+ if ( (samaccount = samu_new( NULL )) == NULL ) {
return -1;
}
- if (!NT_STATUS_IS_OK(in->pdb_getsampwnam(in, samaccount, name))) {
+ if (!NT_STATUS_IS_OK(in->getsampwnam(in, samaccount, name))) {
fprintf (stderr, "machine %s does not exist in the passdb\n", name);
return -1;
}
- if (!NT_STATUS_IS_OK(in->pdb_delete_sam_account (in, samaccount))) {
+ if (!NT_STATUS_IS_OK(in->delete_sam_account (in, samaccount))) {
fprintf (stderr, "Unable to delete machine %s\n", name);
return -1;
}
@@ -722,7 +764,6 @@ int main (int argc, char **argv)
static char *account_control = NULL;
static char *account_policy = NULL;
static char *user_sid = NULL;
- static char *group_sid = NULL;
static long int account_policy_value = 0;
BOOL account_policy_value_set = False;
static BOOL badpw_reset = False;
@@ -731,10 +772,7 @@ int main (int argc, char **argv)
static char *pwd_must_change_time = NULL;
static char *pwd_time_format = NULL;
static BOOL pw_from_stdin = False;
-
- struct pdb_context *bin;
- struct pdb_context *bout;
- struct pdb_context *bdef;
+ struct pdb_methods *bin, *bout, *bdef;
poptContext pc;
struct poptOption long_options[] = {
POPT_AUTOHELP
@@ -750,7 +788,6 @@ int main (int argc, char **argv)
{"profile", 'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL},
{"domain", 'I', POPT_ARG_STRING, &user_domain, 0, "set a users' domain", NULL},
{"user SID", 'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL},
- {"group SID", 'G', POPT_ARG_STRING, &group_sid, 0, "set group SID or RID", NULL},
{"create", 'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL},
{"modify", 'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL},
{"machine", 'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL},
@@ -775,6 +812,8 @@ int main (int argc, char **argv)
POPT_TABLEEND
};
+ bin = bout = bdef = NULL;
+
load_case_tables();
setup_logging("pdbedit", True);
@@ -795,7 +834,7 @@ int main (int argc, char **argv)
if (user_name == NULL)
user_name = poptGetArg(pc);
- if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+ if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
exit(1);
}
@@ -819,6 +858,7 @@ int main (int argc, char **argv)
(user_name ? BIT_USER : 0) +
(list_users ? BIT_LIST : 0) +
(force_initialised_password ? BIT_FIX_INIT : 0) +
+ (user_sid ? BIT_USERSIDS : 0) +
(modify_user ? BIT_MODIFY : 0) +
(add_user ? BIT_CREATE : 0) +
(delete_user ? BIT_DELETE : 0) +
@@ -833,12 +873,12 @@ int main (int argc, char **argv)
(pwd_must_change_time ? BIT_MUST_CHANGE: 0);
if (setparms & BIT_BACKEND) {
- if (!NT_STATUS_IS_OK(make_pdb_context_string(&bdef, backend))) {
+ if (!NT_STATUS_IS_OK(make_pdb_method_name( &bdef, backend ))) {
fprintf(stderr, "Can't initialize passdb backend.\n");
return 1;
}
} else {
- if (!NT_STATUS_IS_OK(make_pdb_context_list(&bdef, lp_passdb_backend()))) {
+ if (!NT_STATUS_IS_OK(make_pdb_method_name(&bdef, lp_passdb_backend()))) {
fprintf(stderr, "Can't initialize passdb backend.\n");
return 1;
}
@@ -893,37 +933,46 @@ int main (int argc, char **argv)
}
/* import and export operations */
- if (((checkparms & BIT_IMPORT) || (checkparms & BIT_EXPORT))
- && !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER))) {
+
+ if ( ((checkparms & BIT_IMPORT)
+ || (checkparms & BIT_EXPORT))
+ && !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER)) )
+ {
+ NTSTATUS status;
+
+ bin = bout = bdef;
+
if (backend_in) {
- if (!NT_STATUS_IS_OK(make_pdb_context_string(&bin, backend_in))) {
- fprintf(stderr, "Can't initialize passdb backend.\n");
+ status = make_pdb_method_name(&bin, backend_in);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ fprintf(stderr, "Unable to initialize %s.\n", backend_in);
return 1;
}
- } else {
- bin = bdef;
}
+
if (backend_out) {
- if (!NT_STATUS_IS_OK(make_pdb_context_string(&bout, backend_out))) {
- fprintf(stderr, "Can't initialize %s.\n", backend_out);
+ status = make_pdb_method_name(&bout, backend_out);
+
+ if ( !NT_STATUS_IS_OK(status) ) {
+ fprintf(stderr, "Unable to initialize %s.\n", backend_out);
return 1;
}
- } else {
- bout = bdef;
}
+
if (transfer_account_policies) {
+
if (!(checkparms & BIT_USER))
return export_account_policies(bin, bout);
+
} else if (transfer_groups) {
+
if (!(checkparms & BIT_USER))
return export_groups(bin, bout);
+
} else {
- if (checkparms & BIT_USER)
- return export_database(bin, bout,
- user_name);
- else
- return export_database(bin, bout,
- NULL);
+ return export_database(bin, bout,
+ (checkparms & BIT_USER) ? user_name : NULL );
}
}
@@ -978,9 +1027,7 @@ int main (int argc, char **argv)
return new_machine (bdef, user_name);
} else {
return new_user (bdef, user_name, full_name, home_dir,
- home_drive, logon_script,
- profile_path, user_sid, group_sid,
- pw_from_stdin);
+ home_drive, logon_script, profile_path, user_sid, pw_from_stdin);
}
}
@@ -1049,16 +1096,10 @@ int main (int argc, char **argv)
}
}
}
- return set_user_info (bdef, user_name, full_name,
- home_dir,
- acct_desc,
- home_drive,
- logon_script,
- profile_path, account_control,
- user_sid, group_sid,
- user_domain,
- badpw_reset, hours_reset,
- pwd_can_change, pwd_must_change);
+ 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;
diff --git a/source/utils/smbcacls.c b/source/utils/smbcacls.c
index cbbd7adaab3..1c34cd32a66 100644
--- a/source/utils/smbcacls.c
+++ b/source/utils/smbcacls.c
@@ -145,7 +145,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str)
if (!cacls_open_policy_hnd() ||
!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx,
- &pol, 1, &str, &sids,
+ &pol, 1, &str, NULL, &sids,
&types))) {
result = False;
goto done;
@@ -378,7 +378,7 @@ static SEC_DESC *sec_desc_parse(char *str)
{
const char *p = str;
fstring tok;
- SEC_DESC *ret;
+ SEC_DESC *ret = NULL;
size_t sd_size;
DOM_SID *grp_sid=NULL, *owner_sid=NULL;
SEC_ACL *dacl=NULL;
@@ -392,21 +392,29 @@ static SEC_DESC *sec_desc_parse(char *str)
}
if (strncmp(tok,"OWNER:", 6) == 0) {
+ if (owner_sid) {
+ printf("Only specify owner once\n");
+ goto done;
+ }
owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
if (!owner_sid ||
!StringToSid(owner_sid, tok+6)) {
printf("Failed to parse owner sid\n");
- return NULL;
+ goto done;
}
continue;
}
if (strncmp(tok,"GROUP:", 6) == 0) {
+ if (grp_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)) {
printf("Failed to parse group sid\n");
- return NULL;
+ goto done;
}
continue;
}
@@ -414,22 +422,23 @@ static SEC_DESC *sec_desc_parse(char *str)
if (strncmp(tok,"ACL:", 4) == 0) {
SEC_ACE ace;
if (!parse_ace(&ace, tok+4)) {
- return NULL;
+ goto done;
}
if(!add_ace(&dacl, &ace)) {
printf("Failed to add ACL %s\n", tok);
- return NULL;
+ goto done;
}
continue;
}
printf("Failed to parse token '%s' in security descriptor,\n", tok);
- return NULL;
+ goto done;
}
ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid,
NULL, dacl, &sd_size);
+ done:
SAFE_FREE(grp_sid);
SAFE_FREE(owner_sid);
@@ -830,7 +839,7 @@ static struct cli_state *connect_one(const char *share)
setlinebuf(stdout);
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c
index b8f7c2f2b55..e1bf25ad05d 100644
--- a/source/utils/smbcontrol.c
+++ b/source/utils/smbcontrol.c
@@ -131,6 +131,47 @@ static BOOL do_debug(const struct process_id pid,
pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
}
+/* Inject a fault (fata signal) into a running smbd */
+
+static BOOL do_inject_fault(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: smbcontrol <dest> inject "
+ "<bus|hup|term|internal|segv>\n");
+ return False;
+ }
+
+#ifndef DEVELOPER
+ fprintf(stderr, "Fault injection is only available in "
+ "developer builds\n");
+ return False;
+#else /* DEVELOPER */
+ {
+ int sig = 0;
+
+ if (strcmp(argv[1], "bus") == 0) {
+ sig = SIGBUS;
+ } else if (strcmp(argv[1], "hup") == 0) {
+ sig = SIGHUP;
+ } else if (strcmp(argv[1], "term") == 0) {
+ sig = SIGTERM;
+ } else if (strcmp(argv[1], "segv") == 0) {
+ sig = SIGSEGV;
+ } else if (strcmp(argv[1], "internal") == 0) {
+ /* Force an internal error, ie. an unclean exit. */
+ sig = -1;
+ } else {
+ fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
+ return False;
+ }
+
+ return send_message(pid, MSG_SMB_INJECT_FAULT,
+ &sig, sizeof(int), False);
+ }
+#endif /* DEVELOPER */
+}
+
/* Force a browser election */
static BOOL do_election(const struct process_id pid,
@@ -151,7 +192,7 @@ static void pong_cb(int msg_type, struct process_id pid, void *buf, size_t len)
{
char *src_string = procid_str(NULL, &pid);
printf("PONG from pid %s\n", src_string);
- talloc_free(src_string);
+ TALLOC_FREE(src_string);
num_replies++;
}
@@ -584,6 +625,107 @@ static BOOL do_drvupgrade(const struct process_id pid,
pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
}
+static BOOL do_winbind_online(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ TDB_CONTEXT *tdb;
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: smbcontrol winbindd online\n");
+ return False;
+ }
+
+ if (!lp_winbind_offline_logon()) {
+ fprintf(stderr, "The parameter \"winbind offline logon\" must "
+ "be set in the [global] section of smb.conf for this "
+ "command to be allowed.\n");
+ return False;
+ }
+
+ /* Remove the entry in the winbindd_cache tdb to tell a later
+ starting winbindd that we're online. */
+
+ tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
+ if (!tdb) {
+ fprintf(stderr, "Cannot open the tdb %s for writing.\n",
+ lock_path("winbindd_cache.tdb"));
+ return False;
+ }
+
+ tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
+ tdb_close(tdb);
+
+ return send_message(pid, MSG_WINBIND_ONLINE, NULL, 0, False);
+}
+
+static BOOL do_winbind_offline(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ TDB_CONTEXT *tdb;
+ BOOL ret = False;
+ int retry = 0;
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
+ return False;
+ }
+
+ if (!lp_winbind_offline_logon()) {
+ fprintf(stderr, "The parameter \"winbind offline logon\" must "
+ "be set in the [global] section of smb.conf for this "
+ "command to be allowed.\n");
+ return False;
+ }
+
+ /* Create an entry in the winbindd_cache tdb to tell a later
+ starting winbindd that we're offline. We may actually create
+ it here... */
+
+ tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+ TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
+
+ if (!tdb) {
+ fprintf(stderr, "Cannot open the tdb %s for writing.\n",
+ lock_path("winbindd_cache.tdb"));
+ return False;
+ }
+
+ /* There's a potential race condition that if a child
+ winbindd detects a domain is online at the same time
+ we're trying to tell it to go offline that it might
+ delete the record we add between us adding it and
+ sending the message. Minimize this by retrying up to
+ 5 times. */
+
+ for (retry = 0; retry < 5; retry++) {
+ int err;
+ TDB_DATA d;
+ ZERO_STRUCT(d);
+ 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 = 0;
+ 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) {
+ DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
+ } else {
+ break;
+ }
+ }
+
+ tdb_close(tdb);
+ return ret;
+}
+
static BOOL do_reload_config(const struct process_id pid,
const int argc, const char **argv)
{
@@ -655,6 +797,8 @@ static const struct {
"Force a browse election" },
{ "ping", do_ping, "Elicit a response" },
{ "profile", do_profile, "" },
+ { "inject", do_inject_fault,
+ "Inject a fatal signal into a running smbd"},
{ "profilelevel", do_profilelevel, "" },
{ "debuglevel", do_debuglevel, "Display current debuglevels" },
{ "printnotify", do_printnotify, "Send a print notify message" },
@@ -668,6 +812,8 @@ static const struct {
{ "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
{ "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
{ "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
+ { "online", do_winbind_online, "Ask winbind to go into online state"},
+ { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
{ "noop", do_noop, "Do nothing" },
{ NULL }
};
@@ -681,7 +827,7 @@ static void usage(poptContext *pc)
poptPrintHelp(*pc, stderr, 0);
fprintf(stderr, "\n");
- fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\" or a "
+ fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
"process ID\n");
fprintf(stderr, "\n");
@@ -715,11 +861,21 @@ static struct process_id parse_dest(const char *dest)
return pid_to_procid(sys_getpid());
}
- /* Check for numeric pid number */
+ /* Fix winbind typo. */
+ if (strequal(dest, "winbind")) {
+ dest = "winbindd";
+ }
- result = interpret_pid(dest);
- if (procid_valid(&result)) {
- return result;
+
+ if (!(strequal(dest, "winbindd") || strequal(dest, "nmbd"))) {
+ /* Check for numeric pid number */
+
+ result = interpret_pid(dest);
+
+ /* Zero isn't valid if not smbd. */
+ if (result.pid && procid_valid(&result)) {
+ return result;
+ }
}
/* Look up other destinations in pidfile directory */
@@ -827,7 +983,7 @@ int main(int argc, const char **argv)
if (argc == 1)
usage(&pc);
- lp_load(dyn_CONFIGFILE,False,False,False);
+ lp_load(dyn_CONFIGFILE,False,False,False,True);
/* Need to invert sense of return code -- samba
* routines mostly return True==1 for success, but
diff --git a/source/utils/smbcquotas.c b/source/utils/smbcquotas.c
index f8e33131555..7b3268e7834 100644
--- a/source/utils/smbcquotas.c
+++ b/source/utils/smbcquotas.c
@@ -116,7 +116,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str)
if (!cli_open_policy_hnd() ||
!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, cli_ipc->mem_ctx,
- &pol, 1, &str, &sids,
+ &pol, 1, &str, NULL, &sids,
&types))) {
result = False;
goto done;
@@ -435,7 +435,7 @@ FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" },
fault_setup(NULL);
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
pc = poptGetContext("smbcquotas", argc, argv, long_options, 0);
diff --git a/source/utils/smbfilter.c b/source/utils/smbfilter.c
index 3665647905d..97d22230c4b 100644
--- a/source/utils/smbfilter.c
+++ b/source/utils/smbfilter.c
@@ -236,7 +236,7 @@ int main(int argc, char *argv[])
netbiosname = argv[2];
}
- if (!lp_load(configfile,True,False,False)) {
+ if (!lp_load(configfile,True,False,False,True)) {
d_printf("Unable to load config file\n");
}
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c
index 38e56bd6a12..d66001e441b 100644
--- a/source/utils/smbpasswd.c
+++ b/source/utils/smbpasswd.c
@@ -187,7 +187,7 @@ static int process_options(int argc, char **argv, int local_flags)
usage();
}
- if (!lp_load(configfile,True,False,False)) {
+ if (!lp_load(configfile,True,False,False,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n",
dyn_CONFIGFILE);
exit(1);
@@ -228,10 +228,11 @@ static char *prompt_for_new_password(BOOL stdin_get)
Change a password either locally or remotely.
*************************************************************/
-static BOOL password_change(const char *remote_mach, char *username,
- char *old_passwd, char *new_pw, int local_flags)
+static NTSTATUS password_change(const char *remote_mach, char *username,
+ char *old_passwd, char *new_pw,
+ int local_flags)
{
- BOOL ret;
+ NTSTATUS ret;
pstring err_str;
pstring msg_str;
@@ -239,7 +240,7 @@ static BOOL password_change(const char *remote_mach, char *username,
if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
/* these things can't be done remotely yet */
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
ret = remote_password_change(remote_mach, username,
old_passwd, new_pw, err_str, sizeof(err_str));
@@ -285,14 +286,20 @@ static int process_root(int local_flags)
char *old_passwd = NULL;
if (local_flags & LOCAL_SET_LDAP_ADMIN_PW) {
- printf("Setting stored password for \"%s\" in secrets.tdb\n",
- lp_ldap_admin_dn());
+ char *ldap_admin_dn = lp_ldap_admin_dn();
+ if ( ! *ldap_admin_dn ) {
+ DEBUG(0,("ERROR: 'ldap admin dn' not defined! Please check your smb.conf\n"));
+ goto done;
+ }
+
+ printf("Setting stored password for \"%s\" in secrets.tdb\n", ldap_admin_dn);
if ( ! *ldap_secret ) {
new_passwd = prompt_for_new_password(stdin_passwd_get);
fstrcpy(ldap_secret, new_passwd);
}
- if (!store_ldap_admin_pw(ldap_secret))
+ if (!store_ldap_admin_pw(ldap_secret)) {
DEBUG(0,("ERROR: Failed to store the ldap admin password!\n"));
+ }
goto done;
}
@@ -322,9 +329,9 @@ static int process_root(int local_flags)
load_interfaces();
}
- if (!user_name[0] && (pwd = getpwuid_alloc(geteuid()))) {
+ if (!user_name[0] && (pwd = getpwuid_alloc(NULL, geteuid()))) {
fstrcpy(user_name, pwd->pw_name);
- passwd_free(&pwd);
+ TALLOC_FREE(pwd);
}
if (!user_name[0]) {
@@ -394,16 +401,16 @@ static int process_root(int local_flags)
*/
if(local_flags & LOCAL_ENABLE_USER) {
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
BOOL ret;
- pdb_init_sam(&sampass);
+ sampass = samu_new( NULL );
ret = pdb_getsampwnam(sampass, user_name);
if((ret) &&
(pdb_get_lanman_passwd(sampass) == NULL)) {
local_flags |= LOCAL_SET_PASSWORD;
}
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
}
}
@@ -417,7 +424,9 @@ static int process_root(int local_flags)
}
}
- if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) {
+ if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name,
+ old_passwd, new_passwd,
+ local_flags))) {
fprintf(stderr,"Failed to modify password entry for user %s\n", user_name);
result = 1;
goto done;
@@ -426,10 +435,10 @@ static int process_root(int local_flags)
if(remote_machine) {
printf("Password changed for user %s on %s.\n", user_name, remote_machine );
} else if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD|LOCAL_SET_PASSWORD))) {
- SAM_ACCOUNT *sampass = NULL;
+ struct samu *sampass = NULL;
BOOL ret;
- pdb_init_sam(&sampass);
+ sampass = samu_new( NULL );
ret = pdb_getsampwnam(sampass, user_name);
printf("Password changed for user %s.", user_name );
@@ -438,7 +447,7 @@ static int process_root(int local_flags)
if((ret != False) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ) )
printf(" User has no password flag set.");
printf("\n");
- pdb_free_sam(&sampass);
+ TALLOC_FREE(sampass);
}
done:
@@ -464,10 +473,10 @@ static int process_nonroot(int local_flags)
}
if (!user_name[0]) {
- pwd = getpwuid_alloc(getuid());
+ pwd = getpwuid_alloc(NULL, getuid());
if (pwd) {
fstrcpy(user_name,pwd->pw_name);
- passwd_free(&pwd);
+ TALLOC_FREE(pwd);
} else {
fprintf(stderr, "smbpasswd: cannot lookup user name for uid %u\n", (unsigned int)getuid());
exit(1);
@@ -501,7 +510,8 @@ static int process_nonroot(int local_flags)
exit(1);
}
- if (!password_change(remote_machine, user_name, old_pw, new_pw, 0)) {
+ if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_pw,
+ new_pw, 0))) {
fprintf(stderr,"Failed to change password for %s\n", user_name);
result = 1;
goto done;
diff --git a/source/utils/smbtree.c b/source/utils/smbtree.c
index 3755b7f8e55..853a46f379e 100644
--- a/source/utils/smbtree.c
+++ b/source/utils/smbtree.c
@@ -216,7 +216,7 @@ static BOOL print_tree(struct user_auth_info *user_info)
while(poptGetNextOpt(pc) != -1);
poptFreeContext(pc);
- lp_load(dyn_CONFIGFILE,True,False,False);
+ lp_load(dyn_CONFIGFILE,True,False,False,True);
load_interfaces();
/* Parse command line args */
diff --git a/source/utils/smbw_sample.c b/source/utils/smbw_sample.c
index 5cd792df7a2..ba78eb22fc7 100644
--- a/source/utils/smbw_sample.c
+++ b/source/utils/smbw_sample.c
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
extern int optind;
char *path;
- lp_load(dyn_CONFIGFILE,1,0,0);
+ lp_load(dyn_CONFIGFILE,1,0,0,1);
smbw_setup_shared();
while ((opt = getopt(argc, argv, "W:U:R:d:P:l:hL:")) != EOF) {
diff --git a/source/utils/status.c b/source/utils/status.c
index 1089a96e4a9..bc26be1ec93 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -159,9 +159,13 @@ static void print_share_mode(const struct share_mode_entry *e, const char *share
}
}
-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)
{
static int count;
if (count==0) {
@@ -653,7 +657,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
d_printf("using configfile = %s\n", dyn_CONFIGFILE);
}
- if (!lp_load(dyn_CONFIGFILE,False,False,False)) {
+ if (!lp_load(dyn_CONFIGFILE,False,False,False,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
return (-1);
}
diff --git a/source/utils/testparm.c b/source/utils/testparm.c
index 11ce960e557..8b9ff4710e0 100644
--- a/source/utils/testparm.c
+++ b/source/utils/testparm.c
@@ -266,7 +266,7 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_
fprintf(stderr,"Load smb config files from %s\n",config_file);
- if (!lp_load(config_file,False,True,False)) {
+ if (!lp_load(config_file,False,True,False,True)) {
fprintf(stderr,"Error loading services.\n");
return(1);
}
diff --git a/source/web/cgi.c b/source/web/cgi.c
index 6c9cfce13cd..b764b6d6283 100644
--- a/source/web/cgi.c
+++ b/source/web/cgi.c
@@ -59,7 +59,7 @@ static char *grab_line(FILE *f, int *cl)
char *ret2;
if (len == 0) len = 1024;
else len *= 2;
- ret2 = (char *)SMB_REALLOC(ret, len);
+ ret2 = (char *)SMB_REALLOC_KEEP_OLD_ON_ERROR(ret, len);
if (!ret2) return ret;
ret = ret2;
}
@@ -293,7 +293,7 @@ static void cgi_web_auth(void)
exit(0);
}
- pwd = getpwnam_alloc(user);
+ pwd = getpwnam_alloc(NULL, user);
if (!pwd) {
printf("%sCannot find user %s<br>%s\n", head, user, tail);
exit(0);
@@ -306,7 +306,7 @@ static void cgi_web_auth(void)
head, user, (int)geteuid(), (int)getuid(), tail);
exit(0);
}
- passwd_free(&pwd);
+ TALLOC_FREE(pwd);
}
@@ -346,7 +346,7 @@ static BOOL cgi_handle_authorization(char *line)
* Try and get the user from the UNIX password file.
*/
- pass = getpwnam_alloc(user);
+ pass = getpwnam_alloc(NULL, user);
/*
* Validate the password they have given.
@@ -367,7 +367,7 @@ static BOOL cgi_handle_authorization(char *line)
/* Save the users name */
C_user = SMB_STRDUP(user);
- passwd_free(&pass);
+ TALLOC_FREE(pass);
return True;
}
}
@@ -377,7 +377,7 @@ err:
"WWW-Authenticate: Basic realm=\"SWAT\"\r\n",
"username or password incorrect");
- passwd_free(&pass);
+ TALLOC_FREE(pass);
return False;
}
diff --git a/source/web/startstop.c b/source/web/startstop.c
index 8f28748918f..44945cd5362 100644
--- a/source/web/startstop.c
+++ b/source/web/startstop.c
@@ -36,7 +36,7 @@ void start_smbd(void)
slprintf(binfile, sizeof(pstring) - 1, "%s/smbd", dyn_SBINDIR);
- become_daemon(True);
+ become_daemon(True, False);
execl(binfile, binfile, "-D", NULL);
@@ -56,7 +56,7 @@ void start_nmbd(void)
slprintf(binfile, sizeof(pstring) - 1, "%s/nmbd", dyn_SBINDIR);
- become_daemon(True);
+ become_daemon(True, False);
execl(binfile, binfile, "-D", NULL);
@@ -76,7 +76,7 @@ void start_winbindd(void)
slprintf(binfile, sizeof(pstring) - 1, "%s/winbindd", dyn_SBINDIR);
- become_daemon(True);
+ become_daemon(True, False);
execl(binfile, binfile, NULL);
diff --git a/source/web/swat.c b/source/web/swat.c
index 91550f7cc9e..cbf5ba89891 100644
--- a/source/web/swat.c
+++ b/source/web/swat.c
@@ -422,7 +422,7 @@ static void show_parameters(int snum, int allparameters, unsigned int parm_filte
static BOOL load_config(BOOL save_def)
{
lp_resetnumservices();
- return lp_load(dyn_CONFIGFILE,False,save_def,False);
+ return lp_load(dyn_CONFIGFILE,False,save_def,False,True);
}
/****************************************************************************
@@ -986,7 +986,7 @@ static BOOL change_password(const char *remote_machine, const char *user_name,
const char *old_passwd, const char *new_passwd,
int local_flags)
{
- BOOL ret = False;
+ NTSTATUS ret;
pstring err_str;
pstring msg_str;
@@ -1000,7 +1000,7 @@ static BOOL change_password(const char *remote_machine, const char *user_name,
new_passwd, err_str, sizeof(err_str));
if(*err_str)
printf("%s\n<p>", err_str);
- return ret;
+ return NT_STATUS_IS_OK(ret);
}
if(!initialize_password_db(True)) {
@@ -1016,7 +1016,7 @@ static BOOL change_password(const char *remote_machine, const char *user_name,
if(*err_str)
printf("%s\n<p>", err_str);
- return ret;
+ return NT_STATUS_IS_OK(ret);
}
/****************************************************************************
diff --git a/source/wrepld/parser.c b/source/wrepld/parser.c
deleted file mode 100644
index 915895507cf..00000000000
--- a/source/wrepld/parser.c
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines
- * Copyright (C) Jean François Micouleau 1998-2002.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-#include "wins_repl.h"
-
-extern TALLOC_CTX *mem_ctx;
-
-/****************************************************************************
-grow the send buffer if necessary
-****************************************************************************/
-BOOL grow_buffer(struct BUFFER *buffer, int more)
-{
- char *temp;
-
- DEBUG(10,("grow_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));
-
- /* grow by at least 256 bytes */
- if (more<256)
- more=256;
-
- if (buffer->offset+more >= buffer->length) {
- temp=talloc_realloc(mem_ctx, buffer->buffer, char, buffer->length + more);
- if (temp==NULL) {
- DEBUG(0,("grow_buffer: can't grow buffer\n"));
- return False;
- }
- buffer->length+=more;
- buffer->buffer=temp;
- }
-
- return True;
-}
-
-/****************************************************************************
-check if the buffer has that much data
-****************************************************************************/
-static BOOL check_buffer(struct BUFFER *buffer, int more)
-{
- DEBUG(10,("check_buffer: size is: %d offet is:%d growing by %d\n", buffer->length, buffer->offset, more));
-
- if (buffer->offset+more > buffer->length) {
- DEBUG(10,("check_buffer: buffer smaller than requested, size is: %d needed: %d\n", buffer->length, buffer->offset+more));
- return False;
- }
-
- return True;
-}
-
-/****************************************************************************
-decode a WINS_OWNER struct
-****************************************************************************/
-static void decode_wins_owner(struct BUFFER *inbuf, WINS_OWNER *wins_owner)
-{
- if(!check_buffer(inbuf, 24))
- return;
-
- wins_owner->address.s_addr=IVAL(inbuf->buffer, inbuf->offset);
- wins_owner->max_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+4))<<32;
- wins_owner->max_version|=RIVAL(inbuf->buffer, inbuf->offset+8);
- wins_owner->min_version=((SMB_BIG_UINT)RIVAL(inbuf->buffer, inbuf->offset+12))<<32;
- wins_owner->min_version|=RIVAL(inbuf->buffer, inbuf->offset+16);
- wins_owner->type=RIVAL(inbuf->buffer, inbuf->offset+20);
- inbuf->offset+=24;
-
-}
-
-/****************************************************************************
-decode a WINS_NAME struct
-****************************************************************************/
-static void decode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
-{
- char *p;
- int i;
-
- if(!check_buffer(outbuf, 40))
- return;
-
- wins_name->name_len=RIVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
- memcpy(wins_name->name,outbuf->buffer+outbuf->offset, 15);
- wins_name->name[15]='\0';
- if((p = strchr(wins_name->name,' ')) != NULL)
- *p = 0;
-
- outbuf->offset+=15;
-
- wins_name->type=(int)outbuf->buffer[outbuf->offset++];
-
- /*
- * fix to bug in WINS replication,
- * present in all versions including W2K SP2 !
- */
- if (wins_name->name[0]==0x1B) {
- wins_name->name[0]=(char)wins_name->type;
- wins_name->type=0x1B;
- }
-
- wins_name->empty=RIVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
-
- wins_name->name_flag=RIVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
- wins_name->group_flag=RIVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
- wins_name->id=((SMB_BIG_UINT)RIVAL(outbuf->buffer, outbuf->offset))<<32;
- outbuf->offset+=4;
- wins_name->id|=RIVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
-
- /* special groups have multiple address */
- if (wins_name->name_flag & 2) {
- if(!check_buffer(outbuf, 4))
- return;
- wins_name->num_ip=IVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
- }
- else
- wins_name->num_ip=1;
-
- if(!check_buffer(outbuf, 4))
- return;
- wins_name->owner.s_addr=IVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
-
- if (wins_name->name_flag & 2) {
- wins_name->others=talloc_array(mem_ctx, struct in_addr, wins_name->num_ip);
- if (wins_name->others==NULL)
- return;
-
- if(!check_buffer(outbuf, 4*wins_name->num_ip))
- return;
- for (i=0; i<wins_name->num_ip; i++) {
- wins_name->others[i].s_addr=IVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
- }
- }
-
- if(!check_buffer(outbuf, 4))
- return;
- wins_name->foo=RIVAL(outbuf->buffer, outbuf->offset);
- outbuf->offset+=4;
-
-}
-
-/****************************************************************************
-decode a update notification request
-****************************************************************************/
-static void decode_update_notify_request(struct BUFFER *inbuf, UPDATE_NOTIFY_REQUEST *un_rq)
-{
- int i;
-
- if(!check_buffer(inbuf, 4))
- return;
- un_rq->partner_count=RIVAL(inbuf->buffer, inbuf->offset);
- inbuf->offset+=4;
-
- un_rq->wins_owner=talloc_array(mem_ctx, WINS_OWNER, un_rq->partner_count);
- if (un_rq->wins_owner==NULL)
- return;
-
- for (i=0; i<un_rq->partner_count; i++)
- decode_wins_owner(inbuf, &un_rq->wins_owner[i]);
-
- if(!check_buffer(inbuf, 4))
- return;
- un_rq->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);
- inbuf->offset+=4;
-}
-
-/****************************************************************************
-decode a send entries request
-****************************************************************************/
-static void decode_send_entries_request(struct BUFFER *inbuf, SEND_ENTRIES_REQUEST *se_rq)
-{
- decode_wins_owner(inbuf, &se_rq->wins_owner);
-}
-
-/****************************************************************************
-decode a send entries reply
-****************************************************************************/
-static void decode_send_entries_reply(struct BUFFER *inbuf, SEND_ENTRIES_REPLY *se_rp)
-{
- int i;
-
- if(!check_buffer(inbuf, 4))
- return;
- se_rp->max_names = RIVAL(inbuf->buffer, inbuf->offset);
- inbuf->offset+=4;
-
- se_rp->wins_name=talloc_array(mem_ctx, WINS_NAME, se_rp->max_names);
- if (se_rp->wins_name==NULL)
- return;
-
- for (i=0; i<se_rp->max_names; i++)
- decode_wins_name(inbuf, &se_rp->wins_name[i]);
-}
-
-/****************************************************************************
-decode a add version number map table reply
-****************************************************************************/
-static void decode_add_version_number_map_table_reply(struct BUFFER *inbuf, AVMT_REP *avmt_rep)
-{
- int i;
-
- if(!check_buffer(inbuf, 4))
- return;
-
- avmt_rep->partner_count=RIVAL(inbuf->buffer, inbuf->offset);
- inbuf->offset+=4;
-
- avmt_rep->wins_owner=talloc_array(mem_ctx, WINS_OWNER, avmt_rep->partner_count);
- if (avmt_rep->wins_owner==NULL)
- return;
-
- for (i=0; i<avmt_rep->partner_count; i++)
- decode_wins_owner(inbuf, &avmt_rep->wins_owner[i]);
-
- if(!check_buffer(inbuf, 4))
- return;
- avmt_rep->initiating_wins_server.s_addr=IVAL(inbuf->buffer, inbuf->offset);
- inbuf->offset+=4;
-}
-
-/****************************************************************************
-decode a replicate packet and fill a structure
-****************************************************************************/
-static void decode_replicate(struct BUFFER *inbuf, REPLICATE *rep)
-{
- if(!check_buffer(inbuf, 4))
- return;
-
- rep->msg_type = RIVAL(inbuf->buffer, inbuf->offset);
-
- inbuf->offset+=4;
-
- switch (rep->msg_type) {
- case 0:
- break;
- case 1:
- /* add version number map table reply */
- decode_add_version_number_map_table_reply(inbuf, &rep->avmt_rep);
- break;
- case 2:
- /* send entry request */
- decode_send_entries_request(inbuf, &rep->se_rq);
- break;
- case 3:
- /* send entry request */
- decode_send_entries_reply(inbuf, &rep->se_rp);
- break;
- case 4:
- /* update notification request */
- decode_update_notify_request(inbuf, &rep->un_rq);
- break;
- default:
- DEBUG(0,("decode_replicate: unknown message type:%d\n", rep->msg_type));
- break;
- }
-}
-
-/****************************************************************************
-read the generic header and fill the struct.
-****************************************************************************/
-static void read_generic_header(struct BUFFER *inbuf, generic_header *q)
-{
- if(!check_buffer(inbuf, 16))
- return;
-
- q->data_size = RIVAL(inbuf->buffer, inbuf->offset+0);
- q->opcode = RIVAL(inbuf->buffer, inbuf->offset+4);
- q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+8);
- q->mess_type = RIVAL(inbuf->buffer, inbuf->offset+12);
-}
-
-/*******************************************************************
-decode a start association request
-********************************************************************/
-static void decode_start_assoc_request(struct BUFFER *inbuf, START_ASSOC_REQUEST *q)
-{
- if(!check_buffer(inbuf, 8))
- return;
-
- q->assoc_ctx = RIVAL(inbuf->buffer, inbuf->offset+0);
- q->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4);
- q->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6);
-}
-
-/*******************************************************************
-decode a start association reply
-********************************************************************/
-static void decode_start_assoc_reply(struct BUFFER *inbuf, START_ASSOC_REPLY *r)
-{
- if(!check_buffer(inbuf, 8))
- return;
-
- r->assoc_ctx=RIVAL(inbuf->buffer, inbuf->offset+0);
- r->min_ver = RSVAL(inbuf->buffer, inbuf->offset+4);
- r->maj_ver = RSVAL(inbuf->buffer, inbuf->offset+6);
-}
-
-/*******************************************************************
-decode a start association reply
-********************************************************************/
-static void decode_stop_assoc(struct BUFFER *inbuf, STOP_ASSOC *r)
-{
- if(!check_buffer(inbuf, 4))
- return;
-
- r->reason=RIVAL(inbuf->buffer, inbuf->offset);
-}
-
-/****************************************************************************
-decode a packet and fill a generic structure
-****************************************************************************/
-void decode_generic_packet(struct BUFFER *inbuf, GENERIC_PACKET *q)
-{
- read_generic_header(inbuf, &q->header);
-
- inbuf->offset+=16;
-
- switch (q->header.mess_type) {
- case 0:
- decode_start_assoc_request(inbuf, &q->sa_rq);
- break;
- case 1:
- decode_start_assoc_reply(inbuf, &q->sa_rp);
- break;
- case 2:
- decode_stop_assoc(inbuf, &q->so);
- break;
- case 3:
- decode_replicate(inbuf, &q->rep);
- break;
- default:
- DEBUG(0,("decode_generic_packet: unknown message type:%d\n", q->header.mess_type));
- break;
- }
-}
-
-/****************************************************************************
-encode a WINS_OWNER struct
-****************************************************************************/
-static void encode_wins_owner(struct BUFFER *outbuf, WINS_OWNER *wins_owner)
-{
- if (!grow_buffer(outbuf, 24))
- return;
-
- SIVAL(outbuf->buffer, outbuf->offset, wins_owner->address.s_addr);
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version>>32));
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, (int)(wins_owner->max_version&0xffffffff));
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version>>32);
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->min_version&0xffffffff);
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, wins_owner->type);
- outbuf->offset+=4;
-
-}
-
-/****************************************************************************
-encode a WINS_NAME struct
-****************************************************************************/
-static void encode_wins_name(struct BUFFER *outbuf, WINS_NAME *wins_name)
-{
- int i;
-
- if (!grow_buffer(outbuf, 48+(4*wins_name->num_ip)))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_len);
- outbuf->offset+=4;
-
- memset(outbuf->buffer+outbuf->offset, ' ', 15);
-
- /* to prevent copying the leading \0 */
- memcpy(outbuf->buffer+outbuf->offset, wins_name->name, strlen(wins_name->name));
- outbuf->offset+=15;
-
- outbuf->buffer[outbuf->offset++]=(char)wins_name->type;
-
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->empty);
- outbuf->offset+=4;
-
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->name_flag);
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->group_flag);
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id>>32);
- outbuf->offset+=4;
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->id);
- outbuf->offset+=4;
-
- if (wins_name->name_flag & 2) {
- SIVAL(outbuf->buffer, outbuf->offset, wins_name->num_ip);
- outbuf->offset+=4;
- }
-
- SIVAL(outbuf->buffer, outbuf->offset, wins_name->owner.s_addr);
- outbuf->offset+=4;
-
- if (wins_name->name_flag & 2) {
- for (i=0;i<wins_name->num_ip;i++) {
- SIVAL(outbuf->buffer, outbuf->offset, wins_name->others[i].s_addr);
- outbuf->offset+=4;
- }
- }
-
- RSIVAL(outbuf->buffer, outbuf->offset, wins_name->foo);
- outbuf->offset+=4;
-}
-
-/****************************************************************************
-encode a update notification request
-****************************************************************************/
-static void encode_update_notify_request(struct BUFFER *outbuf, UPDATE_NOTIFY_REQUEST *un_rq)
-{
- int i;
-
- if (!grow_buffer(outbuf, 8))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, un_rq->partner_count);
- outbuf->offset+=4;
-
- for (i=0; i<un_rq->partner_count; i++)
- encode_wins_owner(outbuf, &un_rq->wins_owner[i]);
-
- SIVAL(outbuf->buffer, outbuf->offset, un_rq->initiating_wins_server.s_addr);
- outbuf->offset+=4;
-
-}
-
-/****************************************************************************
-decode a send entries request
-****************************************************************************/
-static void encode_send_entries_request(struct BUFFER *outbuf, SEND_ENTRIES_REQUEST *se_rq)
-{
- encode_wins_owner(outbuf, &se_rq->wins_owner);
-}
-
-/****************************************************************************
-decode a send entries reply
-****************************************************************************/
-static void encode_send_entries_reply(struct BUFFER *outbuf, SEND_ENTRIES_REPLY *se_rp)
-{
- int i;
-
- if (!grow_buffer(outbuf, 4))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, se_rp->max_names);
- outbuf->offset+=4;
-
- for (i=0; i<se_rp->max_names; i++)
- encode_wins_name(outbuf, &se_rp->wins_name[i]);
-
-}
-
-/****************************************************************************
-encode a add version number map table reply
-****************************************************************************/
-static void encode_add_version_number_map_table_reply(struct BUFFER *outbuf, AVMT_REP *avmt_rep)
-{
- int i;
-
- if (!grow_buffer(outbuf, 8))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, avmt_rep->partner_count);
- outbuf->offset+=4;
-
- for (i=0; i<avmt_rep->partner_count; i++)
- encode_wins_owner(outbuf, &avmt_rep->wins_owner[i]);
-
- SIVAL(outbuf->buffer, outbuf->offset, avmt_rep->initiating_wins_server.s_addr);
- outbuf->offset+=4;
-
-}
-
-/****************************************************************************
-decode a replicate packet and fill a structure
-****************************************************************************/
-static void encode_replicate(struct BUFFER *outbuf, REPLICATE *rep)
-{
- if (!grow_buffer(outbuf, 4))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, rep->msg_type);
- outbuf->offset+=4;
-
- switch (rep->msg_type) {
- case 0:
- break;
- case 1:
- /* add version number map table reply */
- encode_add_version_number_map_table_reply(outbuf, &rep->avmt_rep);
- break;
- case 2:
- /* send entry request */
- encode_send_entries_request(outbuf, &rep->se_rq);
- break;
- case 3:
- /* send entry request */
- encode_send_entries_reply(outbuf, &rep->se_rp);
- break;
- case 4:
- /* update notification request */
- encode_update_notify_request(outbuf, &rep->un_rq);
- break;
- default:
- DEBUG(0,("encode_replicate: unknown message type:%d\n", rep->msg_type));
- break;
- }
-}
-
-/****************************************************************************
-write the generic header.
-****************************************************************************/
-static void write_generic_header(struct BUFFER *outbuf, generic_header *r)
-{
- RSIVAL(outbuf->buffer, 0, r->data_size);
- RSIVAL(outbuf->buffer, 4, r->opcode);
- RSIVAL(outbuf->buffer, 8, r->assoc_ctx);
- RSIVAL(outbuf->buffer,12, r->mess_type);
-}
-
-/*******************************************************************
-decode a start association request
-********************************************************************/
-static void encode_start_assoc_request(struct BUFFER *outbuf, START_ASSOC_REQUEST *q)
-{
- if (!grow_buffer(outbuf, 45))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, q->assoc_ctx);
- RSSVAL(outbuf->buffer, outbuf->offset+4, q->min_ver);
- RSSVAL(outbuf->buffer, outbuf->offset+6, q->maj_ver);
-
- outbuf->offset=45;
-}
-
-/*******************************************************************
-decode a start association reply
-********************************************************************/
-static void encode_start_assoc_reply(struct BUFFER *outbuf, START_ASSOC_REPLY *r)
-{
- if (!grow_buffer(outbuf, 45))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, r->assoc_ctx);
- RSSVAL(outbuf->buffer, outbuf->offset+4, r->min_ver);
- RSSVAL(outbuf->buffer, outbuf->offset+6, r->maj_ver);
-
- outbuf->offset=45;
-}
-
-/*******************************************************************
-decode a start association reply
-********************************************************************/
-static void encode_stop_assoc(struct BUFFER *outbuf, STOP_ASSOC *r)
-{
- if (!grow_buffer(outbuf, 44))
- return;
-
- RSIVAL(outbuf->buffer, outbuf->offset, r->reason);
-
- outbuf->offset=44;
-}
-
-/****************************************************************************
-write the generic header size.
-****************************************************************************/
-static void write_generic_header_size(generic_header *r, int size)
-{
- /* the buffer size is the total size minus the size field */
- r->data_size=size-4;
-}
-
-/****************************************************************************
-encode a packet and read a generic structure
-****************************************************************************/
-void encode_generic_packet(struct BUFFER *outbuf, GENERIC_PACKET *q)
-{
- if (!grow_buffer(outbuf, 16))
- return;
-
- outbuf->offset=16;
-
- switch (q->header.mess_type) {
- case 0:
- encode_start_assoc_request(outbuf, &q->sa_rq);
- break;
- case 1:
- encode_start_assoc_reply(outbuf, &q->sa_rp);
- break;
- case 2:
- encode_stop_assoc(outbuf, &q->so);
- break;
- case 3:
- encode_replicate(outbuf, &q->rep);
- break;
- default:
- DEBUG(0,("encode_generic_packet: unknown message type:%d\n", q->header.mess_type));
- break;
- }
-
- write_generic_header_size(&q->header, outbuf->offset);
- write_generic_header(outbuf, &q->header);
-}
-
-
-/****************************************************************************
-dump a WINS_OWNER structure
-****************************************************************************/
-static void dump_wins_owner(WINS_OWNER *wins_owner)
-{
- DEBUGADD(10,("\t\t\t\taddress : %s\n", inet_ntoa(wins_owner->address)));
- DEBUGADD(10,("\t\t\t\tmax version: %d\n", (int)wins_owner->max_version));
- DEBUGADD(10,("\t\t\t\tmin version: %d\n", (int)wins_owner->min_version));
- DEBUGADD(10,("\t\t\t\ttype : %d\n", wins_owner->type));
-}
-
-/****************************************************************************
-dump a WINS_NAME structure
-****************************************************************************/
-static void dump_wins_name(WINS_NAME *wins_name)
-{
- fstring name;
- int i;
-
- strncpy(name, wins_name->name, 15);
-
- DEBUGADD(10,("name: %d, %s<%02x> %x,%x, %d %s %d ", wins_name->name_len, name, wins_name->type,
- wins_name->name_flag, wins_name->group_flag, (int)wins_name->id,
- inet_ntoa(wins_name->owner), wins_name->num_ip));
-
- if (wins_name->num_ip!=1)
- for (i=0; i<wins_name->num_ip; i++)
- DEBUGADD(10,("%s ", inet_ntoa(wins_name->others[i])));
-
- DEBUGADD(10,("\n"));
-}
-
-/****************************************************************************
-dump a replicate structure
-****************************************************************************/
-static void dump_replicate(REPLICATE *rep)
-{
- int i;
-
- DEBUGADD(5,("\t\tmsg_type: %d ", rep->msg_type));
-
- switch (rep->msg_type) {
- case 0:
- DEBUGADD(5,("(Add Version Map Table Request)\n"));
- break;
- case 1:
- DEBUGADD(5,("(Add Version Map Table Reply)\n"));
- DEBUGADD(5,("\t\t\tpartner_count : %d\n", rep->avmt_rep.partner_count));
- for (i=0; i<rep->avmt_rep.partner_count; i++)
- dump_wins_owner(&rep->avmt_rep.wins_owner[i]);
- DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep->avmt_rep.initiating_wins_server)));
- break;
- case 2:
- DEBUGADD(5,("(Send Entries Request)\n"));
- dump_wins_owner(&rep->se_rq.wins_owner);
- break;
- case 3:
- DEBUGADD(5,("(Send Entries Reply)\n"));
- DEBUGADD(5,("\t\t\tmax_names : %d\n", rep->se_rp.max_names));
- for (i=0; i<rep->se_rp.max_names; i++)
- dump_wins_name(&rep->se_rp.wins_name[i]);
- break;
- case 4:
- DEBUGADD(5,("(Update Notify Request)\n"));
- DEBUGADD(5,("\t\t\tpartner_count : %d\n", rep->un_rq.partner_count));
- for (i=0; i<rep->un_rq.partner_count; i++)
- dump_wins_owner(&rep->un_rq.wins_owner[i]);
- DEBUGADD(5,("\t\t\tinitiating_wins_server: %s\n", inet_ntoa(rep->un_rq.initiating_wins_server)));
- break;
- default:
- DEBUG(5,("\n"));
- break;
- }
-}
-
-/****************************************************************************
-dump a generic structure
-****************************************************************************/
-void dump_generic_packet(GENERIC_PACKET *q)
-{
- DEBUG(5,("dump_generic_packet:\n"));
- DEBUGADD(5,("\tdata_size: %08x\n", q->header.data_size));
- DEBUGADD(5,("\topcode : %08x\n", q->header.opcode));
- DEBUGADD(5,("\tassoc_ctx: %08x\n", q->header.assoc_ctx));
- DEBUGADD(5,("\tmess_type: %08x ", q->header.mess_type));
-
- switch (q->header.mess_type) {
- case 0:
- DEBUGADD(5,("(Start Association Request)\n"));
- DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q->sa_rq.assoc_ctx));
- DEBUGADD(5,("\t\tmin_ver : %04x\n", q->sa_rq.min_ver));
- DEBUGADD(5,("\t\tmaj_ver : %04x\n", q->sa_rq.maj_ver));
- break;
- case 1:
- DEBUGADD(5,("(Start Association Reply)\n"));
- DEBUGADD(5,("\t\tassoc_ctx: %08x\n", q->sa_rp.assoc_ctx));
- DEBUGADD(5,("\t\tmin_ver : %04x\n", q->sa_rp.min_ver));
- DEBUGADD(5,("\t\tmaj_ver : %04x\n", q->sa_rp.maj_ver));
- break;
- case 2:
- DEBUGADD(5,("(Stop Association)\n"));
- DEBUGADD(5,("\t\treason: %08x\n", q->so.reason));
- break;
- case 3:
- DEBUGADD(5,("(Replication Message)\n"));
- dump_replicate(&q->rep);
- break;
- default:
- DEBUG(5,("\n"));
- break;
- }
-
-}
-
-/****************************************************************************
-generate a stop packet
-****************************************************************************/
-void stop_packet(GENERIC_PACKET *q, GENERIC_PACKET *r, int reason)
-{
- r->header.opcode=OPCODE_NON_NBT;
- r->header.assoc_ctx=get_server_assoc(q->header.assoc_ctx);
- r->header.mess_type=MESSAGE_TYPE_STOP_ASSOC;
- r->so.reason=reason;
-
-}
-
-
diff --git a/source/wrepld/partners.c b/source/wrepld/partners.c
deleted file mode 100644
index 2387f5b45f6..00000000000
--- a/source/wrepld/partners.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- process incoming packets - main loop
- Copyright (C) Jean François Micouleau 1998-2002.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "wins_repl.h"
-
-/* we can exchange info with 64 partners at any given time */
-WINS_PARTNER current_partners[64];
-int total_current_partners;
-
-/*******************************************************************
-verify if we know this partner
-********************************************************************/
-BOOL check_partner(int assoc)
-{
- int i;
-
- DEBUG(5,("check_partner: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==assoc)
- return True;
-
- return False;
-}
-
-/*******************************************************************
-add a new entry to the list
-********************************************************************/
-BOOL add_partner(int client_assoc, int server_assoc, BOOL pull, BOOL push)
-{
- DEBUG(5,("add_partner: total_current_partners: %d\n", total_current_partners));
-
- if (total_current_partners==64)
- return False;
-
- current_partners[total_current_partners].client_assoc=client_assoc;
- current_partners[total_current_partners].server_assoc=server_assoc;
- current_partners[total_current_partners].pull_partner=pull;
- current_partners[total_current_partners].push_partner=push;
-
- total_current_partners++;
-
- return True;
-}
-
-/*******************************************************************
-remove an entry to the list
-********************************************************************/
-BOOL remove_partner(int client_assoc)
-{
- int i,j;
-
- DEBUG(5,("remove_partner: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; current_partners[i].client_assoc!=client_assoc && i<total_current_partners; i++)
- ;
-
- if (i==total_current_partners)
- return False;
-
- for (j=i+1; j<total_current_partners; j++) {
- current_partners[j-1].client_assoc=current_partners[j].client_assoc;
- current_partners[j-1].server_assoc=current_partners[j].server_assoc;
- current_partners[j-1].pull_partner=current_partners[j].pull_partner;
- current_partners[j-1].push_partner=current_partners[j].push_partner;
- current_partners[j-1].partner_server.s_addr=current_partners[j].partner_server.s_addr;
- current_partners[j-1].other_server.s_addr=current_partners[j].other_server.s_addr;
- }
-
- total_current_partners--;
-
- return True;
-}
-
-/*******************************************************************
-link the client and server context
-********************************************************************/
-BOOL update_server_partner(int client_assoc, int server_assoc)
-{
- int i;
-
- DEBUG(5,("update_server_partner: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==client_assoc) {
- current_partners[i].server_assoc=server_assoc;
- return True;
- }
-
- return False;
-}
-
-/*******************************************************************
-verify if it's a pull partner
-********************************************************************/
-BOOL check_pull_partner(int assoc)
-{
- int i;
-
- DEBUG(5,("check_pull_partner: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==assoc &&
- current_partners[i].pull_partner==True)
- return True;
-
- return False;
-}
-
-/*******************************************************************
-verify if it's a push partner
-********************************************************************/
-BOOL check_push_partner(int assoc)
-{
- int i;
-
- DEBUG(5,("check_push_partner: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==assoc &&
- current_partners[i].push_partner==True)
- return True;
-
- return False;
-}
-
-/*******************************************************************
-return the server ctx linked to the client ctx
-********************************************************************/
-int get_server_assoc(int assoc)
-{
- int i;
-
- DEBUG(5,("get_server_assoc: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==assoc)
- return current_partners[i].server_assoc;
-
- return 0;
-}
-
-
-/*******************************************************************
-link the client and server context
-********************************************************************/
-BOOL write_server_assoc_table(int client_assoc, struct in_addr partner, struct in_addr server)
-{
- int i;
-
- DEBUG(5,("write_server_assoc_table: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==client_assoc) {
- current_partners[i].partner_server=partner;
- current_partners[i].other_server=server;
- return True;
- }
-
- return False;
-}
-
-/*******************************************************************
-link the client and server context
-********************************************************************/
-BOOL get_server_assoc_table(int client_assoc, struct in_addr *partner, struct in_addr *server)
-{
- int i;
-
- DEBUG(5,("get_server_assoc_table: total_current_partners: %d\n", total_current_partners));
-
- for (i=0; i<total_current_partners; i++)
- if (current_partners[i].client_assoc==client_assoc) {
- partner->s_addr=current_partners[i].partner_server.s_addr;
- server->s_addr=current_partners[i].other_server.s_addr;
- return True;
- }
-
- return False;
-}
-
-
diff --git a/source/wrepld/process.c b/source/wrepld/process.c
deleted file mode 100644
index 7a94cdcafb9..00000000000
--- a/source/wrepld/process.c
+++ /dev/null
@@ -1,983 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- process incoming packets - main loop
- Copyright (C) Jean François Micouleau 1998-2002.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "wins_repl.h"
-
-extern fd_set *listen_set;
-extern int listen_number;
-extern int *sock_array;
-
-WINS_OWNER global_wins_table[64][64];
-int partner_count;
-
-TALLOC_CTX *mem_ctx;
-
-#define WINS_LIST "wins.tdb"
-#define INFO_VERSION "INFO/version"
-#define INFO_COUNT "INFO/num_entries"
-#define INFO_ID_HIGH "INFO/id_high"
-#define INFO_ID_LOW "INFO/id_low"
-#define ENTRY_PREFIX "ENTRY/"
-
-
-/*******************************************************************
-fill the header of a reply.
-********************************************************************/
-static void fill_header(GENERIC_PACKET *g, int opcode, int ctx, int mess)
-{
- if (g==NULL)
- return;
-
- g->header.opcode=opcode;
- g->header.assoc_ctx=ctx;
- g->header.mess_type=mess;
-}
-
-/*******************************************************************
-dump the global table, that's a debug code.
-********************************************************************/
-static void dump_global_table(void)
-{
- int i,j;
-
- for (i=0;i<partner_count;i++) {
- DEBUG(10,("\n%d ", i));
- for (j=0; global_wins_table[i][j].address.s_addr!=0; j++)
- DEBUG(10,("%s:%d \t", inet_ntoa(global_wins_table[i][j].address),
- (int)global_wins_table[i][j].max_version));
- }
- DEBUG(10,("\n"));
-}
-
-/*******************************************************************
-start association
-********************************************************************/
-static void start_assoc_process(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- /*
- * add this request to our current wins partners list
- * this list is used to know with who we are in contact
- *
- */
- r->sa_rp.assoc_ctx=time(NULL);
- fill_header(r, OPCODE_NON_NBT, q->sa_rq.assoc_ctx, MESSAGE_TYPE_START_ASSOC_REPLY);
-
- /* reply we are a NT4 server */
-
- /* w2K is min=2, maj=5 */
-
- r->sa_rp.min_ver=1;
- r->sa_rp.maj_ver=1;
-
- add_partner(r->sa_rp.assoc_ctx, q->sa_rq.assoc_ctx, False, False);
-}
-
-/*******************************************************************
-start association reply
-********************************************************************/
-static void start_assoc_reply(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- int i;
-
- /* check if we have already registered this client */
- if (!check_partner(q->header.assoc_ctx)) {
- DEBUG(0,("start_assoc_reply: unknown client\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- if (!update_server_partner(q->header.assoc_ctx, q->sa_rp.assoc_ctx)) {
- DEBUG(0,("start_assoc_reply: can't update server ctx\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- /* if pull, request map table */
- if (check_pull_partner(q->header.assoc_ctx)) {
- fill_header(r, OPCODE_NON_NBT, get_server_assoc(q->header.assoc_ctx), MESSAGE_TYPE_REPLICATE);
-
- r->rep.msg_type=MESSAGE_REP_ADD_VERSION_REQUEST;
- DEBUG(5,("start_assoc_reply: requesting map table\n"));
-
- return;
- }
-
- /* if push, send our table */
- if (check_push_partner(q->header.assoc_ctx)) {
- fill_header(r, OPCODE_NON_NBT, get_server_assoc(q->header.assoc_ctx), MESSAGE_TYPE_REPLICATE);
- r->rep.msg_type=MESSAGE_REP_UPDATE_NOTIFY_REQUEST;
- r->rep.un_rq.partner_count=partner_count;
-
- r->rep.un_rq.wins_owner=talloc_array(mem_ctx, WINS_OWNER, partner_count);
- if (r->rep.un_rq.wins_owner==NULL) {
- DEBUG(0,("start_assoc_reply: can't alloc memory\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- for (i=0; i<partner_count; i++)
- r->rep.un_rq.wins_owner[i]=global_wins_table[0][i];
-
- DEBUG(5,("start_assoc_reply: sending update table\n"));
- return;
- }
-
- /* neither push/pull, stop */
- /* we should not come here */
- DEBUG(0,("we have a partner which is neither push nor pull !\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
-}
-
-/****************************************************************************
-initialise and fill the in-memory partner table.
-****************************************************************************/
-int init_wins_partner_table(void)
-{
- int i=1,j=0,k;
- char **partner = str_list_make(lp_wins_partners(), NULL);
-
- if (partner==NULL) {
- DEBUG(0,("wrepld: no partner list in smb.conf, exiting\n"));
- exit_server("normal exit");
- return(0);
- }
-
- DEBUG(4, ("init_wins_partner_table: partners: %s\n", lp_wins_partners()));
-
- global_wins_table[0][0].address=*iface_n_ip(0);
- global_wins_table[0][0].max_version=0;
- global_wins_table[0][0].min_version=0;
- global_wins_table[0][0].type=0;
-
- while (partner[j]!=NULL) {
- DEBUG(3,("init_wins_partner_table, adding partner: %s\n", partner[j]));
-
- global_wins_table[0][i].address=*interpret_addr2(partner[j]);
- global_wins_table[0][i].max_version=0;
- global_wins_table[0][i].min_version=0;
- global_wins_table[0][i].type=0;
- global_wins_table[0][i].last_pull=0;
- global_wins_table[0][i].last_push=0;
-
- i++;
- j++;
- }
-
- for (k=1; k<i;k++)
- for (j=0; j<i; j++)
- global_wins_table[k][j]=global_wins_table[0][j];
-
- str_list_free (&partner);
-
- return i;
-}
-
-/****************************************************************************
-read the last ID from the wins tdb file.
-****************************************************************************/
-static void get_our_last_id(WINS_OWNER *wins_owner)
-{
- TDB_CONTEXT *tdb;
-
- tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
- if (!tdb) {
- DEBUG(2,("get_our_last_id: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
- return;
- }
-
- wins_owner->max_version=((SMB_BIG_UINT)tdb_fetch_int32(tdb, INFO_ID_HIGH))<<32 |
- (SMB_BIG_UINT)tdb_fetch_int32(tdb, INFO_ID_LOW);
-
- tdb_close(tdb);
-}
-
-/****************************************************************************
-send the list of wins server we know.
-****************************************************************************/
-static void send_version_number_map_table(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- int i;
- int s_ctx=get_server_assoc(q->header.assoc_ctx);
-
- if (s_ctx==0) {
- DEBUG(5, ("send_version_number_map_table: request for a partner not in our table\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- /*
- * return an array of wins servers, we are partner with.
- * each entry contains the IP address and the version info
- * version: ID of the last entry we've got
- */
-
- /* the first wins server must be self */
-
- /*
- * get our last ID from the wins database
- * it can have been updated since last read
- * as nmbd got registration/release.
- */
- get_our_last_id(&global_wins_table[0][0]);
-
- r->rep.avmt_rep.wins_owner=talloc_array(mem_ctx, WINS_OWNER, partner_count);
- if (r->rep.avmt_rep.wins_owner==NULL) {
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- DEBUG(5,("send_version_number_map_table: partner_count: %d\n", partner_count));
-
- for (i=0; i<partner_count; i++) {
- DEBUG(5,("send_version_number_map_table, partner: %d -> %s, \n", i, inet_ntoa(global_wins_table[0][i].address)));
- r->rep.avmt_rep.wins_owner[i]=global_wins_table[0][i];
- }
-
- r->rep.msg_type=1;
- r->rep.avmt_rep.partner_count=partner_count;
- r->rep.avmt_rep.initiating_wins_server.s_addr=0; /* blatant lie, NT4/w2K do the same ! */
- fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE);
-}
-
-/****************************************************************************
-for a given partner, ask it to send entries we don't have.
-****************************************************************************/
-static BOOL check_partners_and_send_entries(GENERIC_PACKET *q, GENERIC_PACKET *r, int partner)
-{
- int server;
- int other;
- SMB_BIG_UINT temp;
- SMB_BIG_UINT current;
-
-
- /*
- * we check if our partner has more records than us.
- * we need to check more than our direct partners as
- * we can have this case:
- * us: A, partners: B,C, indirect partner: D
- * A<->B, A<->C, B<->D, C<->D
- *
- * So if we're talking to B, we need to check if between
- * B and C, which one have more records about D.
- * and also check if we don't already have the records.
- */
-
-
- /* check all servers even indirect */
- for (server=1; global_wins_table[0][server].address.s_addr!=0; server++) {
- current = global_wins_table[partner][server].max_version;
-
- temp=0;
-
- for (other=1; other<partner_count; other++) {
- /* skip the partner itself */
- if (other==partner)
- continue;
-
- if (global_wins_table[other][server].max_version > temp)
- temp=global_wins_table[other][server].max_version;
- }
-
- if (current >= temp && current > global_wins_table[0][server].max_version) {
- /*
- * it has more records than every body else and more than us,
- * ask it the difference between what we have and what it has
- */
- fill_header(r, OPCODE_NON_NBT, get_server_assoc(q->header.assoc_ctx), MESSAGE_TYPE_REPLICATE);
-
- r->rep.msg_type=MESSAGE_REP_SEND_ENTRIES_REQUEST;
- r->rep.se_rq.wins_owner.address=global_wins_table[partner][server].address;
-
- r->rep.se_rq.wins_owner.max_version=global_wins_table[partner][server].max_version;
- r->rep.se_rq.wins_owner.min_version=global_wins_table[0][server].max_version;
- r->rep.se_rq.wins_owner.type=0;
-
- write_server_assoc_table(q->header.assoc_ctx, global_wins_table[0][partner].address, global_wins_table[partner][server].address);
-
- /*
- * and we update our version for this server
- * as we can't use the IDs returned in the send_entries function
- * the max ID can be larger than the largest ID returned
- */
-
- global_wins_table[0][server].max_version=global_wins_table[partner][server].max_version;
-
- return True;
- }
- }
- return False;
-}
-
-/****************************************************************************
-receive the list of wins server we know.
-****************************************************************************/
-static void receive_version_number_map_table(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- fstring peer;
- struct in_addr addr;
- int i,j,k,l;
- int s_ctx=get_server_assoc(q->header.assoc_ctx);
-
- if (s_ctx==0) {
- DEBUG(5, ("receive_version_number_map_table: request for a partner not in our table\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- fstrcpy(peer,get_peer_addr(q->fd));
- addr=*interpret_addr2(peer);
-
- get_our_last_id(&global_wins_table[0][0]);
-
- DEBUG(5,("receive_version_number_map_table: received a map of %d server from: %s\n",
- q->rep.avmt_rep.partner_count ,inet_ntoa(q->rep.avmt_rep.initiating_wins_server)));
- DEBUG(5,("real peer is: %s\n", peer));
-
- for (i=0; global_wins_table[0][i].address.s_addr!=addr.s_addr && i<partner_count;i++)
- ;
-
- if (i==partner_count) {
- DEBUG(5,("receive_version_number_map_table: unknown partner: %s\n", peer));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- for (j=0; j<q->rep.avmt_rep.partner_count;j++) {
- /*
- * search if we already have this entry or if it's a new one
- * it can be a new one in case of propagation
- */
- for (k=0; global_wins_table[0][k].address.s_addr!=0 &&
- global_wins_table[0][k].address.s_addr!=q->rep.avmt_rep.wins_owner[j].address.s_addr; k++);
-
- global_wins_table[i][k].address.s_addr=q->rep.avmt_rep.wins_owner[j].address.s_addr;
- global_wins_table[i][k].max_version=q->rep.avmt_rep.wins_owner[j].max_version;
- global_wins_table[i][k].min_version=q->rep.avmt_rep.wins_owner[j].min_version;
- global_wins_table[i][k].type=q->rep.avmt_rep.wins_owner[j].type;
-
- /*
- * in case it's a new one, rewrite the address for all the partner
- * to reserve the slot.
- */
-
- for(l=0; l<partner_count; l++)
- global_wins_table[l][k].address.s_addr=q->rep.avmt_rep.wins_owner[j].address.s_addr;
- }
-
- dump_global_table();
-
- /*
- * if this server have newer records than what we have
- * for several wins servers, we need to ask it.
- * Alas a send entry request is only on one server.
- * So in the send entry reply, we'll ask for the next server if required.
- */
-
- if (check_partners_and_send_entries(q, r, i))
- return;
-
- /* it doesn't have more entries than us */
- stop_packet(q, r, STOP_REASON_USER_REASON);
-}
-
-/****************************************************************************
-add an entry to the wins list we'll send.
-****************************************************************************/
-static BOOL add_record_to_winsname(WINS_NAME **wins_name, int *max_names, char *name, int type, int wins_flags, int id, struct in_addr *ip_list, int num_ips)
-{
- WINS_NAME *temp_list;
- int i;
- int current=*max_names;
-
- temp_list=talloc_realloc(mem_ctx, *wins_name, WINS_NAME, current + 1);
- if (temp_list==NULL)
- return False;
-
- temp_list[current].name_len=0x11;
-
- safe_strcpy(temp_list[current].name, name, 15);
-
- temp_list[current].type=type;
- temp_list[current].empty=0;
-
- temp_list[current].name_flag=wins_flags;
-
- if ( (wins_flags&0x03) == 1 || (wins_flags&0x03)==2)
- temp_list[current].group_flag=0x01000000;
- else
- temp_list[current].group_flag=0x00000000;
-
- temp_list[current].id=id;
-
- temp_list[current].owner.s_addr=ip_list[0].s_addr;
-
- if (temp_list[current].name_flag & 2) {
- temp_list[current].num_ip=num_ips;
- temp_list[current].others=talloc_array(mem_ctx, struct in_addr, num_ips);
- if (temp_list[current].others==NULL)
- return False;
-
- for (i=0; i<num_ips; i++)
- temp_list[current].others[i].s_addr=ip_list[i].s_addr;
-
- } else
- temp_list[current].num_ip=1;
-
- temp_list[current].foo=0xffffffff;
-
- *wins_name=temp_list;
-
- return True;
-}
-
-/****************************************************************************
-send the list of name we have.
-****************************************************************************/
-static void send_entry_request(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- int max_names=0;
- int i;
- time_t time_now = time(NULL);
- WINS_OWNER *wins_owner;
- TDB_CONTEXT *tdb;
- TDB_DATA kbuf, dbuf, newkey;
- int s_ctx=get_server_assoc(q->header.assoc_ctx);
- int num_interfaces = iface_count();
-
- if (s_ctx==0) {
- DEBUG(1, ("send_entry_request: request for a partner not in our table\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
-
- wins_owner=&q->rep.se_rq.wins_owner;
- r->rep.se_rp.wins_name=NULL;
-
- DEBUG(3,("send_entry_request: we have been asked to send the list of wins records\n"));
- DEBUGADD(3,("owned by: %s and between min: %d and max: %d\n", inet_ntoa(wins_owner->address),
- (int)wins_owner->min_version, (int)wins_owner->max_version));
-
- /*
- * if we are asked to send records owned by us
- * we overwrite the wins ip with 0.0.0.0
- * to make it easy in case of multihomed
- */
-
- for (i=0; i<num_interfaces; i++)
- if (ip_equal(wins_owner->address, *iface_n_ip(i))) {
- wins_owner->address=*interpret_addr2("0.0.0.0");
- break;
- }
-
-
- tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
- if (!tdb) {
- DEBUG(2,("send_entry_request: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
- return;
- }
-
- for (kbuf = tdb_firstkey(tdb);
- kbuf.dptr;
- newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
- fstring name_type;
- pstring name, ip_str;
- char *p;
- int type = 0;
- int nb_flags;
- int ttl;
- unsigned int num_ips;
- int low, high;
- SMB_BIG_UINT version;
- struct in_addr wins_ip;
- struct in_addr *ip_list;
- int wins_flags;
- int len;
-
- if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
- continue;
-
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- continue;
-
- fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
- pstrcpy(name, name_type);
-
- if((p = strchr(name,'#')) != NULL) {
- *p = 0;
- sscanf(p+1,"%x",&type);
- }
-
- len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
- &nb_flags,
- &high,
- &low,
- ip_str,
- &ttl,
- &num_ips,
- &wins_flags);
-
- wins_ip=*interpret_addr2(ip_str);
-
- /* Allocate the space for the ip_list. */
- if((ip_list = talloc_array(mem_ctx, struct in_addr, num_ips)) == NULL) {
- SAFE_FREE(dbuf.dptr);
- DEBUG(0,("initialise_wins: talloc fail !\n"));
- return;
- }
-
- for (i = 0; i < num_ips; i++) {
- len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
- ip_list[i] = *interpret_addr2(ip_str);
- }
-
- SAFE_FREE(dbuf.dptr);
-
- /* add all entries that have 60 seconds or more to live */
- if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
- if(ttl != PERMANENT_TTL)
- ttl -= time_now;
-
- DEBUG( 4, ("send_entry_request: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
- name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
-
- /* add the record to the list to send */
- version=((SMB_BIG_UINT)high)<<32 | low;
-
- if (wins_owner->min_version<=version && wins_owner->max_version>=version &&
- wins_owner->address.s_addr==wins_ip.s_addr) {
- if(!add_record_to_winsname(&r->rep.se_rp.wins_name, &max_names, name, type, wins_flags, version, ip_list, num_ips))
- return;
- max_names++;
- }
-
- } else {
- DEBUG(4, ("send_entry_request: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
- name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
- }
- }
-
- tdb_close(tdb);
-
- DEBUG(4,("send_entry_request, sending %d records\n", max_names));
- fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE);
- r->rep.msg_type=MESSAGE_REP_SEND_ENTRIES_REPLY; /* reply */
- r->rep.se_rp.max_names=max_names;
-}
-
-
-/****************************************************************************
-.
-****************************************************************************/
-static void update_notify_request(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- int i,j,k,l;
- UPDATE_NOTIFY_REQUEST *u;
- int s_ctx=get_server_assoc(q->header.assoc_ctx);
-
- if (s_ctx==0) {
- DEBUG(4, ("update_notify_request: request for a partner not in our table\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- u=&q->rep.un_rq;
-
- /* check if we already have the range of records */
-
- DEBUG(5,("update_notify_request: wins server: %s offered this list of %d records:\n",
- inet_ntoa(u->initiating_wins_server), u->partner_count));
-
- get_our_last_id(&global_wins_table[0][0]);
-
- for (i=0; i<partner_count; i++) {
- if (global_wins_table[0][i].address.s_addr==u->initiating_wins_server.s_addr) {
- DEBUG(5,("update_notify_request: found initiator at index %d\n", i));
- break;
- }
- }
-
- /*
- * some explanation is required, before someone say it's crap.
- *
- * let's take an example, we have 2 wins partners, we already now
- * that our max id is 10, partner 1 ID is 20 and partner 2 ID is 30
- * the array looks like:
- *
- * 0 1 2
- * 0 10 20 30
- * 1
- * 2
- *
- * we receive an update from partner 2 saying he has: 1:15, 2:40, 3:50
- * we must enlarge the array to add partner 3, it will look like:
- *
- * 0 1 2 3
- * 0 10 20 30
- * 1
- * 2 15 40 50
- *
- * now we know, we should pull from partner 2, the records 30->40 of 2 and 0->50 of 3.
- * once the pull will be over, our table will look like:
- *
- * 0 1 2 3
- * 0 10 20 40 50
- * 1
- * 2 15 40 50
- *
- *
- */
-
- for (j=0; j<u->partner_count;j++) {
- /*
- * search if we already have this entry or if it's a new one
- * it can be a new one in case of propagation
- */
-
- for (k=0; global_wins_table[0][k].address.s_addr!=0 &&
- global_wins_table[0][k].address.s_addr!=u->wins_owner[j].address.s_addr; k++);
-
- global_wins_table[i][k].address.s_addr=u->wins_owner[j].address.s_addr;
- global_wins_table[i][k].max_version=u->wins_owner[j].max_version;
- global_wins_table[i][k].min_version=u->wins_owner[j].min_version;
- global_wins_table[i][k].type=u->wins_owner[j].type;
-
- /*
- * in case it's a new one, rewrite the address for all the partner
- * to reserve the slot.
- */
-
- for(l=0; l<partner_count; l++)
- global_wins_table[l][k].address.s_addr=u->wins_owner[j].address.s_addr;
- }
-
- dump_global_table();
-
- stop_packet(q, r, STOP_REASON_USER_REASON);
-}
-
-/****************************************************************************
-.
-****************************************************************************/
-static void send_entry_reply(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- int i,j,k;
- struct in_addr partner, server;
- pid_t pid;
- int s_ctx=get_server_assoc(q->header.assoc_ctx);
- WINS_RECORD record;
-
- if (s_ctx==0) {
- DEBUG(1, ("send_entry_reply: request for a partner not in our table\n"));
- stop_packet(q, r, STOP_REASON_USER_REASON);
- return;
- }
-
- DEBUG(5,("send_entry_reply:got %d new records\n", q->rep.se_rp.max_names));
-
- /* we got records from a wins partner but that can be from another wins server */
- /* hopefully we track that */
-
- /* and the only doc available from MS is wrong ! */
-
- get_server_assoc_table(q->header.assoc_ctx, &partner, &server);
-
- for (j=0; global_wins_table[0][j].address.s_addr!=0; j++) {
- if (global_wins_table[0][j].address.s_addr==server.s_addr) {
- DEBUG(5,("send_entry_reply: found server at index %d\n", j));
- break;
- }
- }
-
- pid = pidfile_pid("nmbd");
- if (pid == 0) {
- DEBUG(0,("send_entry_reply: Can't find pid for nmbd\n"));
- return;
- }
-
- for (k=0; k<q->rep.se_rp.max_names; k++) {
- DEBUG(5,("send_entry_reply: %s<%02x> %d\n", q->rep.se_rp.wins_name[k].name, q->rep.se_rp.wins_name[k].type,
- (int)q->rep.se_rp.wins_name[k].id));
-
- safe_strcpy(record.name, q->rep.se_rp.wins_name[k].name, 16);
- record.type=q->rep.se_rp.wins_name[k].type;
- record.id=q->rep.se_rp.wins_name[k].id;
- record.wins_flags=q->rep.se_rp.wins_name[k].name_flag&0x00ff;
- record.num_ips=q->rep.se_rp.wins_name[k].num_ip;
-
- record.wins_ip.s_addr=server.s_addr;
-
- if (record.num_ips==1)
- record.ip[0]=q->rep.se_rp.wins_name[k].owner;
- else
- for (i=0; i<record.num_ips; i++)
- record.ip[i]=q->rep.se_rp.wins_name[k].others[i];
-
- record.nb_flags=0;
-
- if (record.wins_flags&WINS_NGROUP || record.wins_flags&WINS_SGROUP)
- record.nb_flags|=NB_GROUP;
-
- if (record.wins_flags&WINS_ACTIVE)
- record.nb_flags|=NB_ACTIVE;
-
- record.nb_flags|=record.wins_flags&WINS_HNODE;
-
- message_send_pid(pid, MSG_WINS_NEW_ENTRY, &record, sizeof(record), False);
-
- }
-
- dump_global_table();
-
- /*
- * we got some entries,
- * ask the partner to send us the map table again
- * to get the other servers entries.
- *
- * we're getting the map table 1 time more than really
- * required. We could remove that call, but that
- * would complexify the code. I prefer this trade-of.
- */
- fill_header(r, OPCODE_NON_NBT, s_ctx, MESSAGE_TYPE_REPLICATE);
-
- r->rep.msg_type=MESSAGE_REP_ADD_VERSION_REQUEST;
-}
-
-/****************************************************************************
-decode the replication message and reply.
-****************************************************************************/
-static void replicate(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- switch (q->rep.msg_type) {
- case 0:
- /* add version number map table request */
- send_version_number_map_table(q, r);
- break;
- case 1:
- receive_version_number_map_table(q, r);
- break;
- case 2:
- /* send entry request */
- send_entry_request(q, r);
- break;
- case 3:
- /* send entry reply */
- send_entry_reply(q, r);
- break;
- case 4:
- /* update notification request */
- update_notify_request(q, r);
- break;
- }
-}
-
-/****************************************************************************
-do a switch on the message type, and return the response size
-****************************************************************************/
-static BOOL switch_message(GENERIC_PACKET *q, GENERIC_PACKET *r)
-{
- switch (q->header.mess_type) {
- case 0:
- /* Start association type */
- start_assoc_process(q, r);
- return True;
- break;
- case 1:
- /* start association reply */
- start_assoc_reply(q, r);
- return True;
- break;
- case 2:
- /* stop association message */
- return False;
- break;
- case 3:
- /* replication message */
- replicate(q, r);
- return True;
- break;
- }
-
- return False;
-}
-
-
-/****************************************************************************
- construct a reply to the incoming packet
-****************************************************************************/
-void construct_reply(struct wins_packet_struct *p)
-{
- GENERIC_PACKET r;
- struct BUFFER buffer;
-
- buffer.buffer=NULL;
- buffer.offset=0;
- buffer.length=0;
-
- DEBUG(5,("dump: received packet\n"));
- dump_generic_packet(p->packet);
-
- /* Verify if the request we got is from a listed partner */
- if (!check_partner(p->packet->header.assoc_ctx)) {
- fstring peer;
- struct in_addr addr;
- int i;
- fstrcpy(peer,get_peer_addr(p->fd));
- addr=*interpret_addr2(peer);
-
- for (i=1; i<partner_count; i++)
- if (ip_equal(addr, global_wins_table[0][i].address))
- break;
-
- if (i==partner_count) {
- DEBUG(1,("construct_reply: got a request from a non peer machine: %s\n", peer));
- stop_packet(p->packet, &r, STOP_REASON_AUTH_FAILED);
- p->stop_packet=True;
- encode_generic_packet(&buffer, &r);
- if (!send_smb(p->fd, buffer.buffer))
- exit_server("process_smb: send_smb failed.");
- return;
- }
- }
-
- if (switch_message(p->packet, &r)) {
- encode_generic_packet(&buffer, &r);
- DEBUG(5,("dump: sending packet\n"));
- dump_generic_packet(&r);
-
- if(buffer.offset > 0) {
- if (!send_smb(p->fd, buffer.buffer))
- exit_server("process_smb: send_smb failed.");
- }
- }
-
- /* if we got a stop assoc or if we send a stop assoc, close the fd after */
- if (p->packet->header.mess_type==MESSAGE_TYPE_STOP_ASSOC ||
- r.header.mess_type==MESSAGE_TYPE_STOP_ASSOC) {
- remove_partner(p->packet->header.assoc_ctx);
- p->stop_packet=True;
- }
-}
-
-/****************************************************************************
- contact periodically our wins partner to do a pull replication
-****************************************************************************/
-void run_pull_replication(time_t t)
-{
- /* we pull every 30 minutes to query about new records*/
- int i, s;
- struct BUFFER buffer;
- GENERIC_PACKET p;
-
- buffer.buffer=NULL;
- buffer.offset=0;
- buffer.length=0;
-
- for (i=1; i<partner_count; i++) {
- if (global_wins_table[0][i].last_pull < t) {
- global_wins_table[0][i].last_pull=t+30*60; /* next in 30 minutes */
-
- /* contact the wins server */
- p.header.mess_type=MESSAGE_TYPE_START_ASSOC_REQUEST;
- p.header.opcode=OPCODE_NON_NBT;
- p.header.assoc_ctx=0;
- p.sa_rq.assoc_ctx=(int)t;
- p.sa_rq.min_ver=1;
- p.sa_rq.maj_ver=1;
-
- DEBUG(3,("run_pull_replication: contacting wins server %s.\n", inet_ntoa(global_wins_table[0][i].address)));
- encode_generic_packet(&buffer, &p);
- dump_generic_packet(&p);
-
- /* send the packet to the server and add the descriptor to receive answers */
- s=open_socket_out(SOCK_STREAM, &global_wins_table[0][i].address, 42, LONG_CONNECT_TIMEOUT);
- if (s==-1) {
- DEBUG(0,("run_pull_replication: can't contact wins server %s.\n", inet_ntoa(global_wins_table[0][i].address)));
- return;
- }
-
- if(buffer.offset > 0) {
- if (!send_smb(s, buffer.buffer))
- exit_server("run_pull_replication: send_smb failed.");
- }
-
- add_fd_to_sock_array(s);
- FD_SET(s, listen_set);
-
- /* add ourself as a client */
- add_partner((int)t, 0, True, False);
- }
- }
-}
-
-/****************************************************************************
- contact periodically our wins partner to do a push replication
-****************************************************************************/
-void run_push_replication(time_t t)
-{
- /* we push every 30 minutes or 25 new entries */
- int i, s;
- struct BUFFER buffer;
- GENERIC_PACKET p;
-
- buffer.buffer=NULL;
- buffer.offset=0;
- buffer.length=0;
-
- for (i=1; i<partner_count; i++) {
- if (global_wins_table[0][i].last_pull < t) {
- global_wins_table[0][i].last_pull=t+30*60; /* next in 30 minutes */
-
- /* contact the wins server */
- p.header.mess_type=MESSAGE_TYPE_START_ASSOC_REQUEST;
- p.header.opcode=OPCODE_NON_NBT;
- p.header.assoc_ctx=0;
- p.sa_rq.assoc_ctx=(int)t;
- p.sa_rq.min_ver=1;
- p.sa_rq.maj_ver=1;
-
- DEBUG(3,("run_push_replication: contacting wins server %s.\n", inet_ntoa(global_wins_table[0][i].address)));
- encode_generic_packet(&buffer, &p);
- dump_generic_packet(&p);
-
- /* send the packet to the server and add the descriptor to receive answers */
- s=open_socket_out(SOCK_STREAM, &global_wins_table[0][i].address, 42, LONG_CONNECT_TIMEOUT);
- if (s==-1) {
- DEBUG(0,("run_push_replication: can't contact wins server %s.\n", inet_ntoa(global_wins_table[0][i].address)));
- return;
- }
-
- if(buffer.offset > 0) {
- if (!send_smb(s, buffer.buffer))
- exit_server("run_push_replication: send_smb failed.");
- }
-
- add_fd_to_sock_array(s);
- FD_SET(s, listen_set);
-
- /* add ourself as a client */
- add_partner((int)t, 0, False, True);
- }
- }
-}
-
diff --git a/source/wrepld/server.c b/source/wrepld/server.c
deleted file mode 100644
index 5ac78a24745..00000000000
--- a/source/wrepld/server.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Main SMB server routines
- Copyright (C) Jean François Micouleau 1998-2002.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "wins_repl.h"
-
-extern pstring user_socket_options;
-
-extern WINS_OWNER *global_wins_table;
-extern int partner_count;
-
-extern fd_set *listen_set;
-extern int listen_number;
-extern int *sock_array;
-
-extern TALLOC_CTX *mem_ctx;
-
-int wins_port = 42;
-
-/****************************************************************************
- when exiting, take the whole family
-****************************************************************************/
-static void *dflt_sig(void)
-{
- exit_server("caught signal");
- return NULL;
-}
-
-/****************************************************************************
- reload the services file
- **************************************************************************/
-BOOL reload_services(BOOL test)
-{
- BOOL ret;
-
- if (lp_loaded()) {
- pstring fname;
- pstrcpy(fname,lp_configfile());
- if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
- pstrcpy(dyn_CONFIGFILE,fname);
- test = False;
- }
- }
-
- reopen_logs();
-
- if (test && !lp_file_list_changed())
- return(True);
-
- ret = lp_load(dyn_CONFIGFILE,False,False,True);
-
-
- /* perhaps the config filename is now set */
- if (!test)
- reload_services(True);
-
- reopen_logs();
-
- load_interfaces();
-
- return(ret);
-}
-
-/****************************************************************************
- Catch a sighup.
-****************************************************************************/
-
-VOLATILE sig_atomic_t reload_after_sighup = False;
-
-static void sig_hup(int sig)
-{
- BlockSignals(True,SIGHUP);
- DEBUG(0,("Got SIGHUP\n"));
-
- sys_select_signal(SIGHUP);
- reload_after_sighup = True;
- BlockSignals(False,SIGHUP);
-}
-
-#if DUMP_CORE
-/*******************************************************************
-prepare to dump a core file - carefully!
-********************************************************************/
-static BOOL dump_core(void)
-{
- char *p;
- pstring dname;
- pstrcpy(dname,lp_logfile());
- if ((p=strrchr_m(dname,'/'))) *p=0;
- pstrcat(dname,"/corefiles");
- mkdir(dname,0700);
- sys_chown(dname,getuid(),getgid());
- chmod(dname,0700);
- if (chdir(dname)) return(False);
- umask(~(0700));
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
- {
- struct rlimit rlp;
- getrlimit(RLIMIT_CORE, &rlp);
- rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
- setrlimit(RLIMIT_CORE, &rlp);
- getrlimit(RLIMIT_CORE, &rlp);
- DEBUG(3,("Core limits now %d %d\n",
- (int)rlp.rlim_cur,(int)rlp.rlim_max));
- }
-#endif
-#endif
-
-
- DEBUG(0,("Dumping core in %s\n",dname));
- abort();
- return(True);
-}
-#endif
-
-/****************************************************************************
-exit the server
-****************************************************************************/
-void exit_server(const char *reason)
-{
- static int firsttime=1;
-
- if (!firsttime)
- exit(0);
- firsttime = 0;
-
- DEBUG(2,("Closing connections\n"));
-
- if (!reason) {
- int oldlevel = DEBUGLEVEL;
- DEBUGLEVEL = 10;
- DEBUGLEVEL = oldlevel;
- DEBUG(0,("===============================================================\n"));
-#if DUMP_CORE
- if (dump_core()) return;
-#endif
- }
-
- DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
- exit(0);
-}
-
-/****************************************************************************
- Create an fd_set containing all the sockets in the subnet structures,
- plus the broadcast sockets.
-***************************************************************************/
-
-static BOOL create_listen_fdset( int *maxfd)
-{
- int i;
- int num_interfaces = iface_count();
- int s;
-
- listen_set = (fd_set *)malloc(sizeof(fd_set));
- if(listen_set == NULL) {
- DEBUG(0,("create_listen_fdset: malloc fail !\n"));
- return True;
- }
-
-#ifdef HAVE_ATEXIT
- {
- static int atexit_set;
- if(atexit_set == 0) {
- atexit_set=1;
- }
- }
-#endif
-
- FD_ZERO(listen_set);
-
- if(lp_interfaces() && lp_bind_interfaces_only()) {
- /* We have been given an interfaces line, and been
- told to only bind to those interfaces. Create a
- socket per interface and bind to only these.
- */
-
- if(num_interfaces > FD_SETSIZE) {
- DEBUG(0,("create_listen_fdset: Too many interfaces specified to bind to. Number was %d max can be %d\n", num_interfaces, FD_SETSIZE));
- return False;
- }
-
- /* Now open a listen socket for each of the interfaces. */
- for(i = 0; i < num_interfaces; i++) {
- struct in_addr *ifip = iface_n_ip(i);
-
- if(ifip == NULL) {
- DEBUG(0,("create_listen_fdset: interface %d has NULL IP address !\n", i));
- continue;
- }
- s = open_socket_in(SOCK_STREAM, wins_port, 0, ifip->s_addr, True);
- if(s == -1)
- return False;
-
- /* ready to listen */
- set_socket_options(s,"SO_KEEPALIVE");
- set_socket_options(s,user_socket_options);
-
- if (listen(s, 5) == -1) {
- DEBUG(5,("listen: %s\n",strerror(errno)));
- close(s);
- return False;
- }
- add_fd_to_sock_array(s);
- FD_SET(s, listen_set);
- *maxfd = MAX( *maxfd, s);
- }
- } else {
- /* Just bind to 0.0.0.0 - accept connections from anywhere. */
- num_interfaces = 1;
-
- /* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, wins_port, 0, interpret_addr(lp_socket_address()),True);
- if (s == -1)
- return(False);
-
- /* ready to listen */
- set_socket_options(s,"SO_KEEPALIVE");
- set_socket_options(s,user_socket_options);
-
- if (listen(s, 5) == -1) {
- DEBUG(0,("create_listen_fdset: listen: %s\n", strerror(errno)));
- close(s);
- return False;
- }
-
- add_fd_to_sock_array(s);
- FD_SET(s, listen_set);
- *maxfd = MAX( *maxfd, s);
- }
-
- return True;
-}
-
-/*******************************************************************
- read a packet from a socket and parse it, returning a packet ready
- to be used or put on the queue. This assumes a UDP socket
- ******************************************************************/
-static struct wins_packet_struct *read_wins_packet(int fd, int timeout)
-{
- struct wins_packet_struct *p;
- GENERIC_PACKET *q;
- struct BUFFER inbuf;
- ssize_t len=0;
- size_t total=0;
- ssize_t ret;
- BOOL ok = False;
-
- inbuf.buffer=NULL;
- inbuf.length=0;
- inbuf.offset=0;
-
- if(!grow_buffer(&inbuf, 4))
- return NULL;
-
- ok = (read(fd, inbuf.buffer,4) == 4);
- if (!ok)
- return NULL;
- len = smb_len(inbuf.buffer);
-
- if (len<=0)
- return NULL;
-
- if(!grow_buffer(&inbuf, len))
- return NULL;
-
- while (total < len) {
- ret = read(fd, inbuf.buffer + total + 4, len - total);
- if (ret == 0) {
- DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(len - total), strerror(errno) ));
- return NULL;
- }
- if (ret == -1) {
- DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(len - total), strerror(errno) ));
- return NULL;
- }
- total += ret;
- }
-
- q = talloc(mem_ctx, GENERIC_PACKET);
- p = talloc(mem_ctx, struct wins_packet_struct);
- if (q==NULL || p==NULL)
- return NULL;
-
- decode_generic_packet(&inbuf, q);
-
- q->fd=fd;
-
- p->next = NULL;
- p->prev = NULL;
- p->stop_packet = False;
- p->timestamp = time(NULL);
- p->fd = fd;
- p->packet=q;
-
- return p;
-}
-
-static struct wins_packet_struct *packet_queue = NULL;
-
-/*******************************************************************
- Queue a packet into a packet queue
-******************************************************************/
-static void queue_packet(struct wins_packet_struct *packet)
-{
- struct wins_packet_struct *p;
-
- if (!packet_queue) {
- packet->prev = NULL;
- packet->next = NULL;
- packet_queue = packet;
- return;
- }
-
- /* find the bottom */
- for (p=packet_queue;p->next;p=p->next)
- ;
-
- p->next = packet;
- packet->next = NULL;
- packet->prev = p;
-}
-
-/****************************************************************************
- Listens for NMB or DGRAM packets, and queues them.
- return True if the socket is dead
-***************************************************************************/
-static BOOL listen_for_wins_packets(void)
-{
- int num_interfaces = iface_count();
- fd_set fds;
- int i, num, s, new_s;
- static int maxfd = 0;
- struct timeval timeout;
-
- if(listen_set == NULL) {
- if(!create_listen_fdset( &maxfd)) {
- DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
- return True;
- }
- }
-
- memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
-
- timeout.tv_sec = NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
-
- /* Prepare for the select - allow certain signals. */
-
- BlockSignals(False, SIGTERM);
-
- num = sys_select(maxfd+1, &fds, NULL, NULL, &timeout);
-
- /* We can only take signals when we are in the select - block them again here. */
-
- BlockSignals(True, SIGTERM);
-
- if(num == -1)
- return False;
-
- for (; num > 0; num--) {
- s = -1;
- /* check the sockets we are only listening on, waiting to accept */
- for (i=0; i<num_interfaces; i++) {
- struct sockaddr addr;
- socklen_t in_addrlen = sizeof(addr);
-
- if(FD_ISSET(sock_array[i], &fds)) {
- s = sock_array[i];
- /* Clear this so we don't look at it again. */
- FD_CLR(sock_array[i], &fds);
-
- /* accept and add the new socket to the listen set */
- new_s=accept(s, &addr, &in_addrlen);
-
- if (new_s < 0)
- continue;
-
- DEBUG(5,("listen_for_wins_packets: new connection, old: %d, new : %d\n", s, new_s));
-
- set_socket_options(new_s, "SO_KEEPALIVE");
- set_socket_options(new_s, user_socket_options);
- FD_SET(new_s, listen_set);
- add_fd_to_sock_array(new_s);
- maxfd = MAX( maxfd, new_s);
- }
- }
-
- /*
- * check for the sockets we are waiting data from
- * either client sending datas
- * or reply to our requests
- */
- for (i=num_interfaces; i<listen_number; i++) {
- if(FD_ISSET(sock_array[i], &fds)) {
- struct wins_packet_struct *packet = read_wins_packet(sock_array[i], timeout.tv_sec);
- if (packet) {
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- DEBUG(2,("listen_for_wins_packets: some data on fd %d\n", sock_array[i]));
- FD_CLR(sock_array[i], &fds);
- break;
- }
-
- }
-
- }
-
- return False;
-}
-
-
-/*******************************************************************
- Run elements off the packet queue till its empty
-******************************************************************/
-
-static void run_wins_packet_queue(void)
-{
- struct wins_packet_struct *p;
-
- while ((p = packet_queue)) {
- packet_queue = p->next;
- if (packet_queue)
- packet_queue->prev = NULL;
- p->next = p->prev = NULL;
-
- construct_reply(p);
-
- /* if it was a stop assoc, close the connection */
- if (p->stop_packet) {
- FD_CLR(p->fd, listen_set);
- remove_fd_from_sock_array(p->fd);
- close(p->fd);
- }
- }
-}
-
-/**************************************************************************** **
- The main select loop.
- **************************************************************************** */
-static void process(void)
-{
-
- while( True ) {
- time_t t = time(NULL);
-
- /* check for internal messages */
- message_dispatch();
-
- if(listen_for_wins_packets())
- return;
-
- run_wins_packet_queue();
-
- run_pull_replication(t);
-
- run_push_replication(t);
-
- /*
- * Reload the services file if we got a sighup.
- */
-
- if(reload_after_sighup) {
- reload_services( True );
- reopen_logs();
- reload_after_sighup = False;
- }
-
- /* free temp memory */
- talloc_free_children(mem_ctx);
-
- /* free up temp memory */
- lp_talloc_free();
- }
-} /* process */
-
-/****************************************************************************
- main program
-****************************************************************************/
- int main(int argc,char *argv[])
-{
- /* shall I run as a daemon */
- static BOOL is_daemon = False;
- static BOOL interactive = False;
- static BOOL Fork = True;
- static BOOL log_stdout = False;
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" },
- { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc)" },
- { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
- { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Run interactive (not a daemon)" },
- { "port", 'p', POPT_ARG_INT, &wins_port, 'p', "Listen on the specified port" },
- POPT_COMMON_SAMBA
- POPT_TABLEEND
- };
- int opt;
- poptContext pc;
-
-#ifdef HAVE_SET_AUTH_PARAMETERS
- set_auth_parameters(argc,argv);
-#endif
-
- pc = poptGetContext("wrepld", argc, (const char **)argv, long_options,
- POPT_CONTEXT_KEEP_FIRST);
-
- while ((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- case 'i':
- interactive = True;
- Fork = False;
- log_stdout = True;
- break;
- }
- }
-
-
- if (log_stdout && Fork) {
- d_printf("Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n");
- poptPrintUsage(pc, stderr, 0);
- exit(1);
- }
-
-#ifdef HAVE_SETLUID
- /* needed for SecureWare on SCO */
- setluid(0);
-#endif
-
- sec_init();
-
- load_case_tables();
-
- set_remote_machine_name("wrepld", False);
-
- setup_logging(argv[0],log_stdout);
-
- /* we want to re-seed early to prevent time delays causing
- client problems at a later date. (tridge) */
- generate_random_buffer(NULL, 0);
-
- /* make absolutely sure we run as root - to handle cases where people
- are crazy enough to have it setuid */
-
- gain_root_privilege();
- gain_root_group_privilege();
-
- fault_setup((void (*)(void *))exit_server);
- CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig);
-
- /* we are never interested in SIGPIPE */
- BlockSignals(True,SIGPIPE);
-
-#if defined(SIGFPE)
- /* we are never interested in SIGFPE */
- BlockSignals(True,SIGFPE);
-#endif
-
-#if defined(SIGUSR2)
- /* We are no longer interested in USR2 */
- BlockSignals(True,SIGUSR2);
-#endif
-
- /* POSIX demands that signals are inherited. If the invoking process has
- * these signals masked, we will have problems, as we won't recieve them. */
- BlockSignals(False, SIGHUP);
- BlockSignals(False, SIGUSR1);
-
- /* we want total control over the permissions on created files,
- so set our umask to 0 */
- umask(0);
-
- reopen_logs();
-
- DEBUG(0,( "wrepld version %s started.\n", SAMBA_VERSION_STRING));
- DEBUGADD( 0, ( "%s\n", COPYRIGHT_STARTUP_MESSAGE ) );
-
- DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
- (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
-
- if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
- DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
- exit(1);
- }
-
- /*
- * Do this before reload_services.
- */
-
- if (!reload_services(False))
- return(-1);
-
- if (!init_names())
- return -1;
-
-#ifdef WITH_PROFILE
- if (!profile_setup(False)) {
- DEBUG(0,("ERROR: failed to setup profiling\n"));
- return -1;
- }
-#endif
-
- CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
-
- DEBUG(3,( "loaded services\n"));
-
- if (!is_daemon && !is_a_socket(0)) {
- DEBUG(0,("standard input is not a socket, assuming -D option\n"));
- is_daemon = True;
- }
-
- if (is_daemon && !interactive) {
- DEBUG( 3, ( "Becoming a daemon.\n" ) );
- become_daemon(Fork);
- }
-
-#if HAVE_SETPGID
- /*
- * If we're interactive we want to set our own process group for
- * signal management.
- */
- if (interactive)
- setpgid( (pid_t)0, (pid_t)0);
-#endif
-
- if (!directory_exist(lp_lockdir(), NULL)) {
- mkdir(lp_lockdir(), 0755);
- }
-
- if (is_daemon) {
- pidfile_create("wrepld");
- }
-
- if (!message_init()) {
- exit(1);
- }
-
- /* Initialise the memory context */
- mem_ctx=talloc_init("wins repl talloc ctx");
-
- /* initialise the global partners table */
- partner_count=init_wins_partner_table();
-
- /* We can only take signals in the select. */
- BlockSignals( True, SIGTERM );
-
- process();
-
- poptFreeContext(pc);
- exit_server("normal exit");
- return(0);
-}
diff --git a/source/wrepld/socket.c b/source/wrepld/socket.c
deleted file mode 100644
index 3d759f0ab89..00000000000
--- a/source/wrepld/socket.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- process incoming packets - main loop
- Copyright (C) Jean François Micouleau 1998-2002.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "wins_repl.h"
-
-fd_set *listen_set = NULL;
-int listen_number = 0;
-int *sock_array = NULL;
-
-/*******************************************************************
- Add an fd from the sock_array
-******************************************************************/
-void add_fd_to_sock_array(int fd)
-{
- int *temp_sock=NULL;
-
- temp_sock=(int *)Realloc(sock_array, (listen_number+1)*sizeof(int));
- if (temp_sock==NULL)
- return;
-
- sock_array=temp_sock;
- sock_array[listen_number]=fd;
- listen_number++;
-}
-
-
-/*******************************************************************
- Remove an fd from the sock_array
-******************************************************************/
-void remove_fd_from_sock_array(int fd)
-{
- int i,j;
-
- for (i=0; sock_array[i]!=fd && i<listen_number; i++)
- ;
-
- if (i==listen_number) {
- DEBUG(0,("remove_fd_from_sock_array: unknown fd: %d\n", fd));
- return;
- }
-
- if (i==listen_number-1) {
- sock_array=(int *)Realloc(sock_array, --listen_number*sizeof(int));
- return;
- }
-
- for (j=i; j<listen_number-1; j++)
- sock_array[j]=sock_array[j+1];
-
- sock_array=(int *)Realloc(sock_array, --listen_number*sizeof(int));
-}
diff --git a/source/wrepld/wins_repl.h b/source/wrepld/wins_repl.h
deleted file mode 100644
index 25b44422121..00000000000
--- a/source/wrepld/wins_repl.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * RPC Pipe client / server routines
- * Copyright (C) Jean François Micouleau 1998-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.
- */
-
-#define OPCODE_NON_NBT 0x00007800
-
-/* the messages */
-#define MESSAGE_TYPE_START_ASSOC_REQUEST 0
-#define MESSAGE_TYPE_START_ASSOC_REPLY 1
-#define MESSAGE_TYPE_STOP_ASSOC 2
-#define MESSAGE_TYPE_REPLICATE 3
-
-/* the replication sub-message */
-#define MESSAGE_REP_ADD_VERSION_REQUEST 0
-#define MESSAGE_REP_ADD_VERSION_REPLY 1
-#define MESSAGE_REP_SEND_ENTRIES_REQUEST 2
-#define MESSAGE_REP_SEND_ENTRIES_REPLY 3
-#define MESSAGE_REP_UPDATE_NOTIFY_REQUEST 4
-
-/* stop reasons */
-#define STOP_REASON_USER_REASON 0
-#define STOP_REASON_AUTH_FAILED 1
-#define STOP_REASON_INCOMPLETE_VERSION 2
-#define STOP_REASON_BUG_CHECK 3
-#define STOP_REASON_MESSAGE_ERROR 4
-
-
-typedef struct _WINS_OWNER {
- struct in_addr address;
- SMB_BIG_UINT max_version;
- SMB_BIG_UINT min_version;
- int type;
- time_t last_pull;
- time_t last_push;
-} WINS_OWNER;
-
-typedef struct _WINS_NAME {
- int name_len; /* always 0x11 */
- char name[16];
- char type;
- int empty;
- int name_flag;
- int group_flag;
- SMB_BIG_UINT id;
- int num_ip;
- struct in_addr owner;
- struct in_addr *others;
- int foo; /* 0xffffff */
-} WINS_NAME;
-
-typedef struct _WINS_PARTNERS
-{
- int client_assoc;
- int server_assoc;
- BOOL pull_partner;
- BOOL push_partner;
- struct in_addr partner_server;
- struct in_addr other_server;
-} WINS_PARTNER;
-
-typedef struct _generic_header{
- int data_size;
- int opcode;
- int assoc_ctx;
- int mess_type;
-} generic_header;
-
-typedef struct _START_ASSOC_REQUEST {
- int assoc_ctx;
- int min_ver;
- int maj_ver;
-} START_ASSOC_REQUEST;
-
-typedef struct _START_ASSOC_REPLY {
- int assoc_ctx;
- int min_ver;
- int maj_ver;
-} START_ASSOC_REPLY;
-
-typedef struct _STOP_ASSOC {
- int reason;
-} STOP_ASSOC;
-
-typedef struct _AVMT_REP {
- int partner_count;
- WINS_OWNER *wins_owner;
- struct in_addr initiating_wins_server;
-} AVMT_REP;
-
-typedef struct _SEND_ENTRIES_REQUEST {
- WINS_OWNER wins_owner;
-} SEND_ENTRIES_REQUEST;
-
-typedef struct _SEND_ENTRIES_REPLY {
- int max_names;
- WINS_NAME *wins_name;
-} SEND_ENTRIES_REPLY;
-
-typedef struct _UPDATE_NOTIFY_REQUEST {
- int partner_count;
- WINS_OWNER *wins_owner;
- struct in_addr initiating_wins_server;
-} UPDATE_NOTIFY_REQUEST;
-
-typedef struct _REPLICATE {
- int msg_type;
-
- AVMT_REP avmt_rep;
- SEND_ENTRIES_REQUEST se_rq;
- SEND_ENTRIES_REPLY se_rp;
- UPDATE_NOTIFY_REQUEST un_rq;
-} REPLICATE;
-
-
-typedef struct _GENERIC_PACKET {
- int fd;
-
- generic_header header;
-
- START_ASSOC_REQUEST sa_rq;
- START_ASSOC_REPLY sa_rp;
- STOP_ASSOC so;
- REPLICATE rep;
-} GENERIC_PACKET;
-
-struct wins_packet_struct
-{
- struct wins_packet_struct *next;
- struct wins_packet_struct *prev;
- BOOL stop_packet;
- int fd;
- time_t timestamp;
- GENERIC_PACKET *packet;
-};
-
-struct BUFFER {
- char *buffer;
- int offset;
- int length;
-};
-
-
-
-#include "wrepld_proto.h"
-
diff --git a/testsuite/nsswitch/pam_winbind_syms.exp b/testsuite/nsswitch/pam_winbind_syms.exp
index f95274cdd9d..7c85a2d24d3 100644
--- a/testsuite/nsswitch/pam_winbind_syms.exp
+++ b/testsuite/nsswitch/pam_winbind_syms.exp
@@ -29,7 +29,7 @@ if {$output != ""} {
# Run load-dl.c
set output [util_start "$srcdir/$subdir/pam_winbind_syms" \
- "nsswitch/pam_winbind.so"]
+ "bin/pam_winbind.so"]
if {[regexp "FAIL:" $output]} {
fail "run pam_winbind_syms"