summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-05-23 15:21:55 +0000
committerGerald Carter <jerry@samba.org>2006-05-23 15:21:55 +0000
commit3f7bb704a9e62e7a46a05838ec9300c2f6916c16 (patch)
treee2ca7f1b8da68d725e5359d7746f391fedcad6be
parent34b471724d1c8eb9e020fce02fc538bd0993d1c4 (diff)
downloadsamba-3f7bb704a9e62e7a46a05838ec9300c2f6916c16.tar.gz
r15837: starting sync up for 3.0.23rc1 (in sync with SAMBA_3_0 r15822)
-rwxr-xr-xexamples/misc/adssearch.pl2
-rw-r--r--packaging/RHEL/samba.spec.tmpl4
-rw-r--r--packaging/RedHat-9/samba.spec.tmpl1
-rw-r--r--source/Makefile.in39
-rw-r--r--source/VERSION4
-rw-r--r--source/aclocal.m456
-rw-r--r--source/auth/auth.c2
-rw-r--r--source/auth/auth_domain.c5
-rw-r--r--source/auth/auth_ntlmssp.c5
-rw-r--r--source/auth/auth_rhosts.c293
-rw-r--r--source/auth/auth_sam.c2
-rw-r--r--source/auth/auth_script.c9
-rw-r--r--source/auth/auth_util.c71
-rw-r--r--source/auth/auth_winbind.c4
-rw-r--r--source/client/smbctool.c4
-rw-r--r--source/client/smbspool.c3
-rw-r--r--source/configure.in153
-rw-r--r--source/include/ads.h78
-rw-r--r--source/include/ads_cldap.h58
-rw-r--r--source/include/ads_dns.h54
-rw-r--r--source/include/auth.h2
-rw-r--r--source/include/includes.h70
-rw-r--r--source/include/messages.h1
-rw-r--r--source/include/rpc_samr.h113
-rw-r--r--source/include/smb.h5
-rw-r--r--source/include/smbprofile.h92
-rw-r--r--source/lib/fault.c9
-rw-r--r--source/lib/iconv.c2
-rw-r--r--source/lib/module.c8
-rw-r--r--source/lib/smbldap.c25
-rw-r--r--source/lib/substitute.c2
-rw-r--r--source/lib/sysacls.c1
-rw-r--r--source/lib/time.c6
-rw-r--r--source/lib/util.c28
-rw-r--r--source/lib/util_sid.c20
-rw-r--r--source/lib/util_sock.c9
-rw-r--r--source/lib/util_str.c18
-rw-r--r--source/libads/ads_ldap.c104
-rw-r--r--source/libads/ads_struct.c16
-rw-r--r--source/libads/cldap.c (renamed from source/utils/net_ads_cldap.c)147
-rw-r--r--source/libads/dns.c371
-rw-r--r--source/libads/kerberos.c54
-rw-r--r--source/libads/kerberos_keytab.c22
-rw-r--r--source/libads/kerberos_verify.c27
-rw-r--r--source/libads/krb5_errs.c2
-rw-r--r--source/libads/krb5_setpw.c6
-rw-r--r--source/libads/ldap.c974
-rw-r--r--source/libads/ldap_schema.c329
-rw-r--r--source/libads/ldap_utils.c88
-rw-r--r--source/libads/sasl.c2
-rw-r--r--source/libsmb/cliconnect.c28
-rw-r--r--source/libsmb/clikrb5.c200
-rw-r--r--source/libsmb/namequery.c100
-rw-r--r--source/libsmb/nmblib.c2
-rw-r--r--source/libsmb/samlogon_cache.c3
-rw-r--r--source/locking/brlock.c109
-rw-r--r--source/locking/locking.c24
-rw-r--r--source/nmbd/nmbd.c4
-rw-r--r--source/nmbd/nmbd_elections.c10
-rw-r--r--source/nmbd/nmbd_incomingdgrams.c4
-rw-r--r--source/nmbd/nmbd_responserecordsdb.c2
-rw-r--r--source/nmbd/nmbd_serverlistdb.c2
-rw-r--r--source/nmbd/nmbd_subnetdb.c6
-rw-r--r--source/nmbd/nmbd_workgroupdb.c2
-rw-r--r--source/nsswitch/pam_winbind.c83
-rw-r--r--source/nsswitch/pam_winbind.h2
-rw-r--r--source/nsswitch/wbinfo.c40
-rw-r--r--source/nsswitch/winbind_nss_aix.c3
-rw-r--r--source/nsswitch/winbind_nss_config.h1
-rw-r--r--source/nsswitch/winbind_nss_irix.c260
-rw-r--r--source/nsswitch/winbindd.c11
-rw-r--r--source/nsswitch/winbindd.h4
-rw-r--r--source/nsswitch/winbindd_ads.c225
-rw-r--r--source/nsswitch/winbindd_cache.c20
-rw-r--r--source/nsswitch/winbindd_cm.c9
-rw-r--r--source/nsswitch/winbindd_cred_cache.c69
-rw-r--r--source/nsswitch/winbindd_dual.c76
-rw-r--r--source/nsswitch/winbindd_nss.h2
-rw-r--r--source/nsswitch/winbindd_pam.c24
-rw-r--r--source/nsswitch/winbindd_rpc.c22
-rw-r--r--source/nsswitch/winbindd_user.c2
-rw-r--r--source/nsswitch/winbindd_util.c49
-rw-r--r--source/pam_smbpass/general.h4
-rw-r--r--source/pam_smbpass/support.c8
-rw-r--r--source/param/loadparm.c92
-rw-r--r--source/passdb/lookup_sid.c29
-rw-r--r--source/passdb/passdb.c3
-rw-r--r--source/passdb/pdb_get_set.c15
-rw-r--r--source/passdb/pdb_interface.c2
-rw-r--r--source/passdb/pdb_ldap.c53
-rw-r--r--source/passdb/pdb_nds.c2
-rw-r--r--source/popt/CHANGES5
-rw-r--r--source/popt/README2
-rw-r--r--source/popt/findme.c30
-rw-r--r--source/popt/findme.h16
-rw-r--r--source/popt/popt.c1062
-rw-r--r--source/popt/popt.h589
-rw-r--r--source/popt/poptconfig.c182
-rw-r--r--source/popt/popthelp.c703
-rw-r--r--source/popt/poptint.h103
-rw-r--r--source/popt/poptparse.c165
-rw-r--r--source/popt/system.h25
-rw-r--r--source/printing/nt_printing.c23
-rw-r--r--source/profile/profile.c34
-rw-r--r--source/python/py_common.c6
-rw-r--r--source/python/py_lsa.c6
-rw-r--r--source/python/py_lsa.h2
-rw-r--r--source/python/py_samr.c10
-rw-r--r--source/python/py_samr.h6
-rw-r--r--source/python/py_spoolss_drivers.c6
-rw-r--r--source/python/py_spoolss_ports.c2
-rw-r--r--source/python/py_spoolss_printerdata.c7
-rw-r--r--source/python/py_spoolss_printers.c6
-rw-r--r--source/python/py_srvsvc.c2
-rw-r--r--source/python/py_tdb.c2
-rw-r--r--source/rpc_client/cli_samr.c48
-rw-r--r--source/rpc_parse/parse_samr.c426
-rw-r--r--source/rpc_server/srv_eventlog_lib.c2
-rw-r--r--source/rpc_server/srv_reg_nt.c2
-rw-r--r--source/rpc_server/srv_samr.c19
-rw-r--r--source/rpc_server/srv_samr_nt.c161
-rw-r--r--source/rpc_server/srv_spoolss_nt.c32
-rw-r--r--source/rpcclient/cmd_lsarpc.c3
-rw-r--r--source/rpcclient/cmd_samr.c62
-rw-r--r--source/rpcclient/rpcclient.c5
-rw-r--r--source/sam/idmap.c2
-rw-r--r--source/sam/idmap_ad.c101
-rw-r--r--source/sam/idmap_util.c14
-rw-r--r--source/sam/nss_info.c111
-rwxr-xr-xsource/script/installswat.sh25
-rw-r--r--source/script/mkbuildoptions.awk23
-rwxr-xr-xsource/script/tests/selftest.sh10
-rwxr-xr-xsource/script/tests/test_posix_s3.sh8
-rw-r--r--source/smbd/close.c140
-rw-r--r--source/smbd/dir.c2
-rw-r--r--source/smbd/fake_file.c6
-rw-r--r--source/smbd/files.c28
-rw-r--r--source/smbd/ipc.c4
-rw-r--r--source/smbd/msdfs.c5
-rw-r--r--source/smbd/notify.c14
-rw-r--r--source/smbd/notify_hash.c20
-rw-r--r--source/smbd/nttrans.c31
-rw-r--r--source/smbd/open.c2
-rw-r--r--source/smbd/oplock.c44
-rw-r--r--source/smbd/oplock_irix.c13
-rw-r--r--source/smbd/oplock_linux.c7
-rw-r--r--source/smbd/password.c10
-rw-r--r--source/smbd/process.c1
-rw-r--r--source/smbd/reply.c15
-rw-r--r--source/smbd/server.c2
-rw-r--r--source/smbd/service.c41
-rw-r--r--source/smbd/sesssetup.c93
-rw-r--r--source/smbd/share_access.c3
-rw-r--r--source/smbd/trans2.c41
-rw-r--r--source/smbd/vfs-wrap.c2
-rw-r--r--source/smbd/vfs.c2
-rw-r--r--source/tdb/spinlock.c9
-rw-r--r--source/torture/msgtest.c57
-rw-r--r--source/utils/net.c74
-rw-r--r--source/utils/net.h29
-rw-r--r--source/utils/net_ads.c622
-rw-r--r--source/utils/net_domain.c338
-rw-r--r--source/utils/net_help.c3
-rw-r--r--source/utils/net_lookup.c72
-rw-r--r--source/utils/net_rpc.c16
-rw-r--r--source/utils/net_rpc_join.c8
-rw-r--r--source/utils/net_rpc_rights.c2
-rw-r--r--source/utils/net_rpc_samsync.c32
-rw-r--r--source/utils/net_sam.c9
-rw-r--r--source/utils/net_usershare.c50
-rw-r--r--source/utils/ntlm_auth.c2
-rw-r--r--source/utils/smbcontrol.c218
-rw-r--r--source/utils/smbpasswd.c2
-rw-r--r--source/utils/smbtree.c57
-rw-r--r--source/utils/status.c1
-rw-r--r--source/utils/testparm.c9
-rw-r--r--source/web/swat.c2
177 files changed, 7687 insertions, 3505 deletions
diff --git a/examples/misc/adssearch.pl b/examples/misc/adssearch.pl
index 3651564ec22..a26bb3b6c45 100755
--- a/examples/misc/adssearch.pl
+++ b/examples/misc/adssearch.pl
@@ -436,6 +436,7 @@ my %attr_handler = (
"modifyTimeStamp" => \&dump_timestr,
"msDS-Behavior-Version" => \&dump_ds_func, #unsure
"msDS-User-Account-Control-Computed" => \&dump_uacc,
+ "mS-DS-CreatorSID" => \&dump_sid,
# "msRADIUSFramedIPAddress" => \&dump_ipaddr,
# "msRASSavedFramedIPAddress" => \&dump_ipaddr,
"netbootGUID" => \&dump_guid,
@@ -457,6 +458,7 @@ my %attr_handler = (
"systemFlags" => \&dump_systemflags,
"tokenGroups", => \&dump_sid,
"tokenGroupsGlobalAndUniversal" => \&dump_sid,
+ "tokenGroupsNoGCAcceptable" => \&dump_sid,
"trustAttributes" => \&dump_trustattr,
"trustDirection" => \&dump_trustdirection,
"trustType" => \&dump_trusttype,
diff --git a/packaging/RHEL/samba.spec.tmpl b/packaging/RHEL/samba.spec.tmpl
index 70501db7ae7..26d8a669367 100644
--- a/packaging/RHEL/samba.spec.tmpl
+++ b/packaging/RHEL/samba.spec.tmpl
@@ -27,7 +27,7 @@ Provides: samba = %{version}
Prefix: /usr
BuildRoot: %{_tmppath}/%{name}-%{version}-root
-BuildRequires: pam-devel, readline-devel, fileutils, libacl-devel, openldap2-devel, krb5-devel, cups-devel
+BuildRequires: pam-devel, readline-devel, fileutils, libacl-devel, openldap-devel, krb5-devel, cups-devel
# Working around perl dependency problem from docs
%define __perl_requires %{SOURCE998}
@@ -112,7 +112,7 @@ cd source
# RPM_OPT_FLAGS="$RPM_OPT_FLAGS -D_FILE_OFFSET_BITS=64"
## check for ccache
-ccache -h 2>&1 > /dev/null
+# ccache -h 2>&1 > /dev/null
#if [ $? -eq 0 ]; then
# CC="ccache gcc"
#else
diff --git a/packaging/RedHat-9/samba.spec.tmpl b/packaging/RedHat-9/samba.spec.tmpl
index 927f8f2b1ba..34e3d1e5161 100644
--- a/packaging/RedHat-9/samba.spec.tmpl
+++ b/packaging/RedHat-9/samba.spec.tmpl
@@ -449,6 +449,7 @@ fi
%{prefix}/lib/libmsrpc.a
%{prefix}/lib/libmsrpc.so
%{prefix}/share/swat/help/*
+%{prefix}/share/swat/using_samba/*
%{prefix}/share/swat/include/*.html
%{prefix}/share/swat/lang/*/help/*
%config(noreplace) /etc/samba/lmhosts
diff --git a/source/Makefile.in b/source/Makefile.in
index 27753dd0721..effd438defe 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -18,7 +18,7 @@ LIBS=@LIBS@
CC=@CC@
SHLD=@SHLD@
CFLAGS=@CFLAGS@
-CPPFLAGS=@CPPFLAGS@
+CPPFLAGS=-DHAVE_CONFIG_H @CPPFLAGS@
EXEEXT=@EXEEXT@
LDFLAGS=@LDFLAGS@
AR=@AR@
@@ -156,7 +156,7 @@ BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@
EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ bin/talloctort@EXEEXT@ \
bin/log2pcap@EXEEXT@
-SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ @LIBSMBSHAREMODES@ cac
+SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ @LIBSMBSHAREMODES@ @LIBMSRPC@
PAM_MODULES = @PAM_MODULES@
@@ -241,14 +241,15 @@ LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
libads/krb5_setpw.o libads/ldap_user.o \
libads/ads_struct.o libads/kerberos_keytab.o \
libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
- libads/ads_ldap.o libads/authdata.o
+ libads/authdata.o libads/cldap.o
-LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o
+LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o \
+ libads/ldap_schema.o sam/nss_info.o
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
+ libsmb/namequery.o libsmb/conncache.o libads/dns.o
LIBSAMBA_OBJ = libsmb/nterr.o libsmb/dcerpc_err.o libsmb/smbdes.o \
libsmb/smbencrypt.o libsmb/ntlm_check.o \
@@ -383,7 +384,6 @@ DCUTIL_OBJ = libsmb/namequery_dc.o libsmb/trustdom_cache.o libsmb/trusts_util.o
AUTH_BUILTIN_OBJ = auth/auth_builtin.o
AUTH_DOMAIN_OBJ = auth/auth_domain.o
AUTH_SAM_OBJ = auth/auth_sam.o
-AUTH_RHOSTS_OBJ = auth/auth_rhosts.o
AUTH_SERVER_OBJ = auth/auth_server.o
AUTH_UNIX_OBJ = auth/auth_unix.o
AUTH_WINBIND_OBJ = auth/auth_winbind.o
@@ -478,7 +478,10 @@ SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) \
- $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ)
+ $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) \
+ rpc_client/cli_srvsvc.o rpc_parse/parse_srv.o \
+ rpc_client/cli_pipe.o rpc_parse/parse_rpc.o \
+ rpc_client/cli_netlogon.o rpc_parse/parse_net.o
TESTPARM_OBJ = utils/testparm.o \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
@@ -567,7 +570,7 @@ TOOL_OBJ = client/smbctool.o client/clitar.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
$(READLINE_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ)
-NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
+NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_domain.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
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 \
@@ -591,9 +594,9 @@ CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
MOUNT_OBJ = client/smbmount.o \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
-MNT_OBJ = client/smbmnt.o lib/replace.o $(VERSION_OBJ) $(SNPRINTF_OBJ)
+MNT_OBJ = client/smbmnt.o lib/replace.o $(VERSION_OBJ) $(SNPRINTF_OBJ) @SOCKWRAP@
-UMOUNT_OBJ = client/smbumount.o
+UMOUNT_OBJ = client/smbumount.o @SOCKWRAP@
CIFS_MOUNT_OBJ = client/mount.cifs.o
@@ -690,7 +693,6 @@ WINBIND_WINS_NSS_PICOBJS = $(WINBIND_WINS_NSS_OBJ:.o=.@PICSUFFIX@)
PICOBJS = $(SMBWRAPPER_OBJ:.o=.@PICSUFFIX@)
LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@)
LIBSMBSHAREMODES_PICOBJS = $(LIBSMBSHAREMODES_OBJ:.o=.@PICSUFFIX@)
-
CAC_PICOBJS = $(CAC_OBJ:.o=.@PICSUFFIX@)
@@ -759,7 +761,7 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \
libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
- $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o
+ $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o $(LIBNMB_OBJ)
######################################################################
# now the rules...
@@ -810,7 +812,7 @@ wins : SHOWFLAGS @WINBIND_WINS_NSS@
modules: SHOWFLAGS proto_exists $(MODULES)
-cac: SHOWFLAGS bin/libmsrpc.@SHLIBEXT@ bin/libmsrpc.a
+cac: SHOWFLAGS $(LIBMSRPC)
everything: all libsmbclient debug2html smbfilter talloctort modules torture \
$(EVERYTHING_PROGS)
@@ -975,9 +977,9 @@ bin/smbstatus@EXEEXT@: $(STATUS_OBJ) @BUILD_POPT@ bin/.dummy
bin/smbcontrol@EXEEXT@: $(SMBCONTROL_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) -DUSING_SMBCONTROL $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBCONTROL_OBJ) $(DYNEXP) \
- $(LDFLAGS) $(LIBS) \
- @POPTLIBS@
+ @$(CC) -DUSING_SMBCONTROL $(FLAGS) @PIE_LDFLAGS@ -o $@ \
+ $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \
+ $(LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@
bin/smbtree@EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -1126,6 +1128,7 @@ bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS)
libsmbclient: $(LIBSMBCLIENT)
libsmbsharemodes: $(LIBSMBSHAREMODES)
+libmsrpc: $(LIBMSRPC)
bin/librpc_lsarpc.@SHLIBEXT@: $(RPC_LSA_OBJ)
@echo "Linking $@"
@@ -1216,10 +1219,6 @@ bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_PICOBJ) bin/.dummy
@$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_PICOBJ) \
@SONAMEFLAG@`basename $@` -lpam @INIPARSERLIBS@
-bin/rhosts.@SHLIBEXT@: $(AUTH_RHOSTS_OBJ:.o=.@PICSUFFIX@)
- @echo "Building plugin $@"
- @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_RHOSTS_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
-
bin/builtin.@SHLIBEXT@: $(AUTH_BUILTIN_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_BUILTIN_OBJ:.o=.@PICSUFFIX@) @SONAMEFLAG@`basename $@`
diff --git a/source/VERSION b/source/VERSION
index eed177544cf..e9820322647 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -47,7 +47,7 @@ SAMBA_VERSION_REVISION=
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=1
+SAMBA_VERSION_PRE_RELEASE=
########################################################
# For 'rc' releases the version will be #
@@ -57,7 +57,7 @@ SAMBA_VERSION_PRE_RELEASE=1
# e.g. SAMBA_VERSION_RC_RELEASE=1 #
# -> "3.0.0rc1" #
########################################################
-SAMBA_VERSION_RC_RELEASE=
+SAMBA_VERSION_RC_RELEASE=1
########################################################
# To mark SVN snapshots this should be set to 'yes' #
diff --git a/source/aclocal.m4 b/source/aclocal.m4
index 86c43f80dc0..459e4d5c7a0 100644
--- a/source/aclocal.m4
+++ b/source/aclocal.m4
@@ -57,6 +57,7 @@ AC_DEFUN(SMB_MODULE,
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();"
+ [decl_static_modules_]translit([$4], [A-Z], [a-z])="$[decl_static_modules_]translit([$4], [A-Z], [a-z]) extern NTSTATUS $1_init(void);"
string_static_modules="$string_static_modules $1"
$4_STATIC="$$4_STATIC $2"
AC_SUBST($4_STATIC)
@@ -73,6 +74,7 @@ AC_DEFUN(SMB_SUBSYSTEM,
AC_SUBST($1_STATIC)
AC_SUBST($1_MODULES)
AC_DEFINE_UNQUOTED([static_init_]translit([$1], [A-Z], [a-z]), [{$init_static_modules_]translit([$1], [A-Z], [a-z])[}], [Static init functions])
+ AC_DEFINE_UNQUOTED([static_decl_]translit([$1], [A-Z], [a-z]), [$decl_static_modules_]translit([$1], [A-Z], [a-z]), [Decl of Static init functions])
ifelse([$2], , :, [rm -f $2])
])
@@ -102,20 +104,32 @@ AC_DEFUN(AC_HAVE_DECL,
])
-dnl Check for a function in a library, but don't
-dnl keep adding the same library to the LIBS variable.
-dnl Check whether the function is available in the current
-dnl LIBS before adding the library. This prevents us spuriously
-dnl finding symbols that are in libc.
-dnl AC_LIBTESTFUNC(lib,func)
+dnl Check for a function in a library, but don't keep adding the same library
+dnl to the LIBS variable. Check whether the function is available in the
+dnl current LIBS before adding the library which prevents us spuriously
+dnl adding libraries for symbols that are in libc. On success, this ensures that
+dnl HAVE_FOO is defined.
+AC_LIBTESTFUNC(lib,func)
AC_DEFUN(AC_LIBTESTFUNC,
[
- AC_CHECK_FUNCS($2, [],
- [ case "$LIBS" in
- *-l$1*) AC_CHECK_FUNCS($2) ;;
- *) AC_CHECK_LIB($1, $2)
- AC_CHECK_FUNCS($2)
- ;;
+ AC_CHECK_FUNCS($2,
+ [
+ # $2 was found in libc or existing $LIBS
+ AC_DEFINE(translit([HAVE_$2], [a-z], [A-Z]), 1,
+ [Whether $2 is available])
+ ],
+ [
+ # $2 was not found, try adding lib$1
+ case " $LIBS " in
+ *\ -l$1\ *) ;;
+ *) AC_CHECK_LIB($1, $2,
+ [
+ AC_DEFINE(translit([HAVE_$2], [a-z], [A-Z]), 1,
+ [Whether $2 is available])
+ LIBS="-l$1 $LIBS"
+ ],
+ [])
+ ;;
esac
])
])
@@ -768,3 +782,21 @@ AC_DEFUN( [AC_TRY_RUN_STRICT],
old_LDFLAGS="";
export LDFLAGS;
])
+
+dnl SMB_CHECK_SYSCONF(varname)
+dnl Tests whether the sysconf(3) variable "varname" is available.
+AC_DEFUN([SMB_CHECK_SYSCONF],
+[
+ AC_CACHE_CHECK([for sysconf($1)],
+ samba_cv_SYSCONF$1,
+ [
+ AC_TRY_LINK([#include <unistd.h>],
+ [ return sysconf($1) == -1 ? 1 : 0; ],
+ [ samba_cv_SYSCONF$1=yes ],
+ [ samba_cv_SYSCONF$1=no ])
+ ])
+
+ if test x"$samba_cv_SYSCONF$1" = x"yes" ; then
+ AC_DEFINE(SYSCONF$1, 1, [Whether sysconf($1) is available])
+ fi
+])
diff --git a/source/auth/auth.c b/source/auth/auth.c
index 5329e736ff1..139ba5482b7 100644
--- a/source/auth/auth.c
+++ b/source/auth/auth.c
@@ -23,6 +23,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
+static_decl_auth;
+
static struct auth_init_function_entry *backends = NULL;
static struct auth_init_function_entry *auth_find_backend_entry(const char *name);
diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c
index c91cbf7af11..6360d10b692 100644
--- a/source/auth/auth_domain.c
+++ b/source/auth/auth_domain.c
@@ -251,12 +251,15 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
}
} else {
nt_status = make_server_info_info3(mem_ctx,
- user_info->internal_username,
user_info->smb_name,
domain,
server_info,
&info3);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ (*server_info)->was_mapped |= user_info->was_mapped;
+ }
+
netsamlogon_cache_store( user_info->smb_name, &info3 );
}
diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index 1d3d17d60dd..76071075483 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -80,6 +80,7 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
auth_usersupplied_info *user_info = NULL;
NTSTATUS nt_status;
+ BOOL username_was_mapped;
/* the client has given us its machine name (which we otherwise would not get on port 445).
we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
@@ -110,12 +111,16 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context,
user_info, &auth_ntlmssp_state->server_info);
+ username_was_mapped = user_info->was_mapped;
+
free_user_info(&user_info);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
+ auth_ntlmssp_state->server_info->was_mapped |= username_was_mapped;
+
nt_status = create_local_token(auth_ntlmssp_state->server_info);
if (!NT_STATUS_IS_OK(nt_status)) {
diff --git a/source/auth/auth_rhosts.c b/source/auth/auth_rhosts.c
deleted file mode 100644
index 23e276bc84e..00000000000
--- a/source/auth/auth_rhosts.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Main SMB reply routines
- Copyright (C) Andrew Tridgell 1992-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_AUTH
-
-/****************************************************************************
- 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, struct samu **account)
-{
- BOOL pdb_ret;
- 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;
-
- if ( !(pass = Get_Pwnam( user )) ) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- nt_status = samu_set_unix( *account, pass );
- }
-
- return nt_status;
-}
-
-/****************************************************************************
- Read the a hosts.equiv or .rhosts file and check if it
- allows this user from this machine.
-****************************************************************************/
-
-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,0);
- 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++;
- }
- 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;
- }
- }
-#else
- 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);
- }
- }
- }
- }
- }
-
- file_lines_free(lines);
- return False;
-}
-
-/****************************************************************************
-check for a possible hosts equiv or rhosts entry for the user
-****************************************************************************/
-
-static BOOL check_hosts_equiv(struct samu *account)
-{
- uid_t uid;
- char *fname = NULL;
-
- fname = lp_hosts_equiv();
- if (!sid_to_uid(pdb_get_user_sid(account), &uid))
- return False;
-
- /* note: don't allow hosts.equiv on root */
- if (fname && *fname && uid != 0) {
- if (check_user_equiv(pdb_get_username(account),client_name(),fname))
- return True;
- }
-
- return False;
-}
-
-
-/****************************************************************************
- Check for a valid .rhosts/hosts.equiv entry for this user
-****************************************************************************/
-
-static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_context,
- void *my_private_data,
- TALLOC_CTX *mem_ctx,
- const auth_usersupplied_info *user_info,
- auth_serversupplied_info **server_info)
-{
- NTSTATUS nt_status;
- struct samu *account = NULL;
- if (!NT_STATUS_IS_OK(nt_status =
- 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;
- return nt_status;
- }
-
- 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 {
- TALLOC_FREE(account);
- nt_status = NT_STATUS_NOT_IMPLEMENTED;
- }
-
- return nt_status;
-}
-
-/* module initialisation */
-static NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* param, auth_methods **auth_method)
-{
- if (!make_auth_methods(auth_context, auth_method)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- (*auth_method)->auth = check_hostsequiv_security;
- (*auth_method)->name = "hostsequiv";
- return NT_STATUS_OK;
-}
-
-
-/****************************************************************************
- Check for a valid .rhosts/hosts.equiv entry for this user
-****************************************************************************/
-
-static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
- void *my_private_data,
- TALLOC_CTX *mem_ctx,
- const auth_usersupplied_info *user_info,
- auth_serversupplied_info **server_info)
-{
- NTSTATUS nt_status;
- struct samu *account = NULL;
- pstring rhostsfile;
- const char *home;
-
- if (!NT_STATUS_IS_OK(nt_status =
- 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;
- return nt_status;
- }
-
- home = pdb_get_unix_homedir(account);
-
- if (home) {
- slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
- 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 {
- TALLOC_FREE(account);
- }
- unbecome_root();
- } else {
- TALLOC_FREE(account);
- nt_status = NT_STATUS_NOT_IMPLEMENTED;
- }
-
- return nt_status;
-}
-
-/* module initialisation */
-static NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param, auth_methods **auth_method)
-{
- if (!make_auth_methods(auth_context, auth_method)) {
- return NT_STATUS_NO_MEMORY;
- }
-
- (*auth_method)->auth = check_rhosts_security;
- (*auth_method)->name = "rhosts";
- return NT_STATUS_OK;
-}
-
-NTSTATUS auth_rhosts_init(void)
-{
- smb_register_auth(AUTH_INTERFACE_VERSION, "rhosts", auth_init_rhosts);
- smb_register_auth(AUTH_INTERFACE_VERSION, "hostsequiv", auth_init_hostsequiv);
- return NT_STATUS_OK;
-}
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index 94e4ec414b6..50ce9065fd9 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -349,6 +349,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
lm_sess_key.length);
data_blob_free(&lm_sess_key);
+ (*server_info)->was_mapped |= user_info->was_mapped;
+
return nt_status;
}
diff --git a/source/auth/auth_script.c b/source/auth/auth_script.c
index 1bc33ec59e7..ec7264924cd 100644
--- a/source/auth/auth_script.c
+++ b/source/auth/auth_script.c
@@ -140,16 +140,7 @@ static NTSTATUS auth_init_script(struct auth_context *auth_context, const char *
return NT_STATUS_OK;
}
-#if 0
-/* Define this to build static. */
NTSTATUS auth_script_init(void)
{
return smb_register_auth(AUTH_INTERFACE_VERSION, "script", auth_init_script);
}
-#else
-/* Define this to build shared. */
-NTSTATUS init_module(void)
-{
- return smb_register_auth(AUTH_INTERFACE_VERSION, "script", auth_init_script);
-}
-#endif
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 4ffbba2e237..f4d32ebdc0c 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -152,9 +152,11 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
BOOL encrypted)
{
const char *domain;
+ NTSTATUS result;
+ BOOL was_mapped;
fstring internal_username;
fstrcpy(internal_username, smb_name);
- map_username(internal_username);
+ was_mapped = map_username(internal_username);
DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
client_domain, smb_name, wksta_name));
@@ -176,11 +178,15 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
/* we know that it is a trusted domain (and we are allowing them) or it is our domain */
- return make_user_info(user_info, smb_name, internal_username,
+ result = make_user_info(user_info, smb_name, internal_username,
client_domain, domain, wksta_name,
lm_pwd, nt_pwd,
lm_interactive_pwd, nt_interactive_pwd,
plaintext, encrypted);
+ if (NT_STATUS_IS_OK(result)) {
+ (*user_info)->was_mapped = was_mapped;
+ }
+ return result;
}
/****************************************************************************
@@ -923,15 +929,29 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
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->was_mapped) {
+ status = create_token_from_username(server_info,
+ server_info->unix_name,
+ server_info->guest,
+ &server_info->uid,
+ &server_info->gid,
+ &server_info->unix_name,
+ &server_info->ptok);
+
+ } else {
+ 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);
+ status = server_info->ptok ?
+ NT_STATUS_OK : NT_STATUS_NO_SUCH_USER;
+ }
- if ( !server_info->ptok ) {
- return NT_STATUS_NO_SUCH_USER;
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(mem_ctx);
+ return status;
}
/* Convert the SIDs to gids. */
@@ -1076,6 +1096,12 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
sid_copy(&primary_group_sid, pdb_get_group_sid(sam_acct));
+ if (!sid_to_gid(&primary_group_sid, gid)) {
+ DEBUG(1, ("sid_to_gid(%s) failed\n",
+ sid_string_static(&primary_group_sid)));
+ goto done;
+ }
+
result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
&group_sids, &gids,
&num_group_sids);
@@ -1172,7 +1198,6 @@ BOOL user_in_group(const char *username, const char *groupname)
{
TALLOC_CTX *mem_ctx;
DOM_SID group_sid;
- NTSTATUS status;
BOOL ret;
mem_ctx = talloc_new(NULL);
@@ -1186,8 +1211,7 @@ BOOL user_in_group(const char *username, const char *groupname)
TALLOC_FREE(mem_ctx);
if (!ret) {
- DEBUG(10, ("lookup_name(%s) failed: %s\n", groupname,
- nt_errstr(status)));
+ DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
return False;
}
@@ -1366,7 +1390,8 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
const char *username,
char **found_username,
uid_t *uid, gid_t *gid,
- struct samu *account)
+ struct samu *account,
+ BOOL *username_was_mapped)
{
NTSTATUS nt_status;
fstring dom_user, lower_username;
@@ -1381,7 +1406,7 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
/* Get the passwd struct. Try to create the account is necessary. */
- map_username( dom_user );
+ *username_was_mapped = map_username( dom_user );
if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
return NT_STATUS_NO_SUCH_USER;
@@ -1496,7 +1521,6 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
***************************************************************************/
NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
- const char *internal_username,
const char *sent_nt_username,
const char *domain,
auth_serversupplied_info **server_info,
@@ -1511,6 +1535,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
struct samu *sam_account = NULL;
DOM_SID user_sid;
DOM_SID group_sid;
+ BOOL username_was_mapped;
uid_t uid;
gid_t gid;
@@ -1563,16 +1588,12 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
+ /* this call will try to create the user if necessary */
+
nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
- &found_username, &uid, &gid, sam_account);
+ &found_username, &uid, &gid, sam_account,
+ &username_was_mapped);
- 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));
- 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 );
- }
/* if we still don't have a valid unix account check for
'map to guest = bad uid' */
@@ -1722,6 +1743,8 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
sizeof(info3->lm_sess_key));
}
+ result->was_mapped = username_was_mapped;
+
*server_info = result;
return NT_STATUS_OK;
diff --git a/source/auth/auth_winbind.c b/source/auth/auth_winbind.c
index 4836d62ef96..d8ac348d040 100644
--- a/source/auth/auth_winbind.c
+++ b/source/auth/auth_winbind.c
@@ -128,11 +128,13 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
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,
user_info->smb_name, user_info->domain,
server_info, &info3);
}
+ if (NT_STATUS_IS_OK(nt_status)) {
+ (*server_info)->was_mapped |= user_info->was_mapped;
+ }
}
} else if (NT_STATUS_IS_OK(nt_status)) {
nt_status = NT_STATUS_NO_LOGON_SERVERS;
diff --git a/source/client/smbctool.c b/source/client/smbctool.c
index 6c89f5ea827..ba095aee84e 100644
--- a/source/client/smbctool.c
+++ b/source/client/smbctool.c
@@ -3649,7 +3649,9 @@ static int do_message_op(void)
if ( override_logfile )
setup_logging( lp_logfile(), False );
-
+
+ load_case_tables();
+
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/smbspool.c b/source/client/smbspool.c
index af2f7e9180c..e5cd4f2e8e6 100644
--- a/source/client/smbspool.c
+++ b/source/client/smbspool.c
@@ -23,7 +23,6 @@
#include "includes.h"
-#define PW_MAX_BUF_SIZE sysconf(_SC_GETPW_R_SIZE_MAX)
#define TICKET_CC_DIR "/tmp"
#define CC_PREFIX "krb5cc_" /* prefix of the ticket cache */
#define CC_MAX_FILE_LEN 24
@@ -214,6 +213,8 @@ static int smb_print(struct cli_state *, char *, FILE *);
in_client = True; /* Make sure that we tell lp_load we are */
+ load_case_tables();
+
if (!lp_load(dyn_CONFIGFILE, True, False, False, True))
{
fprintf(stderr, "ERROR: Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
diff --git a/source/configure.in b/source/configure.in
index c479d2d290f..dabdca87565 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -545,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_netdfs 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_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"
@@ -819,7 +819,8 @@ AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(aio.h arpa/inet.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
-AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h limits.h memory.h alloca.h)
+AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h memory.h alloca.h)
+AC_CHECK_HEADERS(limits.h float.h)
AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h)
@@ -1243,6 +1244,8 @@ AC_CHECK_FUNCS(srandom random srand rand setenv usleep strcasecmp fcvt fcvtl sym
AC_CHECK_FUNCS(syslog vsyslog timegm)
AC_CHECK_FUNCS(setlocale nl_langinfo)
AC_CHECK_FUNCS(nanosleep)
+AC_CHECK_FUNCS(mlock munlock mlockall munlockall)
+AC_CHECK_HEADERS(sys/mman.h)
# setbuffer, shmget, shm_open are needed for smbtorture
AC_CHECK_FUNCS(setbuffer shmget shm_open)
@@ -1256,7 +1259,7 @@ AC_CHECK_LIB(exc, trace_back_stack)
# any of them.
AC_MSG_CHECKING([for libunwind])
save_LIBS=$LIBS
-if test x"$UNAME_P" != xunknown ; then
+if test x"$UNAME_P" = xunknown ; then
# This probably won't link without the platform-specific libunwind.
LIBS="$LIBS -lunwind"
else
@@ -1280,12 +1283,61 @@ AC_TRY_LINK(
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_LIBUNWIND, 1, [Whether libunwind is available])
+
+ # If we have libunwind, test whether we also have libunwind-ptrace
+ # which would let us unwind arbitrary processes.
+ save_LIBS=$LIBS
+ AC_CHECK_HEADERS(libunwind-ptrace.h)
+ AC_CHECK_LIB(unwind-ptrace, _UPT_create,
+ [
+ LIBUNWIND_PTRACE="-lunwind-ptrace";
+ AC_DEFINE(HAVE_LIBUNWIND_PTRACE, 1,
+ [Whether libunwind-ptrace.a is available.])
+ ],
+ [ LIBUNWIND_PTRACE="" ])
+
+ LIBS=$save_LIBS
],
[
AC_MSG_RESULT(no)
LIBS=$save_LIBS
])
+# To use libunwind-ptrace, we also need to make some ptrace system calls.
+if test x"$LIBUNWIND_PTRACE" != x"" ; then
+ AC_CHECK_HEADERS(sys/ptrace.h)
+ AC_MSG_CHECKING([for the Linux ptrace(2) interface])
+ AC_TRY_LINK(
+ [
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_PTRACE_H
+#include <sys/ptrace.h>
+#endif
+ ],
+ [
+ int main(int argc, const char ** argv)
+ {
+ pid_t me = (pid_t)-1;
+ ptrace(PTRACE_ATTACH, me, 0, 0);
+ ptrace(PTRACE_DETACH, me, 0, 0);
+ return 0;
+ }
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LINUX_PTRACE, 1,
+ [Whether the Linux ptrace(2) interface is available.])
+ ],
+ [
+ AC_MSG_RESULT(no)
+ LIBUNWIND_PTRACE=""
+ ])
+fi
+
+AC_SUBST(LIBUNWIND_PTRACE)
+
# syscall() is needed for smbwrapper.
AC_CHECK_FUNCS(syscall)
@@ -1482,8 +1534,10 @@ if test x"$samba_stat_hires_notimespec" = x"yes" ; then
fi
#####################################
-# we might need the resolv library on some systems
+# needed for SRV lookups
AC_CHECK_LIB(resolv, dn_expand)
+AC_CHECK_LIB(resolv, _dn_expand)
+AC_CHECK_LIB(resolv, __dn_expand)
#
# Check for the functions putprpwnam, set_auth_parameters,
@@ -1970,6 +2024,8 @@ if test x"$samba_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available])
fi
+AC_LIBTESTFUNC(rt, clock_gettime)
+
AC_CACHE_CHECK([for va_copy],samba_cv_HAVE_VA_COPY,[
AC_TRY_LINK([#include <stdarg.h>
va_list ap1,ap2;], [va_copy(ap1,ap2);],
@@ -2653,21 +2709,10 @@ 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); }],
-samba_cv_SYSCONF_SC_NGROUPS_MAX=yes,samba_cv_SYSCONF_SC_NGROUPS_MAX=no,samba_cv_SYSCONF_SC_NGROUPS_MAX=cross)])
-if test x"$samba_cv_SYSCONF_SC_NGROUPS_MAX" = x"yes"; then
- AC_DEFINE(SYSCONF_SC_NGROUPS_MAX,1,[Whether sysconf(_SC_NGROUPS_MAX) is available])
-fi
-
-AC_CACHE_CHECK([for sysconf(_SC_NPROC_ONLN)],samba_cv_SYSCONF_SC_NPROC_ONLN,[
-AC_TRY_RUN([#include <unistd.h>
-main() { exit(sysconf(_SC_NPROC_ONLN) == -1 ? 1 : 0); }],
-samba_cv_SYSCONF_SC_NPROC_ONLN=yes,samba_cv_SYSCONF_SC_NPROC_ONLN=no,samba_cv_SYSCONF_SC_NPROC_ONLN=cross)])
-if test x"$samba_cv_SYSCONF_SC_NPROC_ONLN" = x"yes"; then
- AC_DEFINE(SYSCONF_SC_NPROC_ONLN,1,[Whether sysconf(_SC_NPROC_ONLN) is available])
-fi
+SMB_CHECK_SYSCONF(_SC_NGROUPS_MAX)
+SMB_CHECK_SYSCONF(_SC_NPROC_ONLN)
+SMB_CHECK_SYSCONF(_SC_NPROCESSORS_ONLN)
+SMB_CHECK_SYSCONF(_SC_PAGESIZE)
AC_CACHE_CHECK([for root],samba_cv_HAVE_ROOT,[
AC_TRY_RUN([main() { exit(getuid() != 0); }],
@@ -2913,7 +2958,7 @@ AC_ARG_WITH(smbwrapper,
# Conditions under which smbwrapper should not be built.
- if test x$PICFLAGS = x; then
+ if test x"$PICFLAGS" = x; then
echo No support for PIC code - disabling smbwrapper and smbsh
WRAPPROG=""
WRAP=""
@@ -3189,17 +3234,6 @@ else
fi
fi
- 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)
- 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_CHECK_FUNC_EXT(ldap_add_result_entry,$LDAP_LIBS)
if test x"$ac_cv_func_ext_ldap_add_result_entry" != x"yes"; then
@@ -3655,6 +3689,18 @@ if test x"$with_ads_support" != x"no"; then
[Whether krb5_keytab_entry has keyblock member])
fi
+ AC_CACHE_CHECK([for magic in krb5_address],
+ samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS,[
+ AC_TRY_COMPILE([#include <krb5.h>],
+ [krb5_address addr; addr.magic = 0;],
+ samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS=yes,
+ samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS=no)])
+
+ if test x"$samba_cv_HAVE_MAGIC_IN_KRB5_ADDRESS" = x"yes"; then
+ AC_DEFINE(HAVE_MAGIC_IN_KRB5_ADDRESS,1,
+ [Whether the krb5_address struct has a magic property])
+ fi
+
if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then
AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support])
AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support])
@@ -3705,6 +3751,18 @@ if test x"$with_ads_support" != x"no"; then
[Whether krb5_princ_realm returns krb5_realm or krb5_data])
fi
+ AC_CACHE_CHECK([for krb5_addresses type],
+ samba_cv_HAVE_KRB5_ADDRESSES,[
+ AC_TRY_COMPILE([#include <krb5.h>],
+ [krb5_addresses addr;],
+ samba_cv_HAVE_KRB5_ADDRESSES=yes,
+ samba_cv_HAVE_KRB5_ADDRESSES=no)])
+
+ if test x"$samba_cv_HAVE_KRB5_ADDRESSES" = x"yes"; then
+ AC_DEFINE(HAVE_KRB5_ADDRESSES,1,
+ [Whether the type krb5_addresses type exists])
+ fi
+
LIBS="$ac_save_LIBS"
fi
@@ -3838,7 +3896,7 @@ AC_ARG_WITH(pam_smbpass,
# Conditions under which pam_smbpass should not be built.
- if test x$PICFLAGS = x; then
+ if test x"$PICFLAGS" = x; then
AC_MSG_ERROR([No support for PIC code])
elif test x"$ac_cv_header_security_pam_appl_h" = x"no"; then
AC_MSG_ERROR([No security/pam_appl.h found])
@@ -3883,36 +3941,6 @@ if test x"$samba_cv_HAVE_TRUNCATED_SALT" = x"yes"; then
fi
fi
-
-########################################################################################
-##
-## TESTS FOR SAM BACKENDS. KEEP THESE GROUPED TOGETHER
-##
-########################################################################################
-
-#################################################
-# check for a LDAP password database configuration backwards compatibility
-AC_MSG_CHECKING(whether to use LDAP SAM 2.2 compatible configuration)
-AC_ARG_WITH(ldapsam,
-[ --with-ldapsam Include LDAP SAM 2.2 compatible configuration (default=no)],
-[ case "$withval" in
- yes)
- AC_MSG_RESULT(yes)
- AC_DEFINE(WITH_LDAP_SAMCONFIG,1,[Whether to include 2.2 compatible LDAP SAM configuration])
- ;;
- *)
- AC_MSG_RESULT(no)
- ;;
- esac ],
- AC_MSG_RESULT(no)
-)
-
-########################################################################################
-##
-## END OF TESTS FOR SAM BACKENDS.
-##
-########################################################################################
-
#################################################
# check for a NISPLUS_HOME support
AC_MSG_CHECKING(whether to use NISPLUS_HOME)
@@ -5499,7 +5527,6 @@ SMB_MODULE(charset_CP437, modules/CP437.o, "bin/CP437.$SHLIBEXT", CHARSET)
SMB_MODULE(charset_macosxfs, modules/charset_macosxfs.o,"bin/macosxfs.$SHLIBEXT", CHARSET)
SMB_SUBSYSTEM(CHARSET,lib/iconv.o)
-SMB_MODULE(auth_rhosts, \$(AUTH_RHOSTS_OBJ), "bin/rhosts.$SHLIBEXT", AUTH)
SMB_MODULE(auth_sam, \$(AUTH_SAM_OBJ), "bin/sam.$SHLIBEXT", AUTH)
SMB_MODULE(auth_unix, \$(AUTH_UNIX_OBJ), "bin/unix.$SHLIBEXT", AUTH)
SMB_MODULE(auth_winbind, \$(AUTH_WINBIND_OBJ), "bin/winbind.$SHLIBEXT", AUTH)
diff --git a/source/include/ads.h b/source/include/ads.h
index 2c7999e24fd..210c6c80f17 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -4,6 +4,13 @@
basically this is a wrapper around ldap
*/
+enum wb_posix_mapping {
+ WB_POSIX_MAP_TEMPLATE = 0,
+ WB_POSIX_MAP_SFU = 1,
+ WB_POSIX_MAP_RFC2307 = 2,
+ WB_POSIX_MAP_UNIXINFO = 3
+};
+
typedef struct {
void *ld; /* the active ldap structure */
struct in_addr ldap_ip; /* the ip of the active connection, if any */
@@ -17,7 +24,6 @@ typedef struct {
char *realm;
char *workgroup;
char *ldap_server;
- char *ldap_uri;
int foreign; /* set to 1 if connecting to a foreign realm */
} server;
@@ -37,18 +43,18 @@ typedef struct {
struct {
char *realm;
char *bind_path;
- char *schema_path;
char *ldap_server_name;
time_t current_time;
} config;
/* info derived from the servers schema */
struct {
- char *sfu_homedir_attr;
- char *sfu_shell_attr;
- char *sfu_uidnumber_attr;
- char *sfu_gidnumber_attr;
- char *sfu_gecos_attr;
+ enum wb_posix_mapping map_type;
+ char *posix_homedir_attr;
+ char *posix_shell_attr;
+ char *posix_uidnumber_attr;
+ char *posix_gidnumber_attr;
+ char *posix_gecos_attr;
} schema;
} ADS_STRUCT;
@@ -85,6 +91,13 @@ typedef void **ADS_MODLIST;
#define ADS_ERR_OK(status) ((status.error_type == ENUM_ADS_ERROR_NT) ? NT_STATUS_IS_OK(status.err.nt_status):(status.err.rc == 0))
#define ADS_SUCCESS ADS_ERROR(0)
+#define ADS_ERROR_HAVE_NO_MEMORY(x) do { \
+ if (!(x)) {\
+ return ADS_ERROR(LDAP_NO_MEMORY);\
+ }\
+} while (0)
+
+
/* time between reconnect attempts */
#define ADS_RECONNECT_TIME 5
@@ -94,6 +107,7 @@ typedef void **ADS_MODLIST;
#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"
+#define ADS_EXTENDED_DN_OID "1.2.840.113556.1.4.529"
/* ldap attribute oids (Services for Unix) */
#define ADS_ATTR_SFU_UIDNUMBER_OID "1.2.840.113556.1.6.18.1.310"
@@ -102,6 +116,13 @@ typedef void **ADS_MODLIST;
#define ADS_ATTR_SFU_SHELL_OID "1.2.840.113556.1.6.18.1.312"
#define ADS_ATTR_SFU_GECOS_OID "1.2.840.113556.1.6.18.1.337"
+/* ldap attribute oids (RFC2307) */
+#define ADS_ATTR_RFC2307_UIDNUMBER_OID "1.3.6.1.1.1.1.0"
+#define ADS_ATTR_RFC2307_GIDNUMBER_OID "1.3.6.1.1.1.1.1"
+#define ADS_ATTR_RFC2307_HOMEDIR_OID "1.3.6.1.1.1.1.3"
+#define ADS_ATTR_RFC2307_SHELL_OID "1.3.6.1.1.1.1.4"
+#define ADS_ATTR_RFC2307_GECOS_OID "1.3.6.1.1.1.1.2"
+
/* ldap bitwise searches */
#define ADS_LDAP_MATCHING_RULE_BIT_AND "1.2.840.113556.1.4.803"
#define ADS_LDAP_MATCHING_RULE_BIT_OR "1.2.840.113556.1.4.804"
@@ -219,19 +240,6 @@ typedef void **ADS_MODLIST;
#define GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP 0x00000004 /* 4 */
#define GTYPE_DISTRIBUTION_UNIVERSAL_GROUP 0x00000008 /* 8 */
-/* Mailslot or cldap getdcname response flags */
-#define ADS_PDC 0x00000001 /* DC is PDC */
-#define ADS_GC 0x00000004 /* DC is a GC of forest */
-#define ADS_LDAP 0x00000008 /* DC is an LDAP server */
-#define ADS_DS 0x00000010 /* DC supports DS */
-#define ADS_KDC 0x00000020 /* DC is running KDC */
-#define ADS_TIMESERV 0x00000040 /* DC is running time services */
-#define ADS_CLOSEST 0x00000080 /* DC is closest to client */
-#define ADS_WRITABLE 0x00000100 /* DC has writable DS */
-#define ADS_GOOD_TIMESERV 0x00000200 /* DC has hardware clock
- (and running time) */
-#define ADS_NDNC 0x00000400 /* DomainName is non-domain NC serviced
- by LDAP server */
#define ADS_PINGS 0x0000FFFF /* Ping response */
#define ADS_DNS_CONTROLLER 0x20000000 /* DomainControllerName is a DNS name*/
#define ADS_DNS_DOMAIN 0x40000000 /* DomainName is a DNS name */
@@ -266,3 +274,33 @@ typedef void **ADS_MODLIST;
#define WELL_KNOWN_GUID_COMPUTERS "AA312825768811D1ADED00C04FD8D5CD"
#define WELL_KNOWN_GUID_USERS "A9D1CA15768811D1ADED00C04FD8D5CD"
+
+#ifndef KRB5_ADDR_NETBIOS
+#define KRB5_ADDR_NETBIOS 0x14
+#endif
+
+#ifdef HAVE_KRB5
+typedef struct {
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ krb5_address **addrs;
+#elif defined(HAVE_KRB5_ADDRESSES) /* Heimdal */
+ krb5_addresses *addrs;
+#else
+#error UNKNOWN_KRB5_ADDRESS_TYPE
+#endif
+} smb_krb5_addresses;
+#endif
+
+enum ads_extended_dn_flags {
+ ADS_EXTENDED_DN_HEX_STRING = 0,
+ ADS_EXTENDED_DN_STRING = 1 /* not supported on win2k */
+};
+
+/* this is probably not very well suited to pass other controls generically but
+ * is good enough for the extended dn control where it is only used for atm */
+
+typedef struct {
+ const char *control;
+ int val;
+ int critical;
+} ads_control;
diff --git a/source/include/ads_cldap.h b/source/include/ads_cldap.h
new file mode 100644
index 00000000000..65feb072e0f
--- /dev/null
+++ b/source/include/ads_cldap.h
@@ -0,0 +1,58 @@
+/*
+ Samba Unix/Linux SMB client library
+ net ads cldap functions
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+ Copyright (C) 2003 Jim McDonough (jmcd@us.ibm.com)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 MAX_DNS_LABEL 255 + 1
+
+struct cldap_netlogon_reply {
+ uint32 type;
+ uint32 flags;
+ UUID_FLAT guid;
+
+ char forest[MAX_DNS_LABEL];
+ char domain[MAX_DNS_LABEL];
+ char hostname[MAX_DNS_LABEL];
+
+ char netbios_domain[MAX_DNS_LABEL];
+ char netbios_hostname[MAX_DNS_LABEL];
+
+ char unk[MAX_DNS_LABEL];
+ char user_name[MAX_DNS_LABEL];
+ char site_name[MAX_DNS_LABEL];
+ char site_name_2[MAX_DNS_LABEL];
+
+ uint32 version;
+ uint16 lmnt_token;
+ uint16 lm20_token;
+};
+
+/* Mailslot or cldap getdcname response flags */
+#define ADS_PDC 0x00000001 /* DC is PDC */
+#define ADS_GC 0x00000004 /* DC is a GC of forest */
+#define ADS_LDAP 0x00000008 /* DC is an LDAP server */
+#define ADS_DS 0x00000010 /* DC supports DS */
+#define ADS_KDC 0x00000020 /* DC is running KDC */
+#define ADS_TIMESERV 0x00000040 /* DC is running time services */
+#define ADS_CLOSEST 0x00000080 /* DC is closest to client */
+#define ADS_WRITABLE 0x00000100 /* DC has writable DS */
+#define ADS_GOOD_TIMESERV 0x00000200 /* DC has hardware clock (and running time) */
+#define ADS_NDNC 0x00000400 /* DomainName is non-domain NC serviced by LDAP server */
+
+
diff --git a/source/include/ads_dns.h b/source/include/ads_dns.h
new file mode 100644
index 00000000000..9b65db0c8e4
--- /dev/null
+++ b/source/include/ads_dns.h
@@ -0,0 +1,54 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Internal DNS query structures
+ * Copyright (C) Gerald Carter 2006.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ADS_DNS_H
+#define _ADS_DNS_H
+
+/* DNS query section in replies */
+
+struct dns_query {
+ const char *hostname;
+ uint16 type;
+ uint16 in_class;
+};
+
+/* DNS RR record in reply */
+
+struct dns_rr {
+ const char *hostname;
+ uint16 type;
+ uint16 in_class;
+ uint32 ttl;
+ uint16 rdatalen;
+ uint8 *rdata;
+};
+
+/* SRV records */
+
+struct dns_rr_srv {
+ const char *hostname;
+ uint16 priority;
+ uint16 weight;
+ uint16 port;
+ struct in_addr ip;
+};
+
+
+#endif /* _ADS_DNS_H */
diff --git a/source/include/auth.h b/source/include/auth.h
index 465892905a6..de75ff68f6f 100644
--- a/source/include/auth.h
+++ b/source/include/auth.h
@@ -29,6 +29,7 @@ typedef struct auth_usersupplied_info {
BOOL encrypted;
+ BOOL was_mapped; /* Did the username map actually match? */
char *client_domain; /* domain name string */
char *domain; /* domain name after mapping */
char *internal_username; /* username after mapping */
@@ -67,6 +68,7 @@ typedef struct auth_serversupplied_info {
void *pam_handle;
+ BOOL was_mapped; /* Did the username map match? */
char *unix_name;
} auth_serversupplied_info;
diff --git a/source/include/includes.h b/source/include/includes.h
index a5f261282ce..a74ca7084d5 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -93,6 +93,10 @@
#include <sys/types.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
@@ -903,6 +907,7 @@ extern int errno;
#include "nt_status.h"
#include "ads.h"
+#include "ads_dns.h"
#include "interfaces.h"
#include "trans2.h"
#include "nterr.h"
@@ -910,52 +915,29 @@ extern int errno;
#include "messages.h"
#include "charset.h"
#include "dynconfig.h"
-
#include "util_getent.h"
-
#include "debugparse.h"
-
#include "version.h"
-
#include "privileges.h"
-
#include "smb.h"
-
+#include "ads_cldap.h"
#include "nameserv.h"
-
#include "secrets.h"
-
#include "byteorder.h"
-
#include "privileges.h"
-
#include "rpc_misc.h"
-
#include "rpc_dce.h"
-
#include "mapping.h"
-
#include "passdb.h"
-
#include "rpc_secdes.h"
-
#include "authdata.h"
-
#include "msdfs.h"
-
-#include "smbprofile.h"
-
#include "rap.h"
-
#include "md5.h"
#include "hmacmd5.h"
-
#include "ntlmssp.h"
-
#include "auth.h"
-
#include "ntdomain.h"
-
#include "rpc_svcctl.h"
#include "rpc_ntsvcs.h"
#include "rpc_lsa.h"
@@ -973,11 +955,8 @@ extern int errno;
#include "rpc_shutdown.h"
#include "rpc_perfcount.h"
#include "rpc_perfcount_defs.h"
-
#include "nt_printing.h"
-
#include "idmap.h"
-
#include "client.h"
#ifdef WITH_SMBWRAPPER
@@ -985,21 +964,13 @@ extern int errno;
#endif
#include "session.h"
-
#include "asn_1.h"
-
#include "popt.h"
-
#include "mangle.h"
-
#include "module.h"
-
#include "nsswitch/winbind_client.h"
-
#include "spnego.h"
-
#include "rpc_client.h"
-
#include "event.h"
/*
@@ -1059,11 +1030,30 @@ struct smb_ldap_privates;
#include "smb_ldap.h"
+/*
+ * Reasons for cache flush.
+ */
+
+enum flush_reason_enum {
+ SEEK_FLUSH,
+ READ_FLUSH,
+ WRITE_FLUSH,
+ READRAW_FLUSH,
+ OPLOCK_RELEASE_FLUSH,
+ CLOSE_FLUSH,
+ SYNC_FLUSH,
+ SIZECHANGE_FLUSH,
+ /* NUM_FLUSH_REASONS must remain the last value in the enumeration. */
+ NUM_FLUSH_REASONS};
+
/***** automatically generated prototypes *****/
#ifndef NO_PROTO_H
#include "proto.h"
#endif
+/* We need this after proto.h to reference GetTimeOfDay(). */
+#include "smbprofile.h"
+
/* String routines */
#include "srvstr.h"
@@ -1458,6 +1448,14 @@ time_t timegm(struct tm *tm);
#if defined(HAVE_KRB5)
+krb5_error_code smb_krb5_parse_name(krb5_context context,
+ const char *name, /* in unix charset */
+ krb5_principal *principal);
+
+krb5_error_code smb_krb5_unparse_name(krb5_context context,
+ krb5_const_principal principal,
+ char **unix_name);
+
#ifndef HAVE_KRB5_SET_REAL_TIME
krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds);
#endif
@@ -1530,6 +1528,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
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);
+krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr);
+krb5_error_code smb_krb5_free_addresses(krb5_context context, smb_krb5_addresses *addr);
NTSTATUS krb5_to_nt_status(krb5_error_code kerberos_error);
krb5_error_code nt_status_to_krb5(NTSTATUS nt_status);
#endif /* HAVE_KRB5 */
diff --git a/source/include/messages.h b/source/include/messages.h
index 6a739c0bcc7..e246123ea9f 100644
--- a/source/include/messages.h
+++ b/source/include/messages.h
@@ -76,6 +76,7 @@
#define MSG_WINBIND_FORGET_STATE 4002
#define MSG_WINBIND_ONLINE 4003
#define MSG_WINBIND_OFFLINE 4004
+#define MSG_WINBIND_ONLINESTATUS 4005
/* Flags to classify messages - used in message_send_all() */
/* Sender will filter by flag. */
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 37a0ed9a3f8..49ea36f364c 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -531,21 +531,68 @@ typedef struct q_samr_query_domain_info
} SAMR_Q_QUERY_DOMAIN_INFO;
+typedef struct sam_unknown_info_1_inf
+{
+ uint16 min_length_password;
+ uint16 password_history;
+ uint32 password_properties;
+ NTTIME expire;
+ NTTIME min_passwordage;
+
+} SAM_UNK_INFO_1;
+
+typedef struct sam_unknown_info_2_inf
+{
+ NTTIME logout; /* whether users are forcibly disconnected when logon hours expire */
+ UNIHDR hdr_comment; /* comment according to samba4 idl */
+ UNIHDR hdr_domain; /* domain name unicode header */
+ UNIHDR hdr_server; /* server name unicode header */
+
+ /* put all the data in here, at the moment, including what the above
+ pointer is referring to
+ */
+
+ UINT64_S seq_num;
+
+ uint32 unknown_4; /* 0x0000 0001 */
+ uint32 server_role;
+ uint32 unknown_6; /* 0x0000 0001 */
+ uint32 num_domain_usrs; /* number of users in domain */
+ uint32 num_domain_grps; /* number of domain groups in domain */
+ uint32 num_local_grps; /* number of local groups in domain */
+
+ UNISTR2 uni_comment; /* comment unicode string */
+ UNISTR2 uni_domain; /* domain name unicode string */
+ UNISTR2 uni_server; /* server name unicode string */
+
+} SAM_UNK_INFO_2;
+
typedef struct sam_unknown_info_3_info
{
NTTIME logout;
/* 0x8000 0000 */ /* DON'T forcibly disconnect remote users from server when logon hours expire*/
-
/* 0x0000 0000 */ /* forcibly disconnect remote users from server when logon hours expire*/
} SAM_UNK_INFO_3;
-typedef struct sam_unknown_info_6_info
+typedef struct sam_unknown_info_4_inf
{
- uint32 unknown_0; /* 0x0000 0000 */
+ UNIHDR hdr_comment; /* comment according to samba4 idl */
+ UNISTR2 uni_comment; /* comment unicode string */
+
+} SAM_UNK_INFO_4;
+
+typedef struct sam_unknown_info_5_inf
+{
+ UNIHDR hdr_domain; /* domain name unicode header */
+ UNISTR2 uni_domain; /* domain name unicode string */
- uint32 ptr_0; /* pointer to unknown structure */
- uint8 padding[12]; /* 12 bytes zeros */
+} SAM_UNK_INFO_5;
+
+typedef struct sam_unknown_info_6_info
+{
+ UNIHDR hdr_server; /* server name unicode header */
+ UNISTR2 uni_server; /* server name unicode string */
} SAM_UNK_INFO_6;
@@ -562,6 +609,12 @@ typedef struct sam_unknown_info_8_info
} SAM_UNK_INFO_8;
+typedef struct sam_unknown_info_9_info
+{
+ uint32 unknown;
+
+} SAM_UNK_INFO_9;
+
typedef struct sam_unknown_info_12_inf
{
NTTIME duration;
@@ -570,51 +623,14 @@ typedef struct sam_unknown_info_12_inf
} SAM_UNK_INFO_12;
-typedef struct sam_unknown_info_5_inf
-{
- UNIHDR hdr_server; /* server name unicode header */
- UNISTR2 uni_server; /* server name unicode string */
-
-} SAM_UNK_INFO_5;
-
-typedef struct sam_unknown_info_2_inf
+typedef struct sam_unknown_info_13_info
{
- NTTIME logout; /* whether users are forcibly disconnected when logon hours expire */
- UNIHDR hdr_comment; /* comment according to samba4 idl */
- UNIHDR hdr_domain; /* domain name unicode header */
- UNIHDR hdr_server; /* server name unicode header */
-
- /* put all the data in here, at the moment, including what the above
- pointer is referring to
- */
-
UINT64_S seq_num;
-
- uint32 unknown_4; /* 0x0000 0001 */
- uint32 server_role;
- uint32 unknown_6; /* 0x0000 0001 */
- uint32 num_domain_usrs; /* number of users in domain */
- uint32 num_domain_grps; /* number of domain groups in domain */
- uint32 num_local_grps; /* number of local groups in domain */
-
- uint8 padding[12]; /* 12 bytes zeros */
-
- UNISTR2 uni_comment; /* comment unicode string */
- UNISTR2 uni_domain; /* domain name unicode string */
- UNISTR2 uni_server; /* server name unicode string */
-
-} SAM_UNK_INFO_2;
-
-typedef struct sam_unknown_info_1_inf
-{
- uint16 min_length_password;
- uint16 password_history;
- uint32 password_properties;
- NTTIME expire;
- NTTIME min_passwordage;
-
-} SAM_UNK_INFO_1;
+ NTTIME domain_create_time;
+ uint32 unknown1;
+ uint32 unknown2;
+} SAM_UNK_INFO_13;
typedef struct sam_unknown_ctr_info
{
@@ -623,11 +639,14 @@ typedef struct sam_unknown_ctr_info
SAM_UNK_INFO_1 inf1;
SAM_UNK_INFO_2 inf2;
SAM_UNK_INFO_3 inf3;
+ SAM_UNK_INFO_4 inf4;
SAM_UNK_INFO_5 inf5;
SAM_UNK_INFO_6 inf6;
SAM_UNK_INFO_7 inf7;
SAM_UNK_INFO_8 inf8;
+ SAM_UNK_INFO_9 inf9;
SAM_UNK_INFO_12 inf12;
+ SAM_UNK_INFO_13 inf13;
} info;
diff --git a/source/include/smb.h b/source/include/smb.h
index f6ee4297025..f06c551cc0e 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -330,6 +330,7 @@ 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_Builtin_PreWin2kAccess;
extern const DOM_SID global_sid_Unix_Users;
extern const DOM_SID global_sid_Unix_Groups;
@@ -403,6 +404,7 @@ struct fd_handle {
* DELETE_ON_CLOSE is not stored in the share
* mode database.
*/
+ unsigned long file_id;
};
struct timed_event;
@@ -437,7 +439,6 @@ typedef struct files_struct {
struct share_mode_entry *pending_break_messages;
int num_pending_break_messages;
- unsigned long file_id;
BOOL can_lock;
BOOL can_read;
BOOL can_write;
@@ -446,6 +447,7 @@ typedef struct files_struct {
BOOL is_directory;
BOOL is_stat;
BOOL aio_write_behind;
+ BOOL lockdb_clean;
char *fsp_name;
FAKE_FILE_HANDLE *fake_file_handle;
} files_struct;
@@ -736,6 +738,7 @@ struct locking_data {
#define PW_HISTORY_SALT_LEN 16
#define SALTED_MD5_HASH_LEN 16
#define PW_HISTORY_ENTRY_LEN (PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN)
+#define MAX_PW_HISTORY_LEN 24
/*
* Flags for account policy.
diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h
index f68a1e240f2..b8a9a49be1a 100644
--- a/source/include/smbprofile.h
+++ b/source/include/smbprofile.h
@@ -21,14 +21,6 @@
*/
-/*
- * Reasons for cache flush.
- */
-
-#define NUM_FLUSH_REASONS 8 /* Keep this in sync with the enum below. */
-enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH,
- OPLOCK_RELEASE_FLUSH, CLOSE_FLUSH, SYNC_FLUSH, SIZECHANGE_FLUSH };
-
/* this file defines the profile structure in the profile shared
memory area */
@@ -417,6 +409,8 @@ extern struct timeval profile_endtime_nested;
extern BOOL do_profile_flag;
extern BOOL do_profile_times;
+#ifdef WITH_PROFILE
+
/* these are helper macros - do not call them directly in the code
* use the DO_PROFILE_* START_PROFILE and END_PROFILE ones
* below which test for the profile flage first
@@ -424,61 +418,84 @@ extern BOOL do_profile_times;
#define INC_PROFILE_COUNT(x) profile_p->x++
#define DEC_PROFILE_COUNT(x) profile_p->x--
#define ADD_PROFILE_COUNT(x,y) profile_p->x += (y)
-#define PROFILE_TIME \
- ((profile_endtime.tv_sec - profile_starttime.tv_sec) *1000000 + \
- ((int)profile_endtime.tv_usec - (int)profile_starttime.tv_usec))
-#define PROFILE_TIME_NESTED \
- ((profile_endtime_nested.tv_sec - profile_starttime_nested.tv_sec) *1000000 + \
- ((int)profile_endtime_nested.tv_usec - (int)profile_starttime_nested.tv_usec))
-#ifdef WITH_PROFILE
+#if defined(HAVE_CLOCK_GETTIME)
+
+extern clockid_t __profile_clock;
+
+static inline SMB_BIG_UINT profile_timestamp(void)
+{
+ struct timespec ts;
+
+ /* FIXME: On a single-CPU system, or a system where we have bound
+ * daemon threads to single CPUs (eg. using cpusets or processor
+ * affinity), it might be preferable to use CLOCK_PROCESS_CPUTIME_ID.
+ */
+
+ clock_gettime(__profile_clock, &ts);
+ return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); /* usec */
+}
+
+#else
+
+static inline SMB_BIG_UINT profile_timestamp(void)
+{
+ struct timeval tv;
+ GetTimeOfDay(&tv);
+ return (tv.tv_sec * 1000000) + tv.tv_usec;
+}
+
+#endif
+
+/* end of helper macros */
+
#define DO_PROFILE_INC(x) \
if (do_profile_flag) { \
INC_PROFILE_COUNT(x); \
}
+
#define DO_PROFILE_DEC(x) \
if (do_profile_flag) { \
DEC_PROFILE_COUNT(x); \
}
+
#define DO_PROFILE_DEC_INC(x,y) \
if (do_profile_flag) { \
DEC_PROFILE_COUNT(x); \
INC_PROFILE_COUNT(y); \
}
+
#define DO_PROFILE_ADD(x,n) \
if (do_profile_flag) { \
ADD_PROFILE_COUNT(x,n); \
}
+
#define START_PROFILE(x) \
+ SMB_BIG_UINT __profstamp_##x = 0; \
if (do_profile_flag) { \
- if (do_profile_times) \
- GetTimeOfDay(&profile_starttime); \
+ __profstamp_##x = do_profile_times ? profile_timestamp() : 0;\
INC_PROFILE_COUNT(x##_count); \
- }
-#define START_PROFILE_NESTED(x) \
- if (do_profile_flag) { \
- if (do_profile_times) \
- GetTimeOfDay(&profile_starttime_nested); \
- INC_PROFILE_COUNT(x##_count); \
- }
+ }
+
#define START_PROFILE_BYTES(x,n) \
+ SMB_BIG_UINT __profstamp_##x = 0; \
if (do_profile_flag) { \
- if (do_profile_times) \
- GetTimeOfDay(&profile_starttime); \
+ __profstamp_##x = do_profile_times ? profile_timestamp() : 0;\
INC_PROFILE_COUNT(x##_count); \
- ADD_PROFILE_COUNT(x##_bytes,n); \
- }
+ ADD_PROFILE_COUNT(x##_bytes, n); \
+ }
+
#define END_PROFILE(x) \
if (do_profile_times) { \
- GetTimeOfDay(&profile_endtime); \
- ADD_PROFILE_COUNT(x##_time,PROFILE_TIME); \
- }
-#define END_PROFILE_NESTED(x) \
- if (do_profile_times) { \
- GetTimeOfDay(&profile_endtime_nested); \
- ADD_PROFILE_COUNT(x##_time,PROFILE_TIME_NESTED); \
+ ADD_PROFILE_COUNT(x##_time, \
+ profile_timestamp() - __profstamp_##x); \
}
-#else
+
+#define START_PROFILE_NESTED(x) START_PROFILE(x)
+#define END_PROFILE_NESTED(x) END_PROFILE(x)
+
+#else /* WITH_PROFILE */
+
#define DO_PROFILE_INC(x)
#define DO_PROFILE_DEC(x)
#define DO_PROFILE_DEC_INC(x,y)
@@ -488,6 +505,7 @@ extern BOOL do_profile_times;
#define START_PROFILE_BYTES(x,n)
#define END_PROFILE(x)
#define END_PROFILE_NESTED(x)
-#endif
+
+#endif /* WITH_PROFILE */
#endif
diff --git a/source/lib/fault.c b/source/lib/fault.c
index 8ae45f24353..dc8c276d02c 100644
--- a/source/lib/fault.c
+++ b/source/lib/fault.c
@@ -151,6 +151,15 @@ void dump_core_setup(const char *progname)
void dump_core(void)
{
+ /* Note that even if core dumping has been disabled, we still set up
+ * the core path. This is to handle the case where core dumping is
+ * turned on in smb.conf and the relevant daemon is not restarted.
+ */
+ if (!lp_enable_core_files()) {
+ DEBUG(0, ("Exiting on internal error (core file administratively disabled\n"));
+ exit(1);
+ }
+
if (*corepath != '\0') {
/* The chdir might fail if we dump core before we finish
* processing the config file.
diff --git a/source/lib/iconv.c b/source/lib/iconv.c
index f738f45efa9..c96243633fb 100644
--- a/source/lib/iconv.c
+++ b/source/lib/iconv.c
@@ -51,6 +51,8 @@
* @sa Samba Developers Guide
**/
+static_decl_charset;
+
static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *);
static size_t ascii_push(void *,const char **, size_t *, char **, size_t *);
static size_t latin1_push(void *,const char **, size_t *, char **, size_t *);
diff --git a/source/lib/module.c b/source/lib/module.c
index 885faf8d80e..092a68cd680 100644
--- a/source/lib/module.c
+++ b/source/lib/module.c
@@ -61,10 +61,14 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe)
return NT_STATUS_UNSUCCESSFUL;
}
- status = init();
-
DEBUG(2, ("Module '%s' loaded\n", module_name));
+ status = init();
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Module '%s' initialization failed: %s\n",
+ module_name, get_friendly_nt_error_msg(status)));
+ }
+
return status;
}
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index e4cb25104ba..bca984444d4 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -981,7 +981,7 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_
ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
- if (smbldap_has_control(ldap_state, ADS_PAGE_CTL_OID) && version == 3) {
+ if (smbldap_has_control(ldap_state->ldap_struct, ADS_PAGE_CTL_OID) && version == 3) {
ldap_state->paged_results = True;
}
@@ -1554,7 +1554,6 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_
/*******************************************************************
Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX.
********************************************************************/
-
char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry)
{
char *utf8_dn, *unix_dn;
@@ -1595,7 +1594,7 @@ char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry)
Check if root-dse has a certain Control or Extension
********************************************************************/
-static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char **attrs, const char *value)
+static BOOL smbldap_check_root_dse(LDAP *ld, const char **attrs, const char *value)
{
LDAPMessage *msg = NULL;
LDAPMessage *entry = NULL;
@@ -1615,7 +1614,7 @@ static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char
return False;
}
- rc = ldap_search_s(ldap_state->ldap_struct, "", LDAP_SCOPE_BASE,
+ rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE,
"(objectclass=*)", CONST_DISCARD(char **, attrs), 0 , &msg);
if (rc != LDAP_SUCCESS) {
@@ -1623,21 +1622,21 @@ static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char
return False;
}
- num_result = ldap_count_entries(ldap_state->ldap_struct, msg);
+ num_result = ldap_count_entries(ld, msg);
if (num_result != 1) {
DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
goto done;
}
- entry = ldap_first_entry(ldap_state->ldap_struct, msg);
+ entry = ldap_first_entry(ld, msg);
if (entry == NULL) {
DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
goto done;
}
- values = ldap_get_values(ldap_state->ldap_struct, entry, attrs[0]);
+ values = ldap_get_values(ld, entry, attrs[0]);
if (values == NULL) {
DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
@@ -1671,28 +1670,28 @@ static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char
Check if LDAP-Server supports a certain Control (OID in string format)
********************************************************************/
-BOOL smbldap_has_control(struct smbldap_state *ldap_state, const char *control)
+BOOL smbldap_has_control(LDAP *ld, const char *control)
{
const char *attrs[] = { "supportedControl", NULL };
- return smbldap_check_root_dse(ldap_state, attrs, control);
+ return smbldap_check_root_dse(ld, attrs, control);
}
/*******************************************************************
Check if LDAP-Server supports a certain Extension (OID in string format)
********************************************************************/
-BOOL smbldap_has_extension(struct smbldap_state *ldap_state, const char *extension)
+BOOL smbldap_has_extension(LDAP *ld, const char *extension)
{
const char *attrs[] = { "supportedExtension", NULL };
- return smbldap_check_root_dse(ldap_state, attrs, extension);
+ return smbldap_check_root_dse(ld, attrs, extension);
}
/*******************************************************************
Check if LDAP-Server holds a given namingContext
********************************************************************/
-BOOL smbldap_has_naming_context(struct smbldap_state *ldap_state, const char *naming_context)
+BOOL smbldap_has_naming_context(LDAP *ld, const char *naming_context)
{
const char *attrs[] = { "namingContexts", NULL };
- return smbldap_check_root_dse(ldap_state, attrs, naming_context);
+ return smbldap_check_root_dse(ld, attrs, naming_context);
}
diff --git a/source/lib/substitute.c b/source/lib/substitute.c
index bfe7dc814ca..ff9deb8a5f0 100644
--- a/source/lib/substitute.c
+++ b/source/lib/substitute.c
@@ -687,7 +687,7 @@ char *alloc_sub_advanced(int snum, const char *user,
a_string = SMB_STRDUP(str);
if (a_string == NULL) {
- DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
+ DEBUG(0, ("alloc_sub_advanced: Out of memory!\n"));
return NULL;
}
diff --git a/source/lib/sysacls.c b/source/lib/sysacls.c
index 61975264fd6..36baf96016c 100644
--- a/source/lib/sysacls.c
+++ b/source/lib/sysacls.c
@@ -1318,7 +1318,6 @@ char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
if ((len + nbytes) > maxlen) {
maxlen += nbytes + 20 * (acl_d->count - i);
if ((text = SMB_REALLOC(text, maxlen)) == NULL) {
- free(oldtext);
errno = ENOMEM;
return NULL;
}
diff --git a/source/lib/time.c b/source/lib/time.c
index a13dcf1646a..749af37cae0 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -39,12 +39,6 @@ int extra_time_offset = 0;
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
#endif
-void get_nttime_max(NTTIME *t)
-{
- /* FIXME: This is incorrect */
- unix_to_nt_time(t, get_time_t_max());
-}
-
/*******************************************************************
External access to time_t_min and time_t_max.
********************************************************************/
diff --git a/source/lib/util.c b/source/lib/util.c
index c023df0b017..d705901244a 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -1948,7 +1948,8 @@ BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
SMB_STRUCT_FLOCK lock;
int ret;
- DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
+ DEBUG(8,("fcntl_lock fd=%d op=%d offset=%.0f count=%.0f type=%d\n",
+ fd,op,(double)offset,(double)count,type));
lock.l_type = type;
lock.l_whence = SEEK_SET;
@@ -1959,8 +1960,10 @@ 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) {
+ int sav = errno;
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)));
+ errno = sav;
return False;
}
@@ -1982,7 +1985,8 @@ BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pi
SMB_STRUCT_FLOCK lock;
int ret;
- DEBUG(8,("fcntl_getlock %d %.0f %.0f %d\n",fd,(double)*poffset,(double)*pcount,*ptype));
+ DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
+ fd,(double)*poffset,(double)*pcount,*ptype));
lock.l_type = *ptype;
lock.l_whence = SEEK_SET;
@@ -1993,8 +1997,10 @@ BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pi
ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
if (ret == -1) {
+ int sav = errno;
DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
(double)*poffset,(double)*pcount,*ptype,strerror(errno)));
+ errno = sav;
return False;
}
@@ -2967,3 +2973,21 @@ BOOL procid_is_local(const struct process_id *pid)
{
return True;
}
+
+int this_is_smp(void)
+{
+#if defined(HAVE_SYSCONF)
+
+#if defined(SYSCONF_SC_NPROC_ONLN)
+ return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
+#elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
+ return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
+#else
+ return 0;
+#endif
+
+#else
+ return 0;
+#endif
+}
+
diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c
index 3be52dd9f79..307f3e3415d 100644
--- a/source/lib/util_sid.c
+++ b/source/lib/util_sid.c
@@ -74,6 +74,8 @@ const DOM_SID global_sid_Builtin_Backup_Operators = /* Builtin backup operators
{ 1, 2, {0,0,0,0,0,5}, {32,551,0,0,0,0,0,0,0,0,0,0,0,0,0}};
const DOM_SID global_sid_Builtin_Replicator = /* Builtin replicator */
{ 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+const DOM_SID global_sid_Builtin_PreWin2kAccess = /* Builtin pre win2k access */
+{ 1, 2, {0,0,0,0,0,5}, {32,554,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}};
@@ -533,6 +535,24 @@ char *sid_binstring(const DOM_SID *sid)
if (!buf)
return NULL;
sid_linearize(buf, len, sid);
+ s = binary_string_rfc2254(buf, len);
+ free(buf);
+ return s;
+}
+
+/*****************************************************************
+ Return the binary string representation of a DOM_SID.
+ Caller must free.
+*****************************************************************/
+
+char *sid_binstring_hex(const DOM_SID *sid)
+{
+ char *buf, *s;
+ int len = sid_size(sid);
+ buf = SMB_MALLOC(len);
+ if (!buf)
+ return NULL;
+ sid_linearize(buf, len, sid);
s = binary_string(buf, len);
free(buf);
return s;
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 12fc2ead95c..1a73a310b62 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -278,7 +278,12 @@ ssize_t read_udp_socket(int fd,char *buf,size_t len)
memset((char *)&lastip,'\0',sizeof(lastip));
ret = (ssize_t)sys_recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
if (ret <= 0) {
- DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
+ /* Don't print a low debug error for a non-blocking socket. */
+ if (errno == EAGAIN) {
+ DEBUG(10,("read socket returned EAGAIN. ERRNO=%s\n",strerror(errno)));
+ } else {
+ DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
+ }
return(0);
}
@@ -1003,7 +1008,7 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
tv.tv_sec = 0;
tv.tv_usec = connect_loop;
- res = sys_select(maxfd+1, &r_fds, &wr_fds, NULL, &tv);
+ res = sys_select_intr(maxfd+1, &r_fds, &wr_fds, NULL, &tv);
if (res < 0)
goto done;
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 439cbea6d93..df84fa90a56 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -1566,7 +1566,7 @@ void strupper_m(char *s)
Caller must free.
**/
-char *binary_string(char *buf, int len)
+char *binary_string_rfc2254(char *buf, int len)
{
char *s;
int i, j;
@@ -1584,6 +1584,22 @@ char *binary_string(char *buf, int len)
return s;
}
+char *binary_string(char *buf, int len)
+{
+ char *s;
+ int i, j;
+ const char *hex = "0123456789ABCDEF";
+ s = SMB_MALLOC(len * 2 + 1);
+ if (!s)
+ return NULL;
+ for (j=i=0;i<len;i++) {
+ s[j] = hex[((unsigned char)buf[i]) >> 4];
+ s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
+ j += 2;
+ }
+ s[j] = 0;
+ return s;
+}
/**
Just a typesafety wrapper for snprintf into a pstring.
**/
diff --git a/source/libads/ads_ldap.c b/source/libads/ads_ldap.c
deleted file mode 100644
index 42821496c34..00000000000
--- a/source/libads/ads_ldap.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Winbind ADS backend functions
-
- Copyright (C) Andrew Tridgell 2001
- Copyright (C) Andrew Bartlett 2002
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#ifdef HAVE_LDAP
-
-/* convert a sid to a DN */
-
-ADS_STATUS ads_sid_to_dn(ADS_STRUCT *ads,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *sid,
- char **dn)
-{
- ADS_STATUS rc;
- LDAPMessage *msg = NULL;
- LDAPMessage *entry = NULL;
- char *ldap_exp;
- char *sidstr = NULL;
- int count;
- char *dn2 = NULL;
-
- const char *attr[] = {
- "dn",
- NULL
- };
-
- if (!(sidstr = sid_binstring(sid))) {
- DEBUG(1,("ads_sid_to_dn: sid_binstring failed!\n"));
- rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- goto done;
- }
-
- if(!(ldap_exp = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr))) {
- DEBUG(1,("ads_sid_to_dn: talloc_asprintf failed!\n"));
- rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- goto done;
- }
-
- rc = ads_search_retry(ads, (void **)(void *)&msg, ldap_exp, attr);
-
- if (!ADS_ERR_OK(rc)) {
- DEBUG(1,("ads_sid_to_dn ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
-
- if ((count = ads_count_replies(ads, msg)) != 1) {
- fstring sid_string;
- DEBUG(1,("ads_sid_to_dn (sid=%s): Not found (count=%d)\n",
- sid_to_string(sid_string, sid), count));
- rc = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
- goto done;
- }
-
- entry = ads_first_entry(ads, msg);
-
- dn2 = ads_get_dn(ads, entry);
-
- if (!dn2) {
- rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- goto done;
- }
-
- *dn = talloc_strdup(mem_ctx, dn2);
-
- if (!*dn) {
- rc = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- goto done;
- }
-
- rc = ADS_ERROR_NT(NT_STATUS_OK);
-
- DEBUG(3,("ads sid_to_dn mapped %s\n", dn2));
-
- SAFE_FREE(dn2);
-done:
- if (msg) ads_msgfree(ads, msg);
- if (dn2) ads_memfree(ads, dn2);
-
- SAFE_FREE(sidstr);
-
- return rc;
-}
-
-#endif
diff --git a/source/libads/ads_struct.c b/source/libads/ads_struct.c
index 9b2179ad316..e546f2ae8ab 100644
--- a/source/libads/ads_struct.c
+++ b/source/libads/ads_struct.c
@@ -118,12 +118,13 @@ void ads_destroy(ADS_STRUCT **ads)
is_mine = (*ads)->is_mine;
#if HAVE_LDAP
- if ((*ads)->ld) ldap_unbind((*ads)->ld);
+ if ((*ads)->ld) {
+ ldap_unbind((*ads)->ld);
+ }
#endif
SAFE_FREE((*ads)->server.realm);
SAFE_FREE((*ads)->server.workgroup);
SAFE_FREE((*ads)->server.ldap_server);
- SAFE_FREE((*ads)->server.ldap_uri);
SAFE_FREE((*ads)->auth.realm);
SAFE_FREE((*ads)->auth.password);
@@ -132,14 +133,13 @@ void ads_destroy(ADS_STRUCT **ads)
SAFE_FREE((*ads)->config.realm);
SAFE_FREE((*ads)->config.bind_path);
- SAFE_FREE((*ads)->config.schema_path);
SAFE_FREE((*ads)->config.ldap_server_name);
- SAFE_FREE((*ads)->schema.sfu_uidnumber_attr);
- SAFE_FREE((*ads)->schema.sfu_gidnumber_attr);
- SAFE_FREE((*ads)->schema.sfu_shell_attr);
- SAFE_FREE((*ads)->schema.sfu_homedir_attr);
- SAFE_FREE((*ads)->schema.sfu_gecos_attr);
+ SAFE_FREE((*ads)->schema.posix_uidnumber_attr);
+ SAFE_FREE((*ads)->schema.posix_gidnumber_attr);
+ SAFE_FREE((*ads)->schema.posix_shell_attr);
+ SAFE_FREE((*ads)->schema.posix_homedir_attr);
+ SAFE_FREE((*ads)->schema.posix_gecos_attr);
ZERO_STRUCTP(*ads);
diff --git a/source/utils/net_ads_cldap.c b/source/libads/cldap.c
index 2e7a28b3222..f438f98599a 100644
--- a/source/utils/net_ads_cldap.c
+++ b/source/libads/cldap.c
@@ -20,33 +20,6 @@
*/
#include "includes.h"
-#include "utils/net.h"
-
-#ifdef HAVE_ADS
-
-#define MAX_DNS_LABEL 255 + 1
-
-struct cldap_netlogon_reply {
- uint32 type;
- uint32 flags;
- UUID_FLAT guid;
-
- char forest[MAX_DNS_LABEL];
- char domain[MAX_DNS_LABEL];
- char hostname[MAX_DNS_LABEL];
-
- char netbios_domain[MAX_DNS_LABEL];
- char netbios_hostname[MAX_DNS_LABEL];
-
- char unk[MAX_DNS_LABEL];
- char user_name[MAX_DNS_LABEL];
- char site_name[MAX_DNS_LABEL];
- char site_name_2[MAX_DNS_LABEL];
-
- uint32 version;
- uint16 lmnt_token;
- uint16 lm20_token;
-};
/*
These seem to be strings as described in RFC1035 4.1.4 and can be:
@@ -93,7 +66,7 @@ static unsigned pull_netlogon_string(char *ret, const char *ptr,
uint8 len = (uint8)*(ptr++);
if ((pret - ret + len + 1) >= MAX_DNS_LABEL) {
- d_fprintf(stderr, "DC returning too long DNS name\n");
+ DEBUG(1,("DC returning too long DNS name\n"));
return 0;
}
@@ -178,13 +151,13 @@ static int send_cldap_netlogon(int sock, const char *domain,
asn1_pop_tag(&data);
if (data.has_error) {
- d_fprintf(stderr, "Failed to build cldap netlogon at offset %d\n", (int)data.ofs);
+ DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data.ofs));
asn1_free(&data);
return -1;
}
if (write(sock, data.data, data.length) != (ssize_t)data.length) {
- d_fprintf(stderr, "failed to send cldap query (%s)\n", strerror(errno));
+ DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
}
asn1_free(&data);
@@ -192,7 +165,17 @@ static int send_cldap_netlogon(int sock, const char *domain,
return 0;
}
-
+static SIG_ATOMIC_T gotalarm;
+
+/***************************************************************
+ Signal function to tell us we timed out.
+****************************************************************/
+
+static void gotalarm_sig(void)
+{
+ gotalarm = 1;
+}
+
/*
receive a cldap netlogon reply
*/
@@ -207,10 +190,20 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
blob = data_blob(NULL, 8192);
+ /* Setup timeout */
+ gotalarm = 0;
+ CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+ alarm(lp_ldap_timeout());
+ /* End setup timeout. */
+
ret = read(sock, blob.data, blob.length);
+ /* Teardown timeout. */
+ CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
+ alarm(0);
+
if (ret <= 0) {
- d_fprintf(stderr, "no reply received to cldap netlogon\n");
+ DEBUG(1,("no reply received to cldap netlogon\n"));
return -1;
}
blob.length = ret;
@@ -232,7 +225,7 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
asn1_end_tag(&data);
if (data.has_error) {
- d_fprintf(stderr, "Failed to parse cldap reply\n");
+ DEBUG(1,("Failed to parse cldap reply\n"));
return -1;
}
@@ -272,94 +265,34 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
return 0;
}
-/*
- do a cldap netlogon query
-*/
-int ads_cldap_netlogon(ADS_STRUCT *ads)
+/*******************************************************************
+ do a cldap netlogon query. Always 389/udp
+*******************************************************************/
+
+BOOL ads_cldap_netlogon(const char *server, const char *realm, struct cldap_netlogon_reply *reply)
{
int sock;
int ret;
- struct cldap_netlogon_reply reply;
- const char *target = opt_host ? opt_host : inet_ntoa(ads->ldap_ip);
- sock = open_udp_socket(target, ads->ldap_port);
+ sock = open_udp_socket(server, LDAP_PORT );
if (sock == -1) {
- d_fprintf(stderr, "Failed to open udp socket to %s:%u\n",
- inet_ntoa(ads->ldap_ip),
- ads->ldap_port);
- return -1;
-
+ DEBUG(2,("ads_cldap_netlogon: Failed to open udp socket to %s\n",
+ server));
+ return False;
}
- ret = send_cldap_netlogon(sock, ads->config.realm, global_myname(), 6);
+ ret = send_cldap_netlogon(sock, realm, global_myname(), 6);
if (ret != 0) {
- return ret;
+ return False;
}
- ret = recv_cldap_netlogon(sock, &reply);
+ ret = recv_cldap_netlogon(sock, reply);
close(sock);
if (ret == -1) {
- return -1;
+ return False;
}
- d_printf("Information for Domain Controller: %s\n\n",
- ads->config.ldap_server_name);
-
- d_printf("Response Type: ");
- switch (reply.type) {
- case SAMLOGON_AD_UNK_R:
- d_printf("SAMLOGON\n");
- break;
- case SAMLOGON_AD_R:
- d_printf("SAMLOGON_USER\n");
- break;
- default:
- d_printf("0x%x\n", reply.type);
- break;
- }
- d_printf("GUID: %s\n",
- smb_uuid_string_static(smb_uuid_unpack_static(reply.guid)));
- d_printf("Flags:\n"
- "\tIs a PDC: %s\n"
- "\tIs a GC of the forest: %s\n"
- "\tIs an LDAP server: %s\n"
- "\tSupports DS: %s\n"
- "\tIs running a KDC: %s\n"
- "\tIs running time services: %s\n"
- "\tIs the closest DC: %s\n"
- "\tIs writable: %s\n"
- "\tHas a hardware clock: %s\n"
- "\tIs a non-domain NC serviced by LDAP server: %s\n",
- (reply.flags & ADS_PDC) ? "yes" : "no",
- (reply.flags & ADS_GC) ? "yes" : "no",
- (reply.flags & ADS_LDAP) ? "yes" : "no",
- (reply.flags & ADS_DS) ? "yes" : "no",
- (reply.flags & ADS_KDC) ? "yes" : "no",
- (reply.flags & ADS_TIMESERV) ? "yes" : "no",
- (reply.flags & ADS_CLOSEST) ? "yes" : "no",
- (reply.flags & ADS_WRITABLE) ? "yes" : "no",
- (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no",
- (reply.flags & ADS_NDNC) ? "yes" : "no");
-
- printf("Forest:\t\t\t%s\n", reply.forest);
- printf("Domain:\t\t\t%s\n", reply.domain);
- printf("Domain Controller:\t%s\n", reply.hostname);
-
- printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain);
- printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname);
-
- if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk);
- if (*reply.user_name) printf("User name:\t%s\n", reply.user_name);
-
- printf("Site Name:\t\t%s\n", reply.site_name);
- printf("Site Name (2):\t\t%s\n", reply.site_name_2);
-
- d_printf("NT Version: %d\n", reply.version);
- d_printf("LMNT Token: %.2x\n", reply.lmnt_token);
- d_printf("LM20 Token: %.2x\n", reply.lm20_token);
-
- return ret;
+ return True;
}
-#endif
diff --git a/source/libads/dns.c b/source/libads/dns.c
new file mode 100644
index 00000000000..d2e263a9d1b
--- /dev/null
+++ b/source/libads/dns.c
@@ -0,0 +1,371 @@
+/*
+ Unix SMB/CIFS implementation.
+ DNS utility library
+ Copyright (C) Gerald (Jerry) Carter 2006.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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"
+
+/* AIX resolv.h uses 'class' in struct ns_rr */
+
+#if defined(AIX)
+# if defined(class)
+# undef class
+# endif
+#endif /* AIX */
+
+/* resolver headers */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+
+#define MAX_DNS_PACKET_SIZE 0xffff
+
+#ifdef NS_HFIXEDSZ /* Bind 8/9 interface */
+# define C_IN ns_c_in
+# define T_A ns_t_a
+# define T_SRV ns_t_srv
+#else
+# ifdef HFIXEDSZ
+# define NS_HFIXEDSZ HFIXEDSZ
+# else
+# define NS_HFIXEDSZ sizeof(HEADER)
+# endif /* HFIXEDSZ */
+# ifdef PACKETSZ
+# define NS_PACKETSZ PACKETSZ
+# else /* 512 is usually the default */
+# define NS_PACKETSZ 512
+# endif /* PACKETSZ */
+# define T_SRV 33
+#endif
+
+/*********************************************************************
+*********************************************************************/
+
+static BOOL ads_dns_parse_query( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+ uint8 **ptr, struct dns_query *q )
+{
+ uint8 *p = *ptr;
+ pstring hostname;
+ int namelen;
+
+ ZERO_STRUCTP( q );
+
+ if ( !start || !end || !q || !*ptr)
+ return False;
+
+ /* See RFC 1035 for details. If this fails, then return. */
+
+ namelen = dn_expand( start, end, p, hostname, sizeof(hostname) );
+ if ( namelen < 0 ) {
+ return False;
+ }
+ p += namelen;
+ q->hostname = talloc_strdup( ctx, hostname );
+
+ /* check that we have space remaining */
+
+ if ( PTR_DIFF(p+4, end) > 0 )
+ return False;
+
+ q->type = RSVAL( p, 0 );
+ q->in_class = RSVAL( p, 2 );
+ p += 4;
+
+ *ptr = p;
+
+ return True;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static BOOL ads_dns_parse_rr( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+ uint8 **ptr, struct dns_rr *rr )
+{
+ uint8 *p = *ptr;
+ pstring hostname;
+ int namelen;
+
+ if ( !start || !end || !rr || !*ptr)
+ return -1;
+
+ ZERO_STRUCTP( rr );
+ /* pull the name from the answer */
+
+ namelen = dn_expand( start, end, p, hostname, sizeof(hostname) );
+ if ( namelen < 0 ) {
+ return -1;
+ }
+ p += namelen;
+ rr->hostname = talloc_strdup( ctx, hostname );
+
+ /* check that we have space remaining */
+
+ if ( PTR_DIFF(p+10, end) > 0 )
+ return False;
+
+ /* pull some values and then skip onto the string */
+
+ rr->type = RSVAL(p, 0);
+ rr->in_class = RSVAL(p, 2);
+ rr->ttl = RIVAL(p, 4);
+ rr->rdatalen = RSVAL(p, 8);
+
+ p += 10;
+
+ /* sanity check the available space */
+
+ if ( PTR_DIFF(p+rr->rdatalen, end ) > 0 ) {
+ return False;
+
+ }
+
+ /* save a point to the rdata for this section */
+
+ rr->rdata = p;
+ p += rr->rdatalen;
+
+ *ptr = p;
+
+ return True;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static BOOL ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+ uint8 **ptr, struct dns_rr_srv *srv )
+{
+ struct dns_rr rr;
+ uint8 *p;
+ pstring dcname;
+ int namelen;
+
+ if ( !start || !end || !srv || !*ptr)
+ return -1;
+
+ /* Parse the RR entry. Coming out of the this, ptr is at the beginning
+ of the next record */
+
+ if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) {
+ DEBUG(1,("ads_dns_parse_rr_srv: Failed to parse RR record\n"));
+ return False;
+ }
+
+ if ( rr.type != T_SRV ) {
+ DEBUG(1,("ads_dns_parse_rr_srv: Bad answer type (%d)\n", rr.type));
+ return False;
+ }
+
+ p = rr.rdata;
+
+ srv->priority = RSVAL(p, 0);
+ srv->weight = RSVAL(p, 2);
+ srv->port = RSVAL(p, 4);
+
+ p += 6;
+
+ namelen = dn_expand( start, end, p, dcname, sizeof(dcname) );
+ if ( namelen < 0 ) {
+ DEBUG(1,("ads_dns_parse_rr_srv: Failed to uncompress name!\n"));
+ return False;
+ }
+ srv->hostname = talloc_strdup( ctx, dcname );
+
+ return True;
+}
+
+
+/*********************************************************************
+ Sort SRV record list based on weight and priority. See RFC 2782.
+*********************************************************************/
+
+static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b )
+{
+ BOOL init = False;
+
+ if ( !init ) {
+ srand( (uint32)time(NULL) );
+ }
+
+ if ( a->priority == b->priority ) {
+
+ /* randomize entries with an equal weight and priority */
+ if ( a->weight == b->weight )
+ return rand() % 2 ? -1 : 1;
+
+ /* higher weights should be sorted lower */
+ if ( a->weight > b->weight )
+ return -1;
+ else
+ return 1;
+ }
+
+ if ( a->priority < b->priority )
+ return -1;
+
+ return 1;
+}
+
+/*********************************************************************
+ Simple wrapper for a DNS SRV query
+*********************************************************************/
+
+NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dns_rr_srv **dclist, int *numdcs )
+{
+ uint8 *buffer = NULL;
+ size_t buf_len;
+ int resp_len = NS_PACKETSZ;
+ struct dns_rr_srv *dcs = NULL;
+ int query_count, answer_count, auth_count, additional_count;
+ uint8 *p = buffer;
+ int rrnum;
+ int idx = 0;
+
+ if ( !ctx || !name || !dclist ) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Send the request. May have to loop several times in case
+ of large replies */
+
+ do {
+ if ( buffer )
+ TALLOC_FREE( buffer );
+
+ buf_len = resp_len * sizeof(uint8);
+
+ if ( (buffer = TALLOC_ARRAY(ctx, uint8, buf_len)) == NULL ) {
+ DEBUG(0,("ads_dns_lookup_srv: talloc() failed!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if ( (resp_len = res_query(name, C_IN, T_SRV, buffer, buf_len)) < 0 ) {
+ DEBUG(1,("ads_dns_lookup_srv: Failed to resolve %s (%s)\n", name, strerror(errno)));
+ TALLOC_FREE( buffer );
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ } while ( buf_len < resp_len && resp_len < MAX_DNS_PACKET_SIZE );
+
+ p = buffer;
+
+ /* For some insane reason, the ns_initparse() et. al. routines are only
+ available in libresolv.a, and not the shared lib. Who knows why....
+ So we have to parse the DNS reply ourselves */
+
+ /* Pull the answer RR's count from the header. Use the NMB ordering macros */
+
+ query_count = RSVAL( p, 4 );
+ answer_count = RSVAL( p, 6 );
+ auth_count = RSVAL( p, 8 );
+ additional_count = RSVAL( p, 10 );
+
+ DEBUG(4,("ads_dns_lookup_srv: %d records returned in the answer section.\n",
+ answer_count));
+
+ if ( (dcs = TALLOC_ARRAY(ctx, struct dns_rr_srv, answer_count)) == NULL ) {
+ DEBUG(0,("ads_dns_lookup_srv: talloc() failure for %d char*'s\n",
+ answer_count));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* now skip the header */
+
+ p += NS_HFIXEDSZ;
+
+ /* parse the query section */
+
+ for ( rrnum=0; rrnum<query_count; rrnum++ ) {
+ struct dns_query q;
+
+ if ( !ads_dns_parse_query( ctx, buffer, buffer+resp_len, &p, &q ) ) {
+ DEBUG(1,("ads_dns_lookup_srv: Failed to parse query record!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* now we are at the answer section */
+
+ for ( rrnum=0; rrnum<answer_count; rrnum++ ) {
+ if ( !ads_dns_parse_rr_srv( ctx, buffer, buffer+resp_len, &p, &dcs[rrnum] ) ) {
+ DEBUG(1,("ads_dns_lookup_srv: Failed to parse answer record!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ idx = rrnum;
+
+ /* Parse the authority section */
+ /* just skip these for now */
+
+ for ( rrnum=0; rrnum<auth_count; rrnum++ ) {
+ struct dns_rr rr;
+
+ if ( !ads_dns_parse_rr( ctx, buffer, buffer+resp_len, &p, &rr ) ) {
+ DEBUG(1,("ads_dns_lookup_srv: Failed to parse authority record!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* Parse the additional records section */
+
+ for ( rrnum=0; rrnum<additional_count; rrnum++ ) {
+ struct dns_rr rr;
+ int i;
+
+ if ( !ads_dns_parse_rr( ctx, buffer, buffer+resp_len, &p, &rr ) ) {
+ DEBUG(1,("ads_dns_lookup_srv: Failed to parse additional records section!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* only interested in A records as a shortcut for having to come
+ back later and lookup the name */
+
+ if ( (rr.type != T_A) || (rr.rdatalen != 4) )
+ continue;
+
+ for ( i=0; i<idx; i++ ) {
+ if ( strcmp( rr.hostname, dcs[i].hostname ) == 0 ) {
+ uint8 *buf = (uint8*)&dcs[i].ip.s_addr;
+ memcpy( buf, rr.rdata, 4 );
+ }
+ }
+ }
+
+ qsort( dcs, idx, sizeof(struct dns_rr_srv), QSORT_CAST dnssrvcmp );
+
+ *dclist = dcs;
+ *numdcs = idx;
+
+ return NT_STATUS_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+NTSTATUS ads_dns_query_dcs( TALLOC_CTX *ctx, const char *domain, struct dns_rr_srv **dclist, int *numdcs )
+{
+ pstring name;
+
+ snprintf( name, sizeof(name), "_ldap._tcp.dc._msdcs.%s", domain );
+
+ return ads_dns_lookup_srv( ctx, name, dclist, numdcs );
+}
+
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index e5211813d36..2dfdc31dd56 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -65,6 +65,7 @@ int kerberos_kinit_password_ext(const char *principal,
time_t *renew_till_time,
const char *cache_name,
BOOL request_pac,
+ BOOL add_netbios_addr,
time_t renewable_time)
{
krb5_context ctx = NULL;
@@ -73,6 +74,7 @@ int kerberos_kinit_password_ext(const char *principal,
krb5_principal me;
krb5_creds my_creds;
krb5_get_init_creds_opt opt;
+ smb_krb5_addresses *addr = NULL;
initialize_krb5_error_table();
if ((code = krb5_init_context(&ctx)))
@@ -90,7 +92,7 @@ int kerberos_kinit_password_ext(const char *principal,
return code;
}
- if ((code = krb5_parse_name(ctx, principal, &me))) {
+ if ((code = smb_krb5_parse_name(ctx, principal, &me))) {
krb5_free_context(ctx);
return code;
}
@@ -101,19 +103,36 @@ int kerberos_kinit_password_ext(const char *principal,
if (request_pac) {
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
- krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+ code = krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+ if (code) {
+ krb5_free_principal(ctx, me);
+ krb5_free_context(ctx);
+ return code;
+ }
#endif
}
+ if (add_netbios_addr) {
+ code = smb_krb5_gen_netbios_krb5_address(&addr);
+ if (code) {
+ krb5_free_principal(ctx, me);
+ krb5_free_context(ctx);
+ return code;
+ }
+ krb5_get_init_creds_opt_set_address_list(&opt, addr->addrs);
+ }
+
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
kerb_prompter, NULL, 0, NULL, &opt)))
{
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
return code;
}
if ((code = krb5_cc_initialize(ctx, cc, me))) {
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
@@ -122,6 +141,7 @@ int kerberos_kinit_password_ext(const char *principal,
if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
krb5_cc_close(ctx, cc);
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
@@ -137,6 +157,7 @@ int kerberos_kinit_password_ext(const char *principal,
}
krb5_cc_close(ctx, cc);
+ smb_krb5_free_addresses(ctx, addr);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
krb5_free_context(ctx);
@@ -178,7 +199,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
}
ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
- &ads->auth.expire, NULL, NULL, False, ads->auth.renewable);
+ &ads->auth.expire, NULL, NULL, False, False, ads->auth.renewable);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
@@ -260,21 +281,21 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
char *unparsed_name = NULL, *salt_princ_s = NULL;
krb5_principal ret_princ = NULL;
- if (krb5_unparse_name(context, host_princ, &unparsed_name) != 0) {
+ if (smb_krb5_unparse_name(context, host_princ, &unparsed_name) != 0) {
return (krb5_principal)NULL;
}
if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) {
- krb5_free_unparsed_name(context, unparsed_name);
+ SAFE_FREE(unparsed_name);
return (krb5_principal)NULL;
}
- if (krb5_parse_name(context, salt_princ_s, &ret_princ) != 0) {
- krb5_free_unparsed_name(context, unparsed_name);
+ if (smb_krb5_parse_name(context, salt_princ_s, &ret_princ) != 0) {
+ SAFE_FREE(unparsed_name);
SAFE_FREE(salt_princ_s);
return (krb5_principal)NULL;
}
- krb5_free_unparsed_name(context, unparsed_name);
+ SAFE_FREE(unparsed_name);
SAFE_FREE(salt_princ_s);
return ret_princ;
}
@@ -308,11 +329,11 @@ BOOL kerberos_secrets_store_salting_principal(const char *service,
asprintf(&princ_s, "%s@%s", service, lp_realm());
}
- if (krb5_parse_name(context, princ_s, &princ) != 0) {
+ if (smb_krb5_parse_name(context, princ_s, &princ) != 0) {
goto out;
}
- if (krb5_unparse_name(context, princ, &unparsed_name) != 0) {
+ if (smb_krb5_unparse_name(context, princ, &unparsed_name) != 0) {
goto out;
}
@@ -331,10 +352,8 @@ BOOL kerberos_secrets_store_salting_principal(const char *service,
SAFE_FREE(key);
SAFE_FREE(princ_s);
+ SAFE_FREE(unparsed_name);
- if (unparsed_name) {
- krb5_free_unparsed_name(context, unparsed_name);
- }
if (context) {
krb5_free_context(context);
}
@@ -396,8 +415,8 @@ static krb5_error_code get_service_ticket(krb5_context ctx,
asprintf(&service_s, "%s@%s", service_principal, lp_realm());
}
- if ((err = krb5_parse_name(ctx, service_s, &creds.server))) {
- DEBUG(0,("get_service_ticket: krb5_parse_name %s failed: %s\n",
+ if ((err = smb_krb5_parse_name(ctx, service_s, &creds.server))) {
+ DEBUG(0,("get_service_ticket: smb_krb5_parse_name %s failed: %s\n",
service_s, error_message(err)));
goto out;
}
@@ -476,8 +495,8 @@ static BOOL verify_service_password(krb5_context ctx,
asprintf(&salting_s, "%s@%s", salting_principal, lp_realm());
}
- if ((err = krb5_parse_name(ctx, salting_s, &salting_kprinc))) {
- DEBUG(0,("verify_service_password: krb5_parse_name %s failed: %s\n",
+ if ((err = smb_krb5_parse_name(ctx, salting_s, &salting_kprinc))) {
+ DEBUG(0,("verify_service_password: smb_krb5_parse_name %s failed: %s\n",
salting_s, error_message(err)));
goto out;
}
@@ -814,6 +833,7 @@ int kerberos_kinit_password(const char *principal,
0,
cache_name,
False,
+ False,
0);
}
diff --git a/source/libads/kerberos_keytab.c b/source/libads/kerberos_keytab.c
index f6ed107ee00..fc87b687d14 100644
--- a/source/libads/kerberos_keytab.c
+++ b/source/libads/kerberos_keytab.c
@@ -130,9 +130,9 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
/* Guess at how the KDC is salting keys for this principal. */
kerberos_derive_salting_principal(princ_s);
- ret = krb5_parse_name(context, princ_s, &princ);
+ ret = smb_krb5_parse_name(context, princ_s, &princ);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
+ DEBUG(1,("ads_keytab_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
goto out;
}
@@ -150,9 +150,10 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
BOOL compare_name_ok = False;
- ret = krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+ ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
if (ret) {
- DEBUG(1,("ads_keytab_add_entry: krb5_unparse_name failed (%s)\n", error_message(ret)));
+ DEBUG(1,("ads_keytab_add_entry: smb_krb5_unparse_name failed (%s)\n",
+ error_message(ret)));
goto out;
}
@@ -176,8 +177,7 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
ktprinc, kt_entry.vno));
}
- krb5_free_unparsed_name(context, ktprinc);
- ktprinc = NULL;
+ SAFE_FREE(ktprinc);
if (compare_name_ok) {
if (kt_entry.vno == kvno - 1) {
@@ -581,9 +581,9 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
char *p;
/* This returns a malloc'ed string in ktprinc. */
- ret = krb5_unparse_name(context, kt_entry.principal, &ktprinc);
+ ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
if (ret) {
- DEBUG(1,("krb5_unparse_name failed (%s)\n", error_message(ret)));
+ DEBUG(1,("smb_krb5_unparse_name failed (%s)\n", error_message(ret)));
goto done;
}
/*
@@ -606,12 +606,12 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
break;
}
if (!strcmp(oldEntries[i], ktprinc)) {
- krb5_free_unparsed_name(context, ktprinc);
+ SAFE_FREE(ktprinc);
break;
}
}
if (i == found) {
- krb5_free_unparsed_name(context, ktprinc);
+ SAFE_FREE(ktprinc);
}
}
smb_krb5_kt_free_entry(context, &kt_entry);
@@ -620,7 +620,7 @@ int ads_keytab_create_default(ADS_STRUCT *ads)
ret = 0;
for (i = 0; oldEntries[i]; i++) {
ret |= ads_keytab_add_entry(ads, oldEntries[i]);
- krb5_free_unparsed_name(context, oldEntries[i]);
+ SAFE_FREE(oldEntries[i]);
}
krb5_kt_end_seq_get(context, keytab, &cursor);
}
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index 934c1131eb0..525a9cfa27c 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -90,9 +90,10 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
if (ret != KRB5_KT_END && ret != ENOENT ) {
while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
- ret = krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
+ ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
if (ret) {
- DEBUG(1, ("ads_keytab_verify_ticket: krb5_unparse_name failed (%s)\n", error_message(ret)));
+ DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
+ error_message(ret)));
goto out;
}
@@ -138,8 +139,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
}
/* Free the name we parsed. */
- krb5_free_unparsed_name(context, entry_princ_s);
- entry_princ_s = NULL;
+ SAFE_FREE(entry_princ_s);
/* Free the entry we just read. */
smb_krb5_kt_free_entry(context, &kt_entry);
@@ -165,9 +165,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
}
}
- if (entry_princ_s) {
- krb5_free_unparsed_name(context, entry_princ_s);
- }
+ SAFE_FREE(entry_princ_s);
{
krb5_keytab_entry zero_kt_entry;
@@ -288,7 +286,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
***********************************************************************************/
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
- const char *realm, const DATA_BLOB *ticket,
+ const char *realm, time_t time_offset,
+ const DATA_BLOB *ticket,
char **principal, PAC_DATA **pac_data,
DATA_BLOB *ap_rep,
DATA_BLOB *session_key)
@@ -325,6 +324,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
return NT_STATUS_LOGON_FAILURE;
}
+ if (time_offset != 0) {
+ krb5_set_real_time(context, time(NULL) + time_offset, 0);
+ }
+
ret = krb5_set_default_realm(context, realm);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
@@ -343,9 +346,9 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
asprintf(&host_princ_s, "%s$", global_myname());
strlower_m(host_princ_s);
- ret = krb5_parse_name(context, host_princ_s, &host_princ);
+ ret = smb_krb5_parse_name(context, host_princ_s, &host_princ);
if (ret) {
- DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n",
+ DEBUG(1,("ads_verify_ticket: smb_krb5_parse_name(%s) failed (%s)\n",
host_princ_s, error_message(ret)));
goto out;
}
@@ -459,8 +462,8 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
#endif
#endif
- if ((ret = krb5_unparse_name(context, client_principal, principal))) {
- DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
+ if ((ret = smb_krb5_unparse_name(context, client_principal, principal))) {
+ DEBUG(3,("ads_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
goto out;
diff --git a/source/libads/krb5_errs.c b/source/libads/krb5_errs.c
index 0c2e704702c..e73482522b8 100644
--- a/source/libads/krb5_errs.c
+++ b/source/libads/krb5_errs.c
@@ -40,7 +40,7 @@ static const struct {
#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_POLICY, NT_STATUS_INVALID_WORKSTATION},
{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},
diff --git a/source/libads/krb5_setpw.c b/source/libads/krb5_setpw.c
index 415c1e92294..254ca7b2a3a 100644
--- a/source/libads/krb5_setpw.c
+++ b/source/libads/krb5_setpw.c
@@ -521,7 +521,7 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
realm++;
asprintf(&princ_name, "kadmin/changepw@%s", realm);
- ret = krb5_parse_name(context, princ_name, &creds.server);
+ ret = smb_krb5_parse_name(context, princ_name, &creds.server);
if (ret) {
krb5_cc_close(context, ccache);
krb5_free_context(context);
@@ -531,7 +531,7 @@ ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
free(princ_name);
/* parse the principal we got as a function argument */
- ret = krb5_parse_name(context, princ, &principal);
+ ret = smb_krb5_parse_name(context, princ, &principal);
if (ret) {
krb5_cc_close(context, ccache);
krb5_free_principal(context, creds.server);
@@ -633,7 +633,7 @@ static ADS_STATUS ads_krb5_chg_password(const char *kdc_host,
return ADS_ERROR_KRB5(ret);
}
- if ((ret = krb5_parse_name(context, principal,
+ if ((ret = smb_krb5_parse_name(context, principal,
&princ))) {
krb5_free_context(context);
DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret)));
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index c2ebf14d2f9..bac85f3222b 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -112,31 +112,52 @@ static int ldap_search_with_timeout(LDAP *ld,
/*
try a connection to a given ldap server, returning True and setting the servers IP
in the ads struct if successful
-
- TODO : add a negative connection cache in here leveraged off of the one
- found in the rpc code. --jerry
*/
-BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
+BOOL ads_try_connect(ADS_STRUCT *ads, const char *server )
{
char *srv;
+ struct cldap_netlogon_reply cldap_reply;
if (!server || !*server) {
return False;
}
-
- DEBUG(5,("ads_try_connect: trying ldap server '%s' port %u\n", server, port));
+
+ DEBUG(5,("ads_try_connect: sending CLDAP request to %s\n", server));
/* this copes with inet_ntoa brokenness */
+
srv = SMB_STRDUP(server);
- ads->ld = ldap_open_with_timeout(srv, port, lp_ldap_timeout());
- if (!ads->ld) {
- free(srv);
+ ZERO_STRUCT( cldap_reply );
+
+ if ( !ads_cldap_netlogon( srv, ads->server.realm, &cldap_reply ) ) {
+ DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv));
+ return False;
+ }
+
+ /* Check the CLDAP reply flags */
+
+ if ( !(cldap_reply.flags & ADS_LDAP) ) {
+ DEBUG(1,("ads_try_connect: %s's CLDAP reply says it is not an LDAP server!\n",
+ srv));
+ SAFE_FREE( srv );
return False;
}
- ads->ldap_port = port;
+
+ /* Fill in the ads->config values */
+
+ SAFE_FREE(ads->config.realm);
+ SAFE_FREE(ads->config.bind_path);
+ SAFE_FREE(ads->config.ldap_server_name);
+
+ ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.hostname);
+ strupper_m(cldap_reply.domain);
+ ads->config.realm = SMB_STRDUP(cldap_reply.domain);
+ ads->config.bind_path = ads_build_dn(ads->config.realm);
+
+ ads->ldap_port = LDAP_PORT;
ads->ldap_ip = *interpret_addr2(srv);
- free(srv);
+ SAFE_FREE(srv);
/* cache the successful connection */
@@ -145,29 +166,6 @@ BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
return True;
}
-/*
- try a connection to a given ldap server, based on URL, returning True if successful
- */
-static BOOL ads_try_connect_uri(ADS_STRUCT *ads)
-{
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
- DEBUG(5,("ads_try_connect: trying ldap server at URI '%s'\n",
- ads->server.ldap_uri));
-
-
- if (ldap_initialize((LDAP**)&(ads->ld), ads->server.ldap_uri) == LDAP_SUCCESS) {
- return True;
- }
- DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
-
-#else
-
- DEBUG(1, ("no URL support in LDAP libs!\n"));
-#endif
-
- return False;
-}
-
/**********************************************************************
Try to find an AD dc using our internal name resolution routines
Try the realm first and then then workgroup name if netbios is not
@@ -233,8 +231,6 @@ again:
/* if we fail this loop, then giveup since all the IP addresses returned were dead */
for ( i=0; i<count; i++ ) {
- /* since this is an ads conection request, default to LDAP_PORT is not set */
- int port = (ip_list[i].port!=PORT_NONE) ? ip_list[i].port : LDAP_PORT;
fstring server;
fstrcpy( server, inet_ntoa(ip_list[i].ip) );
@@ -242,7 +238,7 @@ again:
if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) )
continue;
- if ( ads_try_connect(ads, server, port) ) {
+ if ( ads_try_connect(ads, server) ) {
SAFE_FREE(ip_list);
return True;
}
@@ -270,16 +266,10 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ads->last_attempt = time(NULL);
ads->ld = NULL;
- /* try with a URL based server */
-
- if (ads->server.ldap_uri &&
- ads_try_connect_uri(ads)) {
- goto got_connection;
- }
-
/* try with a user specified server */
+
if (ads->server.ldap_server &&
- ads_try_connect(ads, ads->server.ldap_server, LDAP_PORT)) {
+ ads_try_connect(ads, ads->server.ldap_server)) {
goto got_connection;
}
@@ -292,22 +282,12 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
got_connection:
DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));
- status = ads_server_info(ads);
- if (!ADS_ERR_OK(status)) {
- DEBUG(1,("Failed to get ldap server info\n"));
- return status;
- }
-
- ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
-
- status = ADS_ERROR(smb_ldap_start_tls(ads->ld, version));
- if (!ADS_ERR_OK(status)) {
- return status;
- }
-
if (!ads->auth.user_name) {
/* have to use the userPrincipalName value here and
- not servicePrincipalName; found by Guenther Deschner @ Sernet */
+ not servicePrincipalName; found by Guenther Deschner @ Sernet.
+
+ Is this still correct? The comment does not match
+ the code. --jerry */
asprintf(&ads->auth.user_name, "host/%s", global_myname() );
}
@@ -331,10 +311,35 @@ got_connection:
}
#endif
+ /* If the caller() requested no LDAP bind, then we are done */
+
if (ads->auth.flags & ADS_AUTH_NO_BIND) {
return ADS_SUCCESS;
}
+
+ /* Otherwise setup the TCP LDAP session */
+
+ if ( (ads->ld = ldap_open_with_timeout(ads->config.ldap_server_name,
+ LDAP_PORT, lp_ldap_timeout())) == NULL )
+ {
+ return ADS_ERROR(LDAP_OPERATIONS_ERROR);
+ }
+ ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ status = ADS_ERROR(smb_ldap_start_tls(ads->ld, version));
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ /* fill in the current time and offsets */
+
+ status = ads_current_time( ads );
+ if ( !ADS_ERR_OK(status) ) {
+ return status;
+ }
+
+ /* Now do the bind */
+
if (ads->auth.flags & ADS_AUTH_ANON_BIND) {
return ADS_ERROR(ldap_simple_bind_s( ads->ld, NULL, NULL));
}
@@ -440,21 +445,25 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals)
* @param cookie The paged results cookie to be returned on subsequent calls
* @return status of search
**/
-ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res,
- int *count, void **cookie)
+ADS_STATUS ads_do_paged_search_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args, void **res,
+ int *count, void **cookie)
{
int rc, i, version;
char *utf8_expr, *utf8_path, **search_attrs;
- LDAPControl PagedResults, NoReferrals, *controls[3], **rcontrols;
+ LDAPControl PagedResults, NoReferrals, ExtendedDn, *controls[4], **rcontrols;
BerElement *cookie_be = NULL;
struct berval *cookie_bv= NULL;
+ BerElement *extdn_be = NULL;
+ struct berval *extdn_bv= NULL;
+
TALLOC_CTX *ctx;
+ ads_control *external_control = (ads_control *) args;
*res = NULL;
- if (!(ctx = talloc_init("ads_do_paged_search")))
+ if (!(ctx = talloc_init("ads_do_paged_search_args")))
return ADS_ERROR(LDAP_NO_MEMORY);
/* 0 means the conversion worked but the result was empty
@@ -504,10 +513,47 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
NoReferrals.ldctl_value.bv_len = 0;
NoReferrals.ldctl_value.bv_val = CONST_DISCARD(char *, "");
+ if (external_control && strequal(external_control->control, ADS_EXTENDED_DN_OID)) {
+
+ ExtendedDn.ldctl_oid = CONST_DISCARD(char *, external_control->control);
+ ExtendedDn.ldctl_iscritical = (char) external_control->critical;
+
+ /* win2k does not accept a ldctl_value beeing passed in */
+
+ if (external_control->val != 0) {
- controls[0] = &NoReferrals;
- controls[1] = &PagedResults;
- controls[2] = NULL;
+ if ((extdn_be = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ rc = LDAP_NO_MEMORY;
+ goto done;
+ }
+
+ if ((ber_printf(extdn_be, "{i}", (ber_int_t) external_control->val)) == -1) {
+ rc = LDAP_NO_MEMORY;
+ goto done;
+ }
+ if ((ber_flatten(extdn_be, &extdn_bv)) == -1) {
+ rc = LDAP_NO_MEMORY;
+ goto done;
+ }
+
+ ExtendedDn.ldctl_value.bv_len = extdn_bv->bv_len;
+ ExtendedDn.ldctl_value.bv_val = extdn_bv->bv_val;
+
+ } else {
+ ExtendedDn.ldctl_value.bv_len = 0;
+ ExtendedDn.ldctl_value.bv_val = NULL;
+ }
+
+ controls[0] = &NoReferrals;
+ controls[1] = &PagedResults;
+ controls[2] = &ExtendedDn;
+ controls[3] = NULL;
+
+ } else {
+ controls[0] = &NoReferrals;
+ controls[1] = &PagedResults;
+ controls[2] = NULL;
+ }
/* we need to disable referrals as the openldap libs don't
handle them and paged results at the same time. Using them
@@ -528,7 +574,7 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
ber_bvfree(cookie_bv);
if (rc) {
- DEBUG(3,("ads_do_paged_search: ldap_search_with_timeout(%s) -> %s\n", expr,
+ DEBUG(3,("ads_do_paged_search_args: ldap_search_with_timeout(%s) -> %s\n", expr,
ldap_err2string(rc)));
goto done;
}
@@ -560,12 +606,29 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
done:
talloc_destroy(ctx);
+
+ if (extdn_be) {
+ ber_free(extdn_be, 1);
+ }
+
+ if (extdn_bv) {
+ ber_bvfree(extdn_bv);
+ }
+
/* if/when we decide to utf8-encode attrs, take out this next line */
str_list_free(&search_attrs);
return ADS_ERROR(rc);
}
+ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void **res,
+ int *count, void **cookie)
+{
+ return ads_do_paged_search_args(ads, bind_path, scope, expr, attrs, NULL, res, count, cookie);
+}
+
/**
* Get all results for a search. This uses ads_do_paged_search() to return
@@ -578,16 +641,16 @@ done:
* @param res ** which will contain results - free res* with ads_msgfree()
* @return status of search
**/
-ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
- int scope, const char *expr,
- const char **attrs, void **res)
+ADS_STATUS ads_do_search_all_args(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void *args, void **res)
{
void *cookie = NULL;
int count = 0;
ADS_STATUS status;
*res = NULL;
- status = ads_do_paged_search(ads, bind_path, scope, expr, attrs, res,
+ status = ads_do_paged_search_args(ads, bind_path, scope, expr, attrs, args, res,
&count, &cookie);
if (!ADS_ERR_OK(status))
@@ -599,8 +662,8 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
ADS_STATUS status2;
LDAPMessage *msg, *next;
- status2 = ads_do_paged_search(ads, bind_path, scope, expr,
- attrs, &res2, &count, &cookie);
+ status2 = ads_do_paged_search_args(ads, bind_path, scope, expr,
+ attrs, args, &res2, &count, &cookie);
if (!ADS_ERR_OK(status2)) break;
@@ -621,6 +684,13 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
return status;
}
+ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
+ int scope, const char *expr,
+ const char **attrs, void **res)
+{
+ return ads_do_search_all_args(ads, bind_path, scope, expr, attrs, NULL, res);
+}
+
/**
* Run a function on all results for a search. Uses ads_do_paged_search() and
* runs the function as each page is returned, using ads_process_results()
@@ -975,6 +1045,7 @@ ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
name, (const void **) vals);
}
+#if 0
/**
* Add a single ber-encoded value to a mod list
* @param ctx An initialized TALLOC_CTX
@@ -995,6 +1066,7 @@ static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods,
return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES,
name, (const void **) values);
}
+#endif
/**
* Perform an ldap modify
@@ -1416,105 +1488,33 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n
* @return 0 upon success, or non-zero otherwise
**/
-static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name,
- uint32 account_type,
- const char *org_unit)
+ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
+ const char *org_unit)
{
- ADS_STATUS ret, status;
- char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
+ ADS_STATUS ret;
+ char *samAccountName, *controlstr;
TALLOC_CTX *ctx;
ADS_MODLIST mods;
+ char *new_dn;
const char *objectClass[] = {"top", "person", "organizationalPerson",
"user", "computer", NULL};
- const char *servicePrincipalName[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
- char *psp, *psp2, *psp3, *psp4;
- unsigned acct_control;
- unsigned exists=0;
- fstring my_fqdn;
LDAPMessage *res = NULL;
- int i, next_spn;
-
+ uint32 acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\
+ UF_DONT_EXPIRE_PASSWD |\
+ UF_ACCOUNTDISABLE );
+
if (!(ctx = talloc_init("ads_add_machine_acct")))
return ADS_ERROR(LDAP_NO_MEMORY);
ret = ADS_ERROR(LDAP_NO_MEMORY);
+
+ new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_name, org_unit);
+ samAccountName = talloc_asprintf(ctx, "%s$", machine_name);
- name_to_fqdn(my_fqdn, machine_name);
-
- status = ads_find_machine_acct(ads, (void **)(void *)&res, machine_name);
- if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
- char *dn_string = ads_get_dn(ads, res);
- if (!dn_string) {
- DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
- goto done;
- }
- new_dn = talloc_strdup(ctx, dn_string);
- ads_memfree(ads,dn_string);
- DEBUG(0, ("ads_add_machine_acct: Host account for %s already exists - modifying old account\n",
- machine_name));
- exists=1;
- } else {
- char *ou_str = ads_ou_string(ads,org_unit);
- if (!ou_str) {
- DEBUG(1, ("ads_add_machine_acct: ads_ou_string returned NULL (malloc failure?)\n"));
- goto done;
- }
- new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", machine_name, ou_str,
- ads->config.bind_path);
-
- SAFE_FREE(ou_str);
- }
-
- if (!new_dn) {
- goto done;
- }
-
- if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", machine_name)))
- goto done;
- if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))
- goto done;
- servicePrincipalName[0] = talloc_asprintf(ctx, "HOST/%s", machine_name);
- psp = talloc_asprintf(ctx, "HOST/%s.%s",
- machine_name,
- ads->config.realm);
- strlower_m(&psp[5]);
- servicePrincipalName[1] = psp;
- servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", machine_name);
- psp2 = talloc_asprintf(ctx, "CIFS/%s.%s",
- machine_name,
- ads->config.realm);
- strlower_m(&psp2[5]);
- servicePrincipalName[3] = psp2;
-
- /* Ensure servicePrincipalName[4] and [5] are unique. */
- strlower_m(my_fqdn);
- psp3 = talloc_asprintf(ctx, "CIFS/%s", my_fqdn);
- strlower_m(&psp3[5]);
-
- next_spn = 4;
- for (i = 0; i < next_spn; i++) {
- if (strequal(servicePrincipalName[i], psp3))
- break;
- }
- if (i == next_spn) {
- servicePrincipalName[next_spn++] = psp3;
- }
-
- psp4 = talloc_asprintf(ctx, "HOST/%s", my_fqdn);
- strlower_m(&psp4[5]);
- for (i = 0; i < next_spn; i++) {
- if (strequal(servicePrincipalName[i], psp4))
- break;
- }
- if (i == next_spn) {
- servicePrincipalName[next_spn++] = psp4;
- }
-
- if (!(samAccountName = talloc_asprintf(ctx, "%s$", machine_name))) {
+ if ( !new_dn || !samAccountName ) {
goto done;
}
-
- acct_control = account_type | UF_DONT_EXPIRE_PASSWD;
+
#ifndef ENCTYPE_ARCFOUR_HMAC
acct_control |= UF_USE_DES_KEY_ONLY;
#endif
@@ -1526,44 +1526,18 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *machine_name
if (!(mods = ads_init_mods(ctx))) {
goto done;
}
-
- if (!exists) {
- ads_mod_str(ctx, &mods, "cn", machine_name);
- ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
- ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
- }
+
+ ads_mod_str(ctx, &mods, "cn", machine_name);
+ ads_mod_str(ctx, &mods, "sAMAccountName", samAccountName);
+ 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);
- ads_mod_str(ctx, &mods, "operatingSystem", "Samba");
- ads_mod_str(ctx, &mods, "operatingSystemVersion", SAMBA_VERSION_STRING);
-
- if (!exists) {
- ret = ads_gen_add(ads, new_dn, mods);
- } else {
- ret = ads_gen_mod(ads, new_dn, mods);
- }
- if (!ADS_ERR_OK(ret)) {
- goto done;
- }
+ ret = ads_gen_add(ads, new_dn, mods);
- /* Do not fail if we can't set security descriptor
- * it shouldn't be mandatory and probably we just
- * don't have enough rights to do it.
- */
- if (!exists) {
- status = ads_set_machine_sd(ads, machine_name, new_dn);
-
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("Warning: ads_set_machine_sd: %s\n",
- ads_errstr(status)));
- }
- }
done:
ads_msgfree(ads, res);
talloc_destroy(ctx);
+
return ret;
}
@@ -1665,6 +1639,8 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
{"dnsRecord", False, dump_binary},
{"objectSid", False, dump_sid},
{"tokenGroups", False, dump_sid},
+ {"tokenGroupsNoGCAcceptable", False, dump_sid},
+ {"tokengroupsGlobalandUniversal", False, dump_sid},
{NULL, True, NULL}
};
int i;
@@ -1777,240 +1753,6 @@ int ads_count_replies(ADS_STRUCT *ads, void *res)
}
/**
- * Join a machine to a realm
- * Creates the machine account and sets the machine password
- * @param ads connection to ads server
- * @param machine name of host to add
- * @param org_unit Organizational unit to place machine in
- * @return status of join
- **/
-ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
- uint32 account_type, const char *org_unit)
-{
- ADS_STATUS status;
- LDAPMessage *res = NULL;
- char *machine;
-
- /* machine name must be lowercase */
- machine = SMB_STRDUP(machine_name);
- strlower_m(machine);
-
- /*
- status = ads_find_machine_acct(ads, (void **)&res, machine);
- if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
- DEBUG(0, ("Host account for %s already exists - deleting old account\n", machine));
- status = ads_leave_realm(ads, machine);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n",
- machine, ads->config.realm));
- return status;
- }
- }
- */
-
- status = ads_add_machine_acct(ads, machine, account_type, org_unit);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("ads_join_realm: ads_add_machine_acct failed (%s): %s\n", machine, ads_errstr(status)));
- SAFE_FREE(machine);
- return status;
- }
-
- status = ads_find_machine_acct(ads, (void **)(void *)&res, machine);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("ads_join_realm: Host account test failed for machine %s\n", machine));
- SAFE_FREE(machine);
- return status;
- }
-
- SAFE_FREE(machine);
- ads_msgfree(ads, res);
-
- return status;
-}
-
-/**
- * Delete a machine from the realm
- * @param ads connection to ads server
- * @param hostname Machine to remove
- * @return status of delete
- **/
-ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
-{
- ADS_STATUS status;
- void *res, *msg;
- char *hostnameDN, *host;
- int rc;
- LDAPControl ldap_control;
- LDAPControl * pldap_control[2] = {NULL, NULL};
-
- pldap_control[0] = &ldap_control;
- memset(&ldap_control, 0, sizeof(LDAPControl));
- ldap_control.ldctl_oid = (char *)LDAP_SERVER_TREE_DELETE_OID;
-
- /* hostname must be lowercase */
- host = SMB_STRDUP(hostname);
- strlower_m(host);
-
- status = ads_find_machine_acct(ads, &res, host);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0, ("Host account for %s does not exist.\n", host));
- return status;
- }
-
- msg = ads_first_entry(ads, res);
- if (!msg) {
- return ADS_ERROR_SYSTEM(ENOENT);
- }
-
- hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg);
-
-
- rc = ldap_delete_ext_s(ads->ld, hostnameDN, pldap_control, NULL);
- if (rc) {
- DEBUG(3,("ldap_delete_ext_s failed with error code %d\n", rc));
- }else {
- DEBUG(3,("ldap_delete_ext_s succeeded with error code %d\n", rc));
- }
-
- ads_memfree(ads, hostnameDN);
- if (rc != LDAP_SUCCESS) {
- return ADS_ERROR(rc);
- }
-
- status = ads_find_machine_acct(ads, &res, host);
- if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) {
- DEBUG(0, ("Failed to remove host account.\n"));
- return status;
- }
-
- free(host);
-
- return status;
-}
-
-/**
- * add machine account to existing security descriptor
- * @param ads connection to ads server
- * @param hostname machine to add
- * @param dn DN of security descriptor
- * @return status
- **/
-ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
-{
- const char *attrs[] = {"nTSecurityDescriptor", "objectSid", 0};
- char *expr = 0;
- size_t sd_size = 0;
- struct berval bval = {0, NULL};
- prs_struct ps_wire;
- char *escaped_hostname = escape_ldap_string_alloc(hostname);
-
- LDAPMessage *res = 0;
- LDAPMessage *msg = 0;
- ADS_MODLIST mods = 0;
-
- NTSTATUS status;
- ADS_STATUS ret;
- DOM_SID sid;
- SEC_DESC *psd = NULL;
- TALLOC_CTX *ctx = NULL;
-
- /* Avoid segmentation fault in prs_mem_free if
- * we have to bail out before prs_init */
- ps_wire.is_dynamic = False;
-
- if (!ads) {
- SAFE_FREE(escaped_hostname);
- return ADS_ERROR(LDAP_SERVER_DOWN);
- }
-
- ret = ADS_ERROR(LDAP_SUCCESS);
-
- if (!escaped_hostname) {
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
- if (asprintf(&expr, "(samAccountName=%s$)", escaped_hostname) == -1) {
- DEBUG(1, ("ads_set_machine_sd: asprintf failed!\n"));
- SAFE_FREE(escaped_hostname);
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
- SAFE_FREE(escaped_hostname);
-
- 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) )) {
- ret = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
- goto ads_set_sd_error;
- }
-
- if (!ads_pull_sid(ads, msg, attrs[1], &sid)) {
- ret = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- goto ads_set_sd_error;
- }
-
- if (!(ctx = talloc_init("sec_io_desc"))) {
- ret = ADS_ERROR(LDAP_NO_MEMORY);
- goto ads_set_sd_error;
- }
-
- if (!ads_pull_sd(ads, ctx, msg, attrs[0], &psd)) {
- ret = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- goto ads_set_sd_error;
- }
-
- status = sec_desc_add_sid(ctx, &psd, &sid, SEC_RIGHTS_FULL_CTRL, &sd_size);
-
- if (!NT_STATUS_IS_OK(status)) {
- ret = ADS_ERROR_NT(status);
- goto ads_set_sd_error;
- }
-
- if (!prs_init(&ps_wire, sd_size, ctx, MARSHALL)) {
- ret = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
- if (!sec_io_desc("sd_wire", &psd, &ps_wire, 1)) {
- ret = ADS_ERROR(LDAP_NO_MEMORY);
- goto ads_set_sd_error;
- }
-
-#if 0
- file_save("/tmp/sec_desc.new", ps_wire.data_p, sd_size);
-#endif
- if (!(mods = ads_init_mods(ctx))) return ADS_ERROR(LDAP_NO_MEMORY);
-
- bval.bv_len = prs_offset(&ps_wire);
- bval.bv_val = TALLOC(ctx, bval.bv_len);
- if (!bval.bv_val) {
- ret = ADS_ERROR(LDAP_NO_MEMORY);
- goto ads_set_sd_error;
- }
-
- prs_set_offset(&ps_wire, 0);
-
- if (!prs_copy_data_out(bval.bv_val, &ps_wire, bval.bv_len)) {
- ret = ADS_ERROR(LDAP_NO_MEMORY);
- goto ads_set_sd_error;
- }
-
- ret = ads_mod_ber(ctx, &mods, attrs[0], &bval);
- if (ADS_ERR_OK(ret)) {
- ret = ads_gen_mod(ads, dn, mods);
- }
-
-ads_set_sd_error:
- ads_msgfree(ads, res);
- prs_mem_free(&ps_wire);
- talloc_destroy(ctx);
- return ret;
-}
-
-/**
* pull the first entry from a ADS result
* @param ads connection to ads server
* @param res Results of search
@@ -2461,44 +2203,6 @@ static time_t ads_parse_time(const char *str)
return timegm(&tm);
}
-
-const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char * OID)
-{
- ADS_STATUS rc;
- int count = 0;
- void *res = NULL;
- char *expr = NULL;
- const char *attrs[] = { "lDAPDisplayName", NULL };
-
- if (ads == NULL || mem_ctx == NULL || OID == NULL) {
- goto failed;
- }
-
- expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID);
- if (expr == NULL) {
- goto failed;
- }
-
- rc = ads_do_search_retry(ads, ads->config.schema_path,
- LDAP_SCOPE_SUBTREE, expr, attrs, &res);
- if (!ADS_ERR_OK(rc)) {
- goto failed;
- }
-
- count = ads_count_replies(ads, res);
- if (count == 0 || !res) {
- goto failed;
- }
-
- return ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
-
-failed:
- DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n",
- OID));
-
- return NULL;
-}
-
/**
* Find the servers name and realm - this can be done before authentication
* The ldapServiceName field on w2k looks like this:
@@ -2506,87 +2210,49 @@ failed:
* @param ads connection to ads server
* @return status of search
**/
-ADS_STATUS ads_server_info(ADS_STRUCT *ads)
+ADS_STATUS ads_current_time(ADS_STRUCT *ads)
{
- const char *attrs[] = {"ldapServiceName",
- "currentTime",
- "schemaNamingContext", NULL};
+ const char *attrs[] = {"currentTime", NULL};
ADS_STATUS status;
void *res;
- char *value;
- char *p;
char *timestr;
- char *schema_path;
TALLOC_CTX *ctx;
+ ADS_STRUCT *ads_s = ads;
if (!(ctx = talloc_init("ads_server_info"))) {
return ADS_ERROR(LDAP_NO_MEMORY);
}
- status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
- if (!ADS_ERR_OK(status)) {
- talloc_destroy(ctx);
- return status;
- }
+ /* establish a new ldap tcp session if necessary */
- value = ads_pull_string(ads, ctx, res, "ldapServiceName");
- if (!value) {
- ads_msgfree(ads, res);
- talloc_destroy(ctx);
- return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ if ( !ads->ld ) {
+ if ( (ads_s = ads_init( ads->server.realm, ads->server.workgroup,
+ ads->server.ldap_server )) == NULL )
+ {
+ goto done;
+ }
+ ads_s->auth.flags = ADS_AUTH_ANON_BIND;
+ status = ads_connect( ads_s );
+ if ( !ADS_ERR_OK(status))
+ goto done;
}
- timestr = ads_pull_string(ads, ctx, res, "currentTime");
- if (!timestr) {
- ads_msgfree(ads, res);
+ status = ads_do_search(ads_s, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ if (!ADS_ERR_OK(status)) {
talloc_destroy(ctx);
- return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ goto done;
}
- schema_path = ads_pull_string(ads, ctx, res, "schemaNamingContext");
- if (!schema_path) {
+ timestr = ads_pull_string(ads_s, ctx, res, "currentTime");
+ if (!timestr) {
ads_msgfree(ads, res);
talloc_destroy(ctx);
- return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
- }
-
- SAFE_FREE(ads->config.schema_path);
- ads->config.schema_path = SMB_STRDUP(schema_path);
-
- ads_msgfree(ads, res);
-
- p = strchr(value, ':');
- if (!p) {
- talloc_destroy(ctx);
- DEBUG(1, ("ads_server_info: returned ldap server name did not contain a ':' "
- "so was deemed invalid\n"));
- return ADS_ERROR(LDAP_DECODING_ERROR);
- }
-
- SAFE_FREE(ads->config.ldap_server_name);
-
- ads->config.ldap_server_name = SMB_STRDUP(p+1);
- p = strchr(ads->config.ldap_server_name, '$');
- if (!p || p[1] != '@') {
- talloc_destroy(ctx);
- DEBUG(1, ("ads_server_info: returned ldap server name (%s) does not contain '$@'"
- " so was deemed invalid\n", ads->config.ldap_server_name));
- SAFE_FREE(ads->config.ldap_server_name);
- return ADS_ERROR(LDAP_DECODING_ERROR);
+ status = ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ goto done;
}
- *p = 0;
-
- SAFE_FREE(ads->config.realm);
- SAFE_FREE(ads->config.bind_path);
-
- ads->config.realm = SMB_STRDUP(p+2);
- ads->config.bind_path = ads_build_dn(ads->config.realm);
-
- DEBUG(3,("got ldap server name %s@%s, using bind path: %s\n",
- ads->config.ldap_server_name, ads->config.realm,
- ads->config.bind_path));
-
+ /* but save the time and offset in the original ADS_STRUCT */
+
ads->config.current_time = ads_parse_time(timestr);
if (ads->config.current_time != 0) {
@@ -2594,58 +2260,18 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
DEBUG(4,("time offset is %d seconds\n", ads->auth.time_offset));
}
- talloc_destroy(ctx);
-
- return ADS_SUCCESS;
-}
-
-/**
- * Check for "Services for Unix"-Schema and load some attributes into the ADS_STRUCT
- * @param ads connection to ads server
- * @return BOOL status of search (False if one or more attributes couldn't be
- * found in Active Directory)
- **/
-BOOL ads_check_sfu_mapping(ADS_STRUCT *ads)
-{
- BOOL ret = False;
- TALLOC_CTX *ctx = NULL;
- const char *gidnumber, *uidnumber, *homedir, *shell, *gecos;
-
- ctx = talloc_init("ads_check_sfu_mapping");
- if (ctx == NULL)
- goto done;
-
- gidnumber = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_GIDNUMBER_OID);
- if (gidnumber == NULL)
- goto done;
- ads->schema.sfu_gidnumber_attr = SMB_STRDUP(gidnumber);
-
- uidnumber = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_UIDNUMBER_OID);
- if (uidnumber == NULL)
- goto done;
- ads->schema.sfu_uidnumber_attr = SMB_STRDUP(uidnumber);
-
- homedir = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_HOMEDIR_OID);
- if (homedir == NULL)
- goto done;
- ads->schema.sfu_homedir_attr = SMB_STRDUP(homedir);
-
- shell = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_SHELL_OID);
- if (shell == NULL)
- goto done;
- ads->schema.sfu_shell_attr = SMB_STRDUP(shell);
+ ads_msgfree(ads, res);
- gecos = ads_get_attrname_by_oid(ads, ctx, ADS_ATTR_SFU_GECOS_OID);
- if (gecos == NULL)
- goto done;
- ads->schema.sfu_gecos_attr = SMB_STRDUP(gecos);
+ status = ADS_SUCCESS;
- ret = True;
done:
- if (ctx)
- talloc_destroy(ctx);
-
- return ret;
+ /* free any temporary ads connections */
+ if ( ads_s != ads ) {
+ ads_destroy( &ads_s );
+ }
+ talloc_destroy(ctx);
+
+ return status;
}
/**
@@ -2672,81 +2298,6 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
return ADS_SUCCESS;
}
-/* this is rather complex - we need to find the allternate (netbios) name
- for the domain, but there isn't a simple query to do this. Instead
- we look for the principle names on the DCs account and find one that has
- the right form, then extract the netbios name of the domain from that
-
- NOTE! better method is this:
-
-bin/net -Uadministrator%XXXXX ads search '(&(objectclass=crossref)(dnsroot=VNET3.HOME.SAMBA.ORG))' nETBIOSName
-
-but you need to force the bind path to match the configurationNamingContext from the rootDSE
-
-*/
-ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **workgroup)
-{
- char *expr;
- ADS_STATUS rc;
- char **principles;
- char *prefix;
- int prefix_length;
- int i;
- void *res;
- const char *attrs[] = {"servicePrincipalName", NULL};
- size_t num_principals;
-
- (*workgroup) = NULL;
-
- asprintf(&expr, "(&(objectclass=computer)(dnshostname=%s.%s))",
- ads->config.ldap_server_name, ads->config.realm);
- if (expr == NULL) {
- return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
- rc = ads_search(ads, &res, expr, attrs);
- free(expr);
-
- if (!ADS_ERR_OK(rc)) {
- return rc;
- }
-
- principles = ads_pull_strings(ads, mem_ctx, res,
- "servicePrincipalName", &num_principals);
-
- ads_msgfree(ads, res);
-
- if (!principles) {
- return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
- }
-
- asprintf(&prefix, "HOST/%s.%s/",
- ads->config.ldap_server_name,
- ads->config.realm);
-
- prefix_length = strlen(prefix);
-
- for (i=0;principles[i]; i++) {
- if (strnequal(principles[i], prefix, prefix_length) &&
- !strequal(ads->config.realm, principles[i]+prefix_length) &&
- !strchr(principles[i]+prefix_length, '.')) {
- /* found an alternate (short) name for the domain. */
- DEBUG(3,("Found alternate name '%s' for realm '%s'\n",
- principles[i]+prefix_length,
- ads->config.realm));
- (*workgroup) = talloc_strdup(mem_ctx, principles[i]+prefix_length);
- break;
- }
- }
- free(prefix);
-
- if (!*workgroup) {
- return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
- }
-
- return ADS_SUCCESS;
-}
-
/**
* find our site name
* @param ads connection to ads server
@@ -2910,4 +2461,127 @@ ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixe
return status;
}
+/**
+ * pull a DOM_SID from an extended dn string
+ * @param mem_ctx TALLOC_CTX
+ * @param flags string type of extended_dn
+ * @param sid pointer to a DOM_SID
+ * @return boolean inidicating success
+ **/
+BOOL ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx,
+ const char *dn,
+ enum ads_extended_dn_flags flags,
+ DOM_SID *sid)
+{
+ char *p, *q;
+
+ if (!dn) {
+ return False;
+ }
+
+ /*
+ * ADS_EXTENDED_DN_HEX_STRING:
+ * <GUID=238e1963cb390f4bb032ba0105525a29>;<SID=010500000000000515000000bb68c8fd6b61b427572eb04556040000>;CN=gd,OU=berlin,OU=suse,DC=ber,DC=suse,DC=de
+ *
+ * ADS_EXTENDED_DN_STRING (only with w2k3):
+ <GUID=63198e23-39cb-4b0f-b032-ba0105525a29>;<SID=S-1-5-21-4257769659-666132843-1169174103-1110>;CN=gd,OU=berlin,OU=suse,DC=ber,DC=suse,DC=de
+ */
+
+ p = strchr(dn, ';');
+ if (!p) {
+ return False;
+ }
+
+ if (strncmp(p, ";<SID=", strlen(";<SID=")) != 0) {
+ return False;
+ }
+
+ p += strlen(";<SID=");
+
+ q = strchr(p, '>');
+ if (!q) {
+ return False;
+ }
+
+ *q = '\0';
+
+ DEBUG(100,("ads_get_sid_from_extended_dn: sid string is %s\n", p));
+
+ switch (flags) {
+
+ case ADS_EXTENDED_DN_STRING:
+ if (!string_to_sid(sid, p)) {
+ return False;
+ }
+ break;
+ case ADS_EXTENDED_DN_HEX_STRING: {
+ pstring buf;
+ size_t buf_len;
+
+ buf_len = strhex_to_str(buf, strlen(p), p);
+ if (buf_len == 0) {
+ return False;
+ }
+
+ if (!sid_parse(buf, buf_len, sid)) {
+ DEBUG(10,("failed to parse sid\n"));
+ return False;
+ }
+ break;
+ }
+ default:
+ DEBUG(10,("unknown extended dn format\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/**
+ * pull an array of DOM_SIDs from a ADS result
+ * @param ads connection to ads server
+ * @param mem_ctx TALLOC_CTX for allocating sid array
+ * @param msg Results of search
+ * @param field Attribute to retrieve
+ * @param flags string type of extended_dn
+ * @param sids pointer to sid array to allocate
+ * @return the count of SIDs pulled
+ **/
+int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
+ TALLOC_CTX *mem_ctx,
+ void *msg,
+ const char *field,
+ enum ads_extended_dn_flags flags,
+ DOM_SID **sids)
+{
+ int i;
+ size_t dn_count;
+ char **dn_strings;
+
+ if ((dn_strings = ads_pull_strings(ads, mem_ctx, msg, field,
+ &dn_count)) == NULL) {
+ return 0;
+ }
+
+ (*sids) = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, dn_count + 1);
+ if (!(*sids)) {
+ TALLOC_FREE(dn_strings);
+ return 0;
+ }
+
+ for (i=0; i<dn_count; i++) {
+
+ if (!ads_get_sid_from_extended_dn(mem_ctx, dn_strings[i],
+ flags, &(*sids)[i])) {
+ TALLOC_FREE(*sids);
+ TALLOC_FREE(dn_strings);
+ return 0;
+ }
+ }
+
+ TALLOC_FREE(dn_strings);
+
+ return dn_count;
+}
+
#endif
diff --git a/source/libads/ldap_schema.c b/source/libads/ldap_schema.c
new file mode 100644
index 00000000000..a0c735208fa
--- /dev/null
+++ b/source/libads/ldap_schema.c
@@ -0,0 +1,329 @@
+/*
+ Unix SMB/CIFS implementation.
+ ads (active directory) utility library
+ Copyright (C) Guenther Deschner 2005-2006
+ Copyright (C) Gerald (Jerry) Carter 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#ifdef HAVE_LDAP
+
+ADS_STATUS ads_get_attrnames_by_oids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
+ const char *schema_path,
+ const char **OIDs, size_t num_OIDs,
+ char ***OIDs_out, char ***names, size_t *count)
+{
+ ADS_STATUS status;
+ void *res = NULL;
+ LDAPMessage *msg;
+ char *expr = NULL;
+ const char *attrs[] = { "lDAPDisplayName", "attributeId", NULL };
+ int i = 0, p = 0;
+
+ if (!ads || !mem_ctx || !names || !count || !OIDs || !OIDs_out) {
+ return ADS_ERROR(LDAP_PARAM_ERROR);
+ }
+
+ if (num_OIDs == 0 || OIDs[0] == NULL) {
+ return ADS_ERROR_NT(NT_STATUS_NONE_MAPPED);
+ }
+
+ if ((expr = talloc_asprintf(mem_ctx, "(|")) == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ for (i=0; i<num_OIDs; i++) {
+
+ if ((expr = talloc_asprintf_append(expr, "(attributeId=%s)",
+ OIDs[i])) == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+ }
+
+ if ((expr = talloc_asprintf_append(expr, ")")) == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_do_search_retry(ads, schema_path,
+ LDAP_SCOPE_SUBTREE, expr, attrs, &res);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ *count = ads_count_replies(ads, res);
+ if (*count == 0 || !res) {
+ status = ADS_ERROR_NT(NT_STATUS_NONE_MAPPED);
+ goto out;
+ }
+
+ if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
+ status = ADS_ERROR(LDAP_NO_MEMORY);
+ goto out;
+ }
+ if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
+ status = ADS_ERROR(LDAP_NO_MEMORY);
+ goto out;
+ }
+
+ for (msg = ads_first_entry(ads, res); msg != NULL;
+ msg = ads_next_entry(ads, msg)) {
+
+ (*names)[p] = ads_pull_string(ads, mem_ctx, msg,
+ "lDAPDisplayName");
+ (*OIDs_out)[p] = ads_pull_string(ads, mem_ctx, msg,
+ "attributeId");
+ if (((*names)[p] == NULL) || ((*OIDs_out)[p] == NULL)) {
+ status = ADS_ERROR(LDAP_NO_MEMORY);
+ goto out;
+ }
+
+ p++;
+ }
+
+ if (*count < num_OIDs) {
+ status = ADS_ERROR_NT(STATUS_SOME_UNMAPPED);
+ goto out;
+ }
+
+ status = ADS_ERROR(LDAP_SUCCESS);
+out:
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+const char *ads_get_attrname_by_oid(ADS_STRUCT *ads, const char *schema_path, TALLOC_CTX *mem_ctx, const char * OID)
+{
+ ADS_STATUS rc;
+ int count = 0;
+ void *res = NULL;
+ char *expr = NULL;
+ const char *attrs[] = { "lDAPDisplayName", NULL };
+ char *result;
+
+ if (ads == NULL || mem_ctx == NULL || OID == NULL) {
+ goto failed;
+ }
+
+ expr = talloc_asprintf(mem_ctx, "(attributeId=%s)", OID);
+ if (expr == NULL) {
+ goto failed;
+ }
+
+ rc = ads_do_search_retry(ads, schema_path, LDAP_SCOPE_SUBTREE,
+ expr, attrs, &res);
+ if (!ADS_ERR_OK(rc)) {
+ goto failed;
+ }
+
+ count = ads_count_replies(ads, res);
+ if (count == 0 || !res) {
+ goto failed;
+ }
+
+ result = ads_pull_string(ads, mem_ctx, res, "lDAPDisplayName");
+ ads_msgfree(ads, res);
+
+ return result;
+
+failed:
+ DEBUG(0,("ads_get_attrname_by_oid: failed to retrieve name for oid: %s\n",
+ OID));
+
+ ads_msgfree(ads, res);
+ return NULL;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static ADS_STATUS ads_schema_path(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **schema_path)
+{
+ ADS_STATUS status;
+ void *res;
+ const char *schema;
+ const char *attrs[] = { "schemaNamingContext", NULL };
+
+ status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
+ if ( (schema = ads_pull_string(ads, mem_ctx, res, "schemaNamingContext")) == NULL ) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ if ( (*schema_path = talloc_strdup(mem_ctx, schema)) == NULL ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+/**
+ * Check for "Services for Unix" or rfc2307 Schema and load some attributes into the ADS_STRUCT
+ * @param ads connection to ads server
+ * @param enum mapping type
+ * @return BOOL status of search (False if one or more attributes couldn't be
+ * found in Active Directory)
+ **/
+ADS_STATUS ads_check_posix_schema_mapping(ADS_STRUCT *ads, enum wb_posix_mapping map_type)
+{
+ TALLOC_CTX *ctx = NULL;
+ ADS_STATUS status;
+ char **oids_out, **names_out;
+ size_t num_names;
+ char *schema_path = NULL;
+ ADS_STRUCT *ads_s = ads;
+ int i;
+
+ const char *oids_sfu[] = { ADS_ATTR_SFU_UIDNUMBER_OID,
+ ADS_ATTR_SFU_GIDNUMBER_OID,
+ ADS_ATTR_SFU_HOMEDIR_OID,
+ ADS_ATTR_SFU_SHELL_OID,
+ ADS_ATTR_SFU_GECOS_OID};
+
+ const char *oids_rfc2307[] = { ADS_ATTR_RFC2307_UIDNUMBER_OID,
+ ADS_ATTR_RFC2307_GIDNUMBER_OID,
+ ADS_ATTR_RFC2307_HOMEDIR_OID,
+ ADS_ATTR_RFC2307_SHELL_OID,
+ ADS_ATTR_RFC2307_GECOS_OID };
+
+ DEBUG(10,("ads_check_posix_schema_mapping\n"));
+
+ switch (map_type) {
+
+ case WB_POSIX_MAP_TEMPLATE:
+ case WB_POSIX_MAP_UNIXINFO:
+ DEBUG(10,("ads_check_posix_schema_mapping: nothing to do\n"));
+ return ADS_ERROR(LDAP_SUCCESS);
+
+ case WB_POSIX_MAP_SFU:
+ case WB_POSIX_MAP_RFC2307:
+ break;
+
+ default:
+ DEBUG(0,("ads_check_posix_schema_mapping: "
+ "unknown enum %d\n", map_type));
+ return ADS_ERROR(LDAP_PARAM_ERROR);
+ }
+
+ ads->schema.posix_uidnumber_attr = NULL;
+ ads->schema.posix_gidnumber_attr = NULL;
+ ads->schema.posix_homedir_attr = NULL;
+ ads->schema.posix_shell_attr = NULL;
+ ads->schema.posix_gecos_attr = NULL;
+
+ ctx = talloc_init("ads_check_posix_schema_mapping");
+ if (ctx == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* establish a new ldap tcp session if necessary */
+
+ if (!ads->ld) {
+ if ((ads_s = ads_init(ads->server.realm, ads->server.workgroup,
+ ads->server.ldap_server)) == NULL) {
+ status = ADS_ERROR(LDAP_SERVER_DOWN);
+ goto done;
+ }
+
+ ads_s->auth.flags = ADS_AUTH_ANON_BIND;
+ status = ads_connect(ads_s);
+ if (!ADS_ERR_OK(status)) {
+ goto done;
+ }
+ }
+
+ status = ads_schema_path(ads, ctx, &schema_path);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3,("ads_check_posix_mapping: Unable to retrieve schema DN!\n"));
+ goto done;
+ }
+
+ if (map_type == WB_POSIX_MAP_SFU) {
+ status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_sfu,
+ ARRAY_SIZE(oids_sfu),
+ &oids_out, &names_out, &num_names);
+ } else {
+ status = ads_get_attrnames_by_oids(ads, ctx, schema_path, oids_rfc2307,
+ ARRAY_SIZE(oids_rfc2307),
+ &oids_out, &names_out, &num_names);
+ }
+
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(3,("ads_check_posix_schema_mapping: failed %s\n",
+ ads_errstr(status)));
+ goto done;
+ }
+
+ DEBUG(10,("ads_check_posix_schema_mapping: query succeeded, identified: %s\n",
+ wb_posix_map_str(map_type)));
+
+ for (i=0; i<num_names; i++) {
+
+ DEBUGADD(10,("\tOID %s has name: %s\n", oids_out[i], names_out[i]));
+
+ if (strequal(ADS_ATTR_RFC2307_UIDNUMBER_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_UIDNUMBER_OID, oids_out[i])) {
+ ads->schema.posix_uidnumber_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_GIDNUMBER_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_GIDNUMBER_OID, oids_out[i])) {
+ ads->schema.posix_gidnumber_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_HOMEDIR_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_HOMEDIR_OID, oids_out[i])) {
+ ads->schema.posix_homedir_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_SHELL_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_SHELL_OID, oids_out[i])) {
+ ads->schema.posix_shell_attr = SMB_STRDUP(names_out[i]);
+ }
+ if (strequal(ADS_ATTR_RFC2307_GECOS_OID, oids_out[i]) ||
+ strequal(ADS_ATTR_SFU_GECOS_OID, oids_out[i])) {
+ ads->schema.posix_gecos_attr = SMB_STRDUP(names_out[i]);
+ }
+ }
+
+ talloc_destroy(ctx);
+
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_uidnumber_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_gidnumber_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_homedir_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_shell_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(ads->schema.posix_gecos_attr);
+
+ status = ADS_ERROR(LDAP_SUCCESS);
+
+ ads->schema.map_type = map_type;
+done:
+ /* free any temporary ads connections */
+ if (ads_s != ads) {
+ ads_destroy(&ads_s);
+ }
+ if (ctx) {
+ talloc_destroy(ctx);
+ }
+
+ return status;
+}
+
+#endif
diff --git a/source/libads/ldap_utils.c b/source/libads/ldap_utils.c
index 18caa2c63ae..c3074233e2e 100644
--- a/source/libads/ldap_utils.c
+++ b/source/libads/ldap_utils.c
@@ -27,9 +27,9 @@
a wrapper around ldap_search_s that retries depending on the error code
this is supposed to catch dropped connections and auto-reconnect
*/
-ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope,
- const char *expr,
- const char **attrs, void **res)
+static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, void *args, void **res)
{
ADS_STATUS status = ADS_SUCCESS;
int count = 3;
@@ -48,15 +48,16 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
- while (count--) {
- *res = NULL;
- status = ads_do_search_all(ads, bp, scope, expr, attrs, res);
- if (ADS_ERR_OK(status)) {
- DEBUG(5,("Search for %s gave %d replies\n",
- expr, ads_count_replies(ads, *res)));
- SAFE_FREE(bp);
- return status;
- }
+ *res = NULL;
+ status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res);
+ if (ADS_ERR_OK(status)) {
+ DEBUG(5,("Search for %s gave %d replies\n",
+ expr, ads_count_replies(ads, *res)));
+ SAFE_FREE(bp);
+ return status;
+ }
+
+ while (--count) {
if (*res)
ads_msgfree(ads, *res);
@@ -79,6 +80,15 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
SAFE_FREE(bp);
return status;
}
+
+ *res = NULL;
+ status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res);
+ if (ADS_ERR_OK(status)) {
+ DEBUG(5,("Search for %s gave %d replies\n",
+ expr, ads_count_replies(ads, *res)));
+ SAFE_FREE(bp);
+ return status;
+ }
}
SAFE_FREE(bp);
@@ -89,6 +99,20 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
return status;
}
+ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, void **res)
+{
+ return ads_do_search_retry_internal(ads, bind_path, scope, expr, attrs, NULL, res);
+}
+
+ADS_STATUS ads_do_search_retry_args(ADS_STRUCT *ads, const char *bind_path, int scope,
+ const char *expr,
+ const char **attrs, void *args, void **res)
+{
+ return ads_do_search_retry_internal(ads, bind_path, scope, expr, attrs, args, res);
+}
+
ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
const char *expr,
@@ -105,4 +129,44 @@ ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res,
return ads_do_search_retry(ads, dn, LDAP_SCOPE_BASE,
"(objectclass=*)", attrs, res);
}
+
+ADS_STATUS ads_search_retry_extended_dn(ADS_STRUCT *ads, void **res,
+ const char *dn,
+ const char **attrs,
+ enum ads_extended_dn_flags flags)
+{
+ ads_control args;
+
+ args.control = ADS_EXTENDED_DN_OID;
+ args.val = flags;
+ args.critical = True;
+
+ return ads_do_search_retry_args(ads, dn, LDAP_SCOPE_BASE,
+ "(objectclass=*)", attrs, &args, res);
+}
+
+ADS_STATUS ads_search_retry_sid(ADS_STRUCT *ads, void **res,
+ const DOM_SID *sid,
+ const char **attrs)
+{
+ char *dn, *sid_string;
+ ADS_STATUS status;
+
+ sid_string = sid_binstring_hex(sid);
+ if (sid_string == NULL) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if (!asprintf(&dn, "<SID=%s>", sid_string)) {
+ SAFE_FREE(sid_string);
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ status = ads_do_search_retry(ads, dn, LDAP_SCOPE_BASE,
+ "(objectclass=*)", attrs, res);
+ SAFE_FREE(dn);
+ SAFE_FREE(sid_string);
+ return status;
+}
+
#endif
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index d8d33a924f2..a12af43eb37 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -304,7 +304,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
if (!ADS_ERR_OK(status)) {
return status;
}
- status = ADS_ERROR_KRB5(krb5_parse_name(ctx, sname, &principal));
+ status = ADS_ERROR_KRB5(smb_krb5_parse_name(ctx, sname, &principal));
if (!ADS_ERR_OK(status)) {
return status;
}
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 6b5de6d1439..7f5b5d7fa57 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -221,6 +221,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user,
fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
+ memset(cli->outbuf, '\0', smb_size);
set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
@@ -921,6 +922,7 @@ BOOL cli_ulogoff(struct cli_state *cli)
/****************************************************************************
Send a tconX.
****************************************************************************/
+
BOOL cli_send_tconX(struct cli_state *cli,
const char *share, const char *dev, const char *pass, int passlen)
{
@@ -935,9 +937,13 @@ BOOL cli_send_tconX(struct cli_state *cli,
if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
passlen = 1;
pass = "";
+ } else if (!pass) {
+ DEBUG(1, ("Server not using user level security and no password supplied.\n"));
+ return False;
}
- if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
+ *pass && passlen != 24) {
if (!lp_client_lanman_auth()) {
DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
" is disabled\n"));
@@ -963,7 +969,9 @@ BOOL cli_send_tconX(struct cli_state *cli,
passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
} else {
- memcpy(pword, pass, passlen);
+ if (passlen) {
+ memcpy(pword, pass, passlen);
+ }
}
}
@@ -978,7 +986,9 @@ BOOL cli_send_tconX(struct cli_state *cli,
SSVAL(cli->outbuf,smb_vwv3,passlen);
p = smb_buf(cli->outbuf);
- memcpy(p,pword,passlen);
+ if (passlen) {
+ memcpy(p,pword,passlen);
+ }
p += passlen;
p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
@@ -1483,6 +1493,11 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
{
NTSTATUS nt_status;
struct cli_state *cli = NULL;
+ int pw_len = password ? strlen(password)+1 : 0;
+
+ if (password == NULL) {
+ password = "";
+ }
nt_status = cli_start_connection(&cli, my_name, dest_host,
dest_ip, port, signing_state, flags, retry);
@@ -1491,9 +1506,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
return nt_status;
}
- if (!cli_session_setup(cli, user, password, strlen(password)+1,
- password, strlen(password)+1,
- domain)) {
+ if (!cli_session_setup(cli, user, password, pw_len, password, pw_len, domain)) {
if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
&& cli_session_setup(cli, "", "", 0, "", 0, domain)) {
} else {
@@ -1507,8 +1520,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
}
if (service) {
- if (!cli_send_tconX(cli, service, service_type,
- password, strlen(password)+1)) {
+ if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
nt_status = cli_nt_error(cli);
DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
cli_shutdown(cli);
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index 4943f67b776..e0d6b09d977 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -38,6 +38,78 @@
#define KRB5_KEY_DATA(k) ((k)->contents)
#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
+/**************************************************************
+ Wrappers around kerberos string functions that convert from
+ utf8 -> unix charset and vica versa.
+**************************************************************/
+
+/**************************************************************
+ krb5_parse_name that takes a UNIX charset.
+**************************************************************/
+
+ krb5_error_code smb_krb5_parse_name(krb5_context context,
+ const char *name, /* in unix charset */
+ krb5_principal *principal)
+{
+ krb5_error_code ret;
+ char *utf8_name;
+
+ if (push_utf8_allocate(&utf8_name, name) == (size_t)-1) {
+ return ENOMEM;
+ }
+
+ ret = krb5_parse_name(context, utf8_name, principal);
+ SAFE_FREE(utf8_name);
+ return ret;
+}
+
+#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
+/**************************************************************
+ krb5_parse_name_norealm that takes a UNIX charset.
+**************************************************************/
+
+static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
+ const char *name, /* in unix charset */
+ krb5_principal *principal)
+{
+ krb5_error_code ret;
+ char *utf8_name;
+
+ if (push_utf8_allocate(&utf8_name, name) == (size_t)-1) {
+ return ENOMEM;
+ }
+
+ ret = krb5_parse_name_norealm(context, utf8_name, principal);
+ SAFE_FREE(utf8_name);
+ return ret;
+}
+#endif
+
+/**************************************************************
+ krb5_parse_name that returns a UNIX charset name. Must
+ be freed with normal free() call.
+**************************************************************/
+
+ krb5_error_code smb_krb5_unparse_name(krb5_context context,
+ krb5_const_principal principal,
+ char **unix_name)
+{
+ krb5_error_code ret;
+ char *utf8_name;
+
+ ret = krb5_unparse_name(context, principal, &utf8_name);
+ if (ret) {
+ return ret;
+ }
+
+ if (pull_utf8_allocate(unix_name, utf8_name)==-1) {
+ krb5_free_unparsed_name(context, utf8_name);
+ return ENOMEM;
+ }
+ krb5_free_unparsed_name(context, utf8_name);
+ return 0;
+}
+
#ifndef HAVE_KRB5_SET_REAL_TIME
/*
* This function is not in the Heimdal mainline.
@@ -459,7 +531,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
BOOL creds_ready = False;
int i = 0, maxtries = 3;
- retval = krb5_parse_name(context, principal, &server);
+ retval = smb_krb5_parse_name(context, principal, &server);
if (retval) {
DEBUG(1,("ads_krb5_mk_req: Failed to parse principal %s\n", principal));
return retval;
@@ -795,10 +867,11 @@ get_key_from_keytab(krb5_context context,
}
if ( DEBUGLEVEL >= 10 ) {
- krb5_unparse_name(context, server, &name);
- DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n",
- kvno, enctype, name));
- krb5_free_unparsed_name(context, name);
+ if (smb_krb5_unparse_name(context, server, &name) == 0) {
+ DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n",
+ kvno, enctype, name));
+ SAFE_FREE(name);
+ }
}
ret = krb5_kt_get_entry(context,
@@ -943,7 +1016,7 @@ out:
krb5_principal *principal)
{
#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
- return krb5_parse_name_norealm(context, name, principal);
+ return smb_krb5_parse_name_norealm_conv(context, name, principal);
#endif
/* we are cheating here because parse_name will in fact set the realm.
@@ -951,7 +1024,7 @@ out:
* ignores the realm anyway when calling
* smb_krb5_principal_compare_any_realm later - Guenther */
- return krb5_parse_name(context, name, principal);
+ return smb_krb5_parse_name(context, name, principal);
}
BOOL smb_krb5_principal_compare_any_realm(krb5_context context,
@@ -1022,7 +1095,7 @@ out:
krb5_creds creds;
if (client_string) {
- ret = krb5_parse_name(context, client_string, &client);
+ ret = smb_krb5_parse_name(context, client_string, &client);
if (ret) {
goto done;
}
@@ -1063,7 +1136,7 @@ out:
memset(&creds_in, 0, sizeof(creds_in));
if (client_string) {
- ret = krb5_parse_name(context, client_string, &creds_in.client);
+ ret = smb_krb5_parse_name(context, client_string, &creds_in.client);
if (ret) {
goto done;
}
@@ -1075,7 +1148,7 @@ out:
}
if (service_string) {
- ret = krb5_parse_name(context, service_string, &creds_in.server);
+ ret = smb_krb5_parse_name(context, service_string, &creds_in.server);
if (ret) {
goto done;
}
@@ -1132,6 +1205,113 @@ done:
}
+ krb5_error_code smb_krb5_free_addresses(krb5_context context, smb_krb5_addresses *addr)
+{
+ krb5_error_code ret = 0;
+ if (addr == NULL) {
+ return ret;
+ }
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ krb5_free_addresses(context, addr->addrs);
+#elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */
+ ret = krb5_free_addresses(context, addr->addrs);
+ SAFE_FREE(addr->addrs);
+#endif
+ SAFE_FREE(addr);
+ addr = NULL;
+ return ret;
+}
+
+ krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr)
+{
+ krb5_error_code ret = 0;
+ nstring buf;
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ krb5_address **addrs = NULL;
+#elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */
+ krb5_addresses *addrs = NULL;
+#endif
+
+ *kerb_addr = (smb_krb5_addresses *)SMB_MALLOC(sizeof(smb_krb5_addresses));
+ if (*kerb_addr == NULL) {
+ return ENOMEM;
+ }
+
+ put_name(buf, global_myname(), ' ', 0x20);
+
+#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */
+ {
+ int num_addr = 2;
+
+ addrs = (krb5_address **)SMB_MALLOC(sizeof(krb5_address *) * num_addr);
+ if (addrs == NULL) {
+ SAFE_FREE(kerb_addr);
+ return ENOMEM;
+ }
+
+ memset(addrs, 0, sizeof(krb5_address *) * num_addr);
+
+ addrs[0] = (krb5_address *)SMB_MALLOC(sizeof(krb5_address));
+ if (addrs[0] == NULL) {
+ SAFE_FREE(addrs);
+ SAFE_FREE(kerb_addr);
+ return ENOMEM;
+ }
+
+ addrs[0]->magic = KV5M_ADDRESS;
+ addrs[0]->addrtype = KRB5_ADDR_NETBIOS;
+ addrs[0]->length = MAX_NETBIOSNAME_LEN;
+ addrs[0]->contents = (unsigned char *)SMB_MALLOC(addrs[0]->length);
+ if (addrs[0]->contents == NULL) {
+ SAFE_FREE(addrs[0]);
+ SAFE_FREE(addrs);
+ SAFE_FREE(kerb_addr);
+ return ENOMEM;
+ }
+
+ memcpy(addrs[0]->contents, buf, addrs[0]->length);
+
+ addrs[1] = NULL;
+ }
+#elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */
+ {
+ addrs = (krb5_addresses *)SMB_MALLOC(sizeof(krb5_addresses));
+ if (addrs == NULL) {
+ SAFE_FREE(kerb_addr);
+ return ENOMEM;
+ }
+
+ memset(addrs, 0, sizeof(krb5_addresses));
+
+ addrs->len = 1;
+ addrs->val = (krb5_address *)SMB_MALLOC(sizeof(krb5_address));
+ if (addrs->val == NULL) {
+ SAFE_FREE(addrs);
+ SAFE_FREE(kerb_addr);
+ return ENOMEM;
+ }
+
+ addrs->val[0].addr_type = KRB5_ADDR_NETBIOS;
+ addrs->val[0].address.length = MAX_NETBIOSNAME_LEN;
+ addrs->val[0].address.data = (unsigned char *)SMB_MALLOC(addrs->val[0].address.length);
+ if (addrs->val[0].address.data == NULL) {
+ SAFE_FREE(addrs->val);
+ SAFE_FREE(addrs);
+ SAFE_FREE(kerb_addr);
+ return ENOMEM;
+ }
+
+ memcpy(addrs->val[0].address.data, buf, addrs->val[0].address.length);
+ }
+#else
+#error UNKNOWN_KRB5_ADDRESS_FORMAT
+#endif
+ (*kerb_addr)->addrs = addrs;
+
+ return ret;
+}
+
+
#else /* HAVE_KRB5 */
/* this saves a few linking headaches */
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 1d40837f2bd..0172ab9514e 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -1024,63 +1024,62 @@ static BOOL resolve_hosts(const char *name, int name_type,
static BOOL resolve_ads(const char *name, int name_type,
struct ip_service **return_iplist, int *return_count)
{
-
-#ifdef HAVE_ADS
- if ( name_type == 0x1c ) {
- int count, i = 0;
- char *list = NULL;
- const char *ptr;
- pstring tok;
+ int i = 0;
+ NTSTATUS status;
+ TALLOC_CTX *ctx;
+ struct dns_rr_srv *dcs = NULL;
+ int numdcs = 0;
+
+ if ( name_type != 0x1c )
+ return False;
- /* try to lookup the _ldap._tcp.<domain> if we are using ADS */
- if ( lp_security() != SEC_ADS )
- return False;
+ DEBUG(5,("resolve_hosts: Attempting to resolve DC's for %s using DNS\n",
+ name));
- DEBUG(5,("resolve_hosts: Attempting to resolve DC's for %s using DNS\n",
- name));
-
- if (ldap_domain2hostlist(name, &list) != LDAP_SUCCESS)
- return False;
-
- count = count_chars(list, ' ') + 1;
- if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
- DEBUG(0,("resolve_hosts: malloc failed for %d entries\n", count ));
- return False;
- }
+ if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
+ DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
+ return False;
+ }
+
+ status = ads_dns_query_dcs( ctx, name, &dcs, &numdcs );
+ if ( !NT_STATUS_IS_OK( status ) ) {
+ return False;
+ }
+
+ if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numdcs)) == NULL ) {
+ DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numdcs ));
+ return False;
+ }
- ptr = list;
- while (next_token(&ptr, tok, " ", sizeof(tok))) {
- unsigned port = LDAP_PORT;
- char *p = strchr(tok, ':');
- if (p) {
- *p = 0;
- port = atoi(p+1);
- }
- (*return_iplist)[i].ip = *interpret_addr2(tok);
- (*return_iplist)[i].port = port;
+ i = 0;
+ while ( i < numdcs ) {
+
+ /* use the IP address from the SRV structure if we have one */
+ if ( is_zero_ip( dcs[i].ip ) )
+ (*return_iplist)[i].ip = *interpret_addr2(dcs[i].hostname);
+ else
+ (*return_iplist)[i].ip = dcs[i].ip;
+
+ (*return_iplist)[i].port = dcs[i].port;
- /* make sure it is a valid IP. I considered checking the negative
- connection cache, but this is the wrong place for it. Maybe only
- as a hac. After think about it, if all of the IP addresses retuend
- from DNS are dead, what hope does a netbios name lookup have?
- The standard reason for falling back to netbios lookups is that
- our DNS server doesn't know anything about the DC's -- jerry */
+ /* make sure it is a valid IP. I considered checking the negative
+ connection cache, but this is the wrong place for it. Maybe only
+ as a hac. After think about it, if all of the IP addresses retuend
+ from DNS are dead, what hope does a netbios name lookup have?
+ The standard reason for falling back to netbios lookups is that
+ our DNS server doesn't know anything about the DC's -- jerry */
- if ( is_zero_ip((*return_iplist)[i].ip) )
- continue;
+ if ( is_zero_ip((*return_iplist)[i].ip) )
+ continue;
+
+ i++;
+ }
- i++;
- }
- SAFE_FREE(list);
+ TALLOC_FREE( dcs );
- *return_count = i;
+ *return_count = i;
- return True;
- } else
-#endif /* HAVE_ADS */
- {
- return False;
- }
+ return True;
}
/*******************************************************************
@@ -1171,8 +1170,7 @@ BOOL internal_resolve_name(const char *name, int name_type,
}
} else if(strequal( tok, "ads")) {
/* deal with 0x1c names here. This will result in a
- SRV record lookup for _ldap._tcp.<domain> if we
- are using 'security = ads' */
+ SRV record lookup */
if (resolve_ads(name, name_type, return_iplist, return_count)) {
result = True;
goto done;
diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c
index 4d84d7bc499..5280dfdbffa 100644
--- a/source/libsmb/nmblib.c
+++ b/source/libsmb/nmblib.c
@@ -265,7 +265,7 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
[15 bytes name + padding][1 byte name type].
****************************************************************************/
-static void put_name(char *dest, const char *name, int pad, unsigned int name_type)
+void put_name(char *dest, const char *name, int pad, unsigned int name_type)
{
size_t len = strlen(name);
diff --git a/source/libsmb/samlogon_cache.c b/source/libsmb/samlogon_cache.c
index cc1c6bd6b24..7a6d9a96ad0 100644
--- a/source/libsmb/samlogon_cache.c
+++ b/source/libsmb/samlogon_cache.c
@@ -151,10 +151,9 @@ BOOL netsamlogon_cache_store( const char *username, NET_USER_INFO_3 *user )
prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
{
- uint32 ts;
+ uint32 ts = (uint32)t;
if ( !prs_uint32( "timestamp", &ps, 0, &ts ) )
return False;
- t = (time_t)ts;
}
if ( net_io_user_info3("", user, &ps, 0, 3, 0) )
diff --git a/source/locking/brlock.c b/source/locking/brlock.c
index e6f0dd1c729..574552e9e21 100644
--- a/source/locking/brlock.c
+++ b/source/locking/brlock.c
@@ -563,6 +563,8 @@ OR
smb_panic("brlock_posix_split_merge\n");
/* Notreached. */
abort();
+ /* Keep some compilers happy. */
+ return 0;
}
/****************************************************************************
@@ -905,7 +907,7 @@ static BOOL brl_unlock_posix(struct byte_range_lock *br_lck, const struct lock_s
/* 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);
+ SMB_ASSERT(tmp_lock[2].lock_type == locks[i].lock_type);
memcpy(&tp[count], &tmp_lock[0], sizeof(struct lock_struct));
count++;
@@ -1259,6 +1261,58 @@ void brl_close_fnum(struct byte_range_lock *br_lck, struct process_id pid)
}
/****************************************************************************
+ Ensure this set of lock entries is valid.
+****************************************************************************/
+
+static BOOL validate_lock_entries(unsigned int *pnum_entries, struct lock_struct **pplocks)
+{
+ unsigned int i;
+ unsigned int num_valid_entries = 0;
+ struct lock_struct *locks = *pplocks;
+
+ for (i = 0; i < *pnum_entries; i++) {
+ struct lock_struct *lock_data = &locks[i];
+ if (!process_exists(lock_data->context.pid)) {
+ /* This process no longer exists - mark this
+ entry as invalid by zeroing it. */
+ ZERO_STRUCTP(lock_data);
+ } else {
+ num_valid_entries++;
+ }
+ }
+
+ if (num_valid_entries != *pnum_entries) {
+ struct lock_struct *new_lock_data = NULL;
+
+ if (num_valid_entries) {
+ new_lock_data = SMB_MALLOC_ARRAY(struct lock_struct, num_valid_entries);
+ if (!new_lock_data) {
+ DEBUG(3, ("malloc fail\n"));
+ return False;
+ }
+
+ num_valid_entries = 0;
+ for (i = 0; i < *pnum_entries; i++) {
+ struct lock_struct *lock_data = &locks[i];
+ if (lock_data->context.smbpid &&
+ lock_data->context.tid) {
+ /* Valid (nonzero) entry - copy it. */
+ memcpy(&new_lock_data[num_valid_entries],
+ lock_data, sizeof(struct lock_struct));
+ num_valid_entries++;
+ }
+ }
+ }
+
+ SAFE_FREE(*pplocks);
+ *pplocks = new_lock_data;
+ *pnum_entries = num_valid_entries;
+ }
+
+ return True;
+}
+
+/****************************************************************************
Traverse the whole database with this function, calling traverse_callback
on each lock.
****************************************************************************/
@@ -1267,14 +1321,42 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
{
struct lock_struct *locks;
struct lock_key *key;
- int i;
+ unsigned int i;
+ unsigned int num_locks = 0;
+ unsigned int orig_num_locks = 0;
BRLOCK_FN(traverse_callback) = (BRLOCK_FN_CAST())state;
- locks = (struct lock_struct *)dbuf.dptr;
+ /* In a traverse function we must make a copy of
+ dbuf before modifying it. */
+
+ locks = (struct lock_struct *)memdup(dbuf.dptr, dbuf.dsize);
+ if (!locks) {
+ return -1; /* Terminate traversal. */
+ }
+
key = (struct lock_key *)kbuf.dptr;
+ orig_num_locks = num_locks = dbuf.dsize/sizeof(*locks);
- for (i=0;i<dbuf.dsize/sizeof(*locks);i++) {
+ /* Ensure the lock db is clean of entries from invalid processes. */
+
+ if (!validate_lock_entries(&num_locks, &locks)) {
+ SAFE_FREE(locks);
+ return -1; /* Terminate traversal */
+ }
+
+ if (orig_num_locks != num_locks) {
+ dbuf.dptr = (void *)locks;
+ dbuf.dsize = num_locks * sizeof(*locks);
+
+ if (dbuf.dsize) {
+ tdb_store(ttdb, kbuf, dbuf, TDB_REPLACE);
+ } else {
+ tdb_delete(ttdb, kbuf);
+ }
+ }
+
+ for ( i=0; i<num_locks; i++) {
traverse_callback(key->device,
key->inode,
locks[i].context.pid,
@@ -1283,6 +1365,8 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
locks[i].start,
locks[i].size);
}
+
+ SAFE_FREE(locks);
return 0;
}
@@ -1373,6 +1457,23 @@ struct byte_range_lock *brl_get_locks(files_struct *fsp)
br_lck->lock_data = (void *)data.dptr;
br_lck->num_locks = data.dsize / sizeof(struct lock_struct);
+ if (!fsp->lockdb_clean) {
+
+ /* This is the first time we've accessed this. */
+ /* Go through and ensure all entries exist - remove any that don't. */
+ /* Makes the lockdb self cleaning at low cost. */
+
+ if (!validate_lock_entries(&br_lck->num_locks, (struct lock_struct **)&br_lck->lock_data)) {
+ tdb_chainunlock(tdb, key);
+ SAFE_FREE(br_lck->lock_data);
+ SAFE_FREE(br_lck);
+ return NULL;
+ }
+
+ /* Mark the lockdb as "clean" as seen from this open file. */
+ fsp->lockdb_clean = True;
+ }
+
if (DEBUGLEVEL >= 10) {
unsigned int i;
struct lock_struct *locks = (struct lock_struct *)br_lck->lock_data;
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 2b6023c0c41..a532a90d0d4 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -665,6 +665,7 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
p += sizeof(uid_t);
memcpy(p, &lck->delete_token->gid, sizeof(gid_t));
+ p += sizeof(gid_t);
for (i = 0; i < lck->delete_token->ngroups; i++) {
memcpy(p, &lck->delete_token->groups[i], sizeof(gid_t));
@@ -927,7 +928,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e,
e->op_type = op_type;
e->time.tv_sec = fsp->open_time.tv_sec;
e->time.tv_usec = fsp->open_time.tv_usec;
- e->share_file_id = fsp->file_id;
+ e->share_file_id = fsp->fh->file_id;
e->dev = fsp->dev;
e->inode = fsp->inode;
}
@@ -986,28 +987,19 @@ void add_deferred_open(struct share_mode_lock *lck, uint16 mid,
/*******************************************************************
Check if two share mode entries are identical, ignoring oplock
- and mid info and desired_access.
+ and mid info and desired_access. (Removed paranoia test - it's
+ not automatically a logic error if they are identical. JRA.)
********************************************************************/
static BOOL share_modes_identical(struct share_mode_entry *e1,
struct share_mode_entry *e2)
{
-#if 1 /* JRA PARANOIA TEST - REMOVE LATER */
- if (procid_equal(&e1->pid, &e2->pid) &&
- e1->share_file_id == e2->share_file_id &&
- e1->dev == e2->dev &&
- e1->inode == e2->inode &&
- (e1->share_access) != (e2->share_access)) {
- DEBUG(0,("PANIC: share_modes_identical: share_mode "
- "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n",
- (unsigned int)e1->share_access,
- (unsigned int)e2->share_access ));
- smb_panic("PANIC: share_modes_identical logic error.\n");
- }
-#endif
+ /* We used to check for e1->share_access == e2->share_access here
+ as well as the other fields but 2 different DOS or FCB opens
+ sharing the same share mode entry may validly differ in
+ fsp->share_access field. */
return (procid_equal(&e1->pid, &e2->pid) &&
- (e1->share_access) == (e2->share_access) &&
e1->dev == e2->dev &&
e1->inode == e2->inode &&
e1->share_file_id == e2->share_file_id );
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index fca17d1ff7b..9c8f99df252 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -605,6 +605,10 @@ static BOOL open_sockets(BOOL isdaemon, int port)
set_socket_options( ClientNMB, "SO_BROADCAST" );
set_socket_options( ClientDGRAM, "SO_BROADCAST" );
+ /* Ensure we're non-blocking. */
+ set_blocking( ClientNMB, False);
+ set_blocking( ClientDGRAM, False);
+
DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
return( True );
}
diff --git a/source/nmbd/nmbd_elections.c b/source/nmbd/nmbd_elections.c
index 6e8e8429bec..50e13729361 100644
--- a/source/nmbd/nmbd_elections.c
+++ b/source/nmbd/nmbd_elections.c
@@ -166,13 +166,16 @@ void run_elections(time_t t)
struct subnet_record *subrec;
+ START_PROFILE(run_elections);
+
/* Send election packets once every 2 seconds - note */
- if (lastime && (t - lastime < 2))
+ if (lastime && (t - lastime < 2)) {
+ END_PROFILE(run_elections);
return;
+ }
lastime = t;
- START_PROFILE(run_elections);
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
struct work_record *work;
@@ -267,10 +270,11 @@ void process_election(struct subnet_record *subrec, struct packet_struct *p, cha
struct work_record *work;
unstring workgroup_name;
+ START_PROFILE(election);
+
pull_ascii_nstring(server_name, sizeof(server_name), buf+13);
pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name);
- START_PROFILE(election);
server_name[15] = 0;
DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
diff --git a/source/nmbd/nmbd_incomingdgrams.c b/source/nmbd/nmbd_incomingdgrams.c
index 09eb7bfa86b..880700c72cb 100644
--- a/source/nmbd/nmbd_incomingdgrams.c
+++ b/source/nmbd/nmbd_incomingdgrams.c
@@ -797,7 +797,7 @@ void process_announce_request(struct subnet_record *subrec, struct packet_struct
work->needannounce = True;
done:
- END_PROFILE(lm_host_announce);
+ END_PROFILE(announce_request);
}
/*******************************************************************
@@ -838,5 +838,5 @@ void process_lm_announce_request(struct subnet_record *subrec, struct packet_str
done:
- END_PROFILE(lm_host_announce);
+ END_PROFILE(lm_announce_request);
}
diff --git a/source/nmbd/nmbd_responserecordsdb.c b/source/nmbd/nmbd_responserecordsdb.c
index a5903ef462e..6f22fd906de 100644
--- a/source/nmbd/nmbd_responserecordsdb.c
+++ b/source/nmbd/nmbd_responserecordsdb.c
@@ -23,8 +23,6 @@
#include "includes.h"
-extern int ClientNMB;
-
int num_response_packets = 0;
/***************************************************************************
diff --git a/source/nmbd/nmbd_serverlistdb.c b/source/nmbd/nmbd_serverlistdb.c
index 52d00e15854..cc762ae8d23 100644
--- a/source/nmbd/nmbd_serverlistdb.c
+++ b/source/nmbd/nmbd_serverlistdb.c
@@ -23,8 +23,6 @@
#include "includes.h"
-extern int ClientNMB;
-
int updatecount = 0;
/*******************************************************************
diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c
index b2e1178bebc..c3640028d27 100644
--- a/source/nmbd/nmbd_subnetdb.c
+++ b/source/nmbd/nmbd_subnetdb.c
@@ -26,8 +26,6 @@
#include "includes.h"
extern struct in_addr loopback_ip;
-extern int ClientNMB;
-extern int ClientDGRAM;
extern int global_nmb_port;
/* This is the broadcast subnets database. */
@@ -118,6 +116,10 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type
/* Make sure we can broadcast from these sockets. */
set_socket_options(nmb_sock,"SO_BROADCAST");
set_socket_options(dgram_sock,"SO_BROADCAST");
+
+ /* Set them non-blocking. */
+ set_blocking(nmb_sock, False);
+ set_blocking(dgram_sock, False);
}
subrec = SMB_MALLOC_P(struct subnet_record);
diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c
index 335d5220310..ca665bdf4f5 100644
--- a/source/nmbd/nmbd_workgroupdb.c
+++ b/source/nmbd/nmbd_workgroupdb.c
@@ -23,8 +23,6 @@
#include "includes.h"
-extern int ClientNMB;
-
extern uint16 samba_nb_type;
int workgroup_count = 0; /* unique index key: one for each workgroup */
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index b2c3a011643..43ac83a99a8 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -66,7 +66,7 @@ static int _pam_parse(int argc, const char **argv, dictionary **d)
*d = iniparser_load(CONST_DISCARD(char *, config_file));
if (*d == NULL) {
- return -1;
+ goto config_from_pam;
}
if (iniparser_getboolean(*d, CONST_DISCARD(char *, "global:debug"), False)) {
@@ -191,7 +191,7 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
struct pam_response *resp;
pmsg[0] = &msg[0];
- msg[0].msg = text;
+ msg[0].msg = CONST_DISCARD(char *, text);
msg[0].msg_style = type;
resp = NULL;
@@ -242,8 +242,9 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
/* Copy reply data from socket */
if (response->result != WINBINDD_OK) {
if (response->data.auth.pam_error != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "request failed: %s, PAM error was %d, NT error was %s",
+ _pam_log(LOG_ERR, "request failed: %s, PAM error was %s (%d), NT error was %s",
response->data.auth.error_string,
+ pam_strerror(pamh, response->data.auth.pam_error),
response->data.auth.pam_error,
response->data.auth.nt_status_string);
return response->data.auth.pam_error;
@@ -286,8 +287,7 @@ static int pam_winbind_request_log(pam_handle_t * pamh,
return retval;
case PAM_USER_UNKNOWN:
/* the user does not exist */
- _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found",
- user);
+ _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", user);
if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
return PAM_IGNORE;
}
@@ -320,7 +320,8 @@ static int winbind_auth_request(pam_handle_t * pamh,
const char *pass,
const char *member,
const char *cctype,
- int process_result)
+ int process_result,
+ time_t *pwd_last_set)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -329,6 +330,10 @@ static int winbind_auth_request(pam_handle_t * pamh,
ZERO_STRUCT(request);
ZERO_STRUCT(response);
+ if (pwd_last_set) {
+ *pwd_last_set = 0;
+ }
+
strncpy(request.data.auth.user, user,
sizeof(request.data.auth.user)-1);
@@ -401,6 +406,10 @@ static int winbind_auth_request(pam_handle_t * pamh,
ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user);
+ if (pwd_last_set) {
+ *pwd_last_set = response.data.auth.info3.pass_last_set_time;
+ }
+
if ((ctrl & WINBIND_KRB5_AUTH) &&
response.data.auth.krb5ccname[0] != '\0') {
@@ -466,6 +475,7 @@ static int winbind_auth_request(pam_handle_t * pamh,
if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
_make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable");
+ _pam_log_debug(ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user);
}
/* save the CIFS homedir for pam_cifs / pam_mount */
@@ -487,7 +497,8 @@ static int winbind_chauthtok_request(pam_handle_t * pamh,
int ctrl,
const char *user,
const char *oldpass,
- const char *newpass)
+ const char *newpass,
+ time_t pwd_last_set)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -541,7 +552,13 @@ static int winbind_chauthtok_request(pam_handle_t * pamh,
/* FIXME: avoid to send multiple PAM messages after another */
switch (response.data.auth.reject_reason) {
- case 0:
+ case -1:
+ break;
+ case REJECT_REASON_OTHER:
+ if ((response.data.auth.policy.min_passwordage > 0) &&
+ (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL))) {
+ PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_RECENT");
+ }
break;
case REJECT_REASON_TOO_SHORT:
PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT");
@@ -692,7 +709,7 @@ static int _winbind_read_password(pam_handle_t * pamh,
if (comment != NULL) {
pmsg[0] = &msg[0];
msg[0].msg_style = PAM_TEXT_INFO;
- msg[0].msg = comment;
+ msg[0].msg = CONST_DISCARD(char *, comment);
i = 1;
} else {
i = 0;
@@ -700,13 +717,13 @@ static int _winbind_read_password(pam_handle_t * pamh,
pmsg[i] = &msg[i];
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
- msg[i++].msg = prompt1;
+ msg[i++].msg = CONST_DISCARD(char *, prompt1);
replies = 1;
if (prompt2 != NULL) {
pmsg[i] = &msg[i];
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
- msg[i++].msg = prompt2;
+ msg[i++].msg = CONST_DISCARD(char *, prompt2);
++replies;
}
/* so call the conversation expecting i responses */
@@ -790,7 +807,7 @@ const char *get_conf_item_string(int argc,
goto out;
}
- /* let the pam opt take precedence over the smb.conf option */
+ /* let the pam opt take precedence over the pam_winbind.conf option */
if (d != NULL) {
@@ -819,7 +836,9 @@ const char *get_conf_item_string(int argc,
}
}
- _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt);
+ if (d != NULL) {
+ _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt);
+ }
out:
SAFE_FREE(parm);
return parm_opt;
@@ -858,7 +877,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate");
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate (flags: 0x%04x)", flags);
/* Get the username */
retval = pam_get_user(pamh, &username, NULL);
@@ -892,7 +911,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d);
/* Now use the username to look up password */
- retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True);
+ retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True, NULL);
if (retval == PAM_NEW_AUTHTOK_REQD ||
retval == PAM_AUTHTOK_EXPIRED) {
@@ -927,7 +946,7 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags,
return PAM_SYSTEM_ERR;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred");
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred (flags: 0x%04x)", flags);
if (flags & PAM_DELETE_CRED) {
return pam_sm_close_session(pamh, flags, argc, argv);
@@ -954,7 +973,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
return PAM_SYSTEM_ERR;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt");
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt (flags: 0x%04x)", flags);
/* Get the username */
@@ -1021,7 +1040,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
return PAM_SYSTEM_ERR;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler");
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler (flags: 0x%04x)", flags);
return PAM_SUCCESS;
}
@@ -1040,7 +1059,7 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags,
goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler");
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler (flags: 0x%04x)", flags);
if (!(flags & PAM_DELETE_CRED)) {
retval = PAM_SUCCESS;
@@ -1132,7 +1151,10 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
goto out;
}
- _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok");
+ _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok (flags: 0x%04x)", flags);
+
+ /* clearing offline bit for the auth in the password change */
+ ctrl &= ~WINBIND_CACHED_LOGIN;
/*
* First get the name of a user
@@ -1174,6 +1196,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (flags & PAM_PRELIM_CHECK) {
+ time_t pwdlastset_prelim = 0;
+
/* instruct user what is happening */
#define greeting "Changing password for "
Announce = (char *) malloc(sizeof(greeting) + strlen(user));
@@ -1198,16 +1222,18 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
}
/* verify that this is the password for this user */
- retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False);
+ retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False, &pwdlastset_prelim);
- if (retval != PAM_ACCT_EXPIRED
- && retval != PAM_AUTHTOK_EXPIRED
- && retval != PAM_NEW_AUTHTOK_REQD
- && retval != PAM_SUCCESS) {
+ if (retval != PAM_ACCT_EXPIRED &&
+ retval != PAM_AUTHTOK_EXPIRED &&
+ retval != PAM_NEW_AUTHTOK_REQD &&
+ retval != PAM_SUCCESS) {
pass_old = NULL;
goto out;
}
+ pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, _pam_winbind_cleanup_func);
+
retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
pass_old = NULL;
if (retval != PAM_SUCCESS) {
@@ -1215,6 +1241,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
}
} else if (flags & PAM_UPDATE_AUTHTOK) {
+ time_t pwdlastset_update = 0;
+
/*
* obtain the proposed password
*/
@@ -1272,8 +1300,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* By reaching here we have approved the passwords and must now
* rebuild the password database file.
*/
+ pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update);
- retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new);
+ retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update);
if (retval) {
_pam_overwrite(pass_new);
_pam_overwrite(pass_old);
@@ -1288,7 +1317,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
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);
+ retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False, NULL);
_pam_overwrite(pass_new);
_pam_overwrite(pass_old);
pass_old = pass_new = NULL;
diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
index 89553ebfc38..fb2769d1c1a 100644
--- a/source/nsswitch/pam_winbind.h
+++ b/source/nsswitch/pam_winbind.h
@@ -10,6 +10,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
#include <string.h>
#include <syslog.h>
#include <stdarg.h>
@@ -107,6 +108,7 @@ do { \
#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR"
+#define PAM_WINBIND_PWD_LAST_SET "PAM_WINBIND_PWD_LAST_SET"
#define SECONDS_PER_DAY 86400
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index ad5ef715230..c004b842f4f 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -119,6 +119,38 @@ static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain,
return True;
}
+/* pull pwent info for a given user */
+
+static BOOL wbinfo_get_userinfo(char *user)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ /* Send request */
+
+ fstrcpy(request.data.username, user);
+
+ result = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
+
+ if (result != NSS_STATUS_SUCCESS)
+ return False;
+
+ d_printf( "%s:%s:%d:%d:%s:%s:%s\n",
+ response.data.pw.pw_name,
+ response.data.pw.pw_passwd,
+ response.data.pw.pw_uid,
+ response.data.pw.pw_gid,
+ response.data.pw.pw_gecos,
+ response.data.pw.pw_dir,
+ response.data.pw.pw_shell );
+
+ return True;
+}
+
/* List groups a user is a member of */
static BOOL wbinfo_get_usergroups(char *user)
@@ -1086,6 +1118,7 @@ int main(int argc, char **argv)
{ "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-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
{ "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
{ "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
@@ -1245,6 +1278,13 @@ int main(int argc, char **argv)
goto done;
}
break;
+ case 'i':
+ if (!wbinfo_get_userinfo(string_arg)) {
+ d_fprintf(stderr, "Could not get info for user %s\n",
+ string_arg);
+ goto done;
+ }
+ break;
case 'r':
if (!wbinfo_get_usergroups(string_arg)) {
d_fprintf(stderr, "Could not get groups for user %s\n",
diff --git a/source/nsswitch/winbind_nss_aix.c b/source/nsswitch/winbind_nss_aix.c
index c5d98dad067..5b3aaeb8d77 100644
--- a/source/nsswitch/winbind_nss_aix.c
+++ b/source/nsswitch/winbind_nss_aix.c
@@ -360,6 +360,9 @@ static char *wb_aix_getgrset(char *user)
logit("getgrset '%s'\n", r_user);
+ ZERO_STRUCT(response);
+ ZERO_STRUCT(request);
+
STRCPY_RETNULL(request.data.username, r_user);
if (*user == WB_AIX_ENCODED) {
diff --git a/source/nsswitch/winbind_nss_config.h b/source/nsswitch/winbind_nss_config.h
index 0400b2fb36d..66e38513fd2 100644
--- a/source/nsswitch/winbind_nss_config.h
+++ b/source/nsswitch/winbind_nss_config.h
@@ -159,6 +159,7 @@ typedef int BOOL;
#endif
#ifndef HAVE_SOCKLEN_T_TYPE
+#define HAVE_SOCKLEN_T_TYPE
typedef int socklen_t;
#endif
diff --git a/source/nsswitch/winbind_nss_irix.c b/source/nsswitch/winbind_nss_irix.c
index 05085ba1f39..2fbf3e0df82 100644
--- a/source/nsswitch/winbind_nss_irix.c
+++ b/source/nsswitch/winbind_nss_irix.c
@@ -4,6 +4,7 @@
Windows NT Domain nsswitch module
Copyright (C) Tim Potter 2000
+ Copyright (C) James Peach 2006
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -23,8 +24,19 @@
#include "winbind_client.h"
+#ifndef PRINTF_ATTRIBUTE
+#define PRINTF_ATTRIBUTE(m, n)
+#endif
+
+#ifndef HAVE_ASPRINTF_DECL
+/*PRINTFLIKE2 */
+int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3);
+#endif
+
#ifdef HAVE_NS_API_H
#undef VOLATILE
+#undef STATIC
+#undef DYNAMIC
#include <ns_daemon.h>
#endif
@@ -165,13 +177,10 @@ static int
winbind_callback(nsd_file_t **rqp, int fd)
{
struct winbindd_response response;
- struct winbindd_pw *pw = &response.data.pw;
- struct winbindd_gr *gr = &response.data.gr;
nsd_file_t *rq;
NSS_STATUS status;
- fstring result;
- char *members;
- int i, maxlen;
+ char * result = NULL;
+ size_t rlen;
dequeue_request();
@@ -192,76 +201,164 @@ winbind_callback(nsd_file_t **rqp, int fd)
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) returning not found, status = %d\n",
status);
- rq->f_status = NS_NOTFOUND;
+
+ switch (status) {
+ case NSS_STATUS_UNAVAIL:
+ rq->f_status = NS_UNAVAIL;
+ break;
+ case NSS_STATUS_TRYAGAIN:
+ rq->f_status = NS_TRYAGAIN;
+ break;
+ case NSS_STATUS_NOTFOUND:
+ /* FALLTHRU */
+ default:
+ rq->f_status = NS_NOTFOUND;
+ }
+
return NSD_NEXT;
}
- maxlen = sizeof(result) - 1;
-
switch ((int)rq->f_cmd_data) {
case WINBINDD_WINS_BYNAME:
case WINBINDD_WINS_BYIP:
- snprintf(result,maxlen,"%s\n",response.data.winsresp);
- break;
+ nsd_logprintf(NSD_LOG_MIN,
+ "callback (winbind) WINS_BYNAME | WINS_BYIP\n");
+
+ rlen = asprintf(&result, "%s\n", response.data.winsresp);
+ if (rlen == 0 || result == NULL) {
+ return NSD_ERROR;
+ }
+
+ free_response(&response);
+
+ nsd_logprintf(NSD_LOG_MIN, " %s\n", result);
+ nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
+ return NSD_OK;
+
case WINBINDD_GETPWUID:
case WINBINDD_GETPWNAM:
- snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s\n",
- pw->pw_name,
- pw->pw_passwd,
- pw->pw_uid,
- pw->pw_gid,
- pw->pw_gecos,
- pw->pw_dir,
- pw->pw_shell);
- break;
+ {
+ struct winbindd_pw *pw = &response.data.pw;
+
+ nsd_logprintf(NSD_LOG_MIN,
+ "callback (winbind) GETPWUID | GETPWUID\n");
+
+ rlen = asprintf(&result,"%s:%s:%d:%d:%s:%s:%s\n",
+ pw->pw_name,
+ pw->pw_passwd,
+ pw->pw_uid,
+ pw->pw_gid,
+ pw->pw_gecos,
+ pw->pw_dir,
+ pw->pw_shell);
+ if (rlen == 0 || result == NULL)
+ return NSD_ERROR;
+
+ free_response(&response);
+
+ nsd_logprintf(NSD_LOG_MIN, " %s\n", result);
+ nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
+ return NSD_OK;
+ }
+
case WINBINDD_GETGRNAM:
case WINBINDD_GETGRGID:
- if (gr->num_gr_mem && response.extra_data.data)
- members = response.extra_data.data;
- else
- members = "";
- snprintf(result,maxlen,"%s:%s:%d:%s\n",
- gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
- break;
+ {
+ const struct winbindd_gr *gr = &response.data.gr;
+ const char * members;
+
+ nsd_logprintf(NSD_LOG_MIN,
+ "callback (winbind) GETGRNAM | GETGRGID\n");
+
+ if (gr->num_gr_mem && response.extra_data.data) {
+ members = response.extra_data.data;
+ } else {
+ members = "";
+ }
+
+ rlen = asprintf(&result, "%s:%s:%d:%s\n",
+ gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
+ if (rlen == 0 || result == NULL)
+ return NSD_ERROR;
+
+ free_response(&response);
+
+ nsd_logprintf(NSD_LOG_MIN, " %s\n", result);
+ nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
+ return NSD_OK;
+ }
+
case WINBINDD_SETGRENT:
case WINBINDD_SETPWENT:
- nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - SETPWENT/SETGRENT\n");
+ nsd_logprintf(NSD_LOG_MIN,
+ "callback (winbind) SETGRENT | SETPWENT\n");
free_response(&response);
return(do_list(1,rq));
+
case WINBINDD_GETGRENT:
case WINBINDD_GETGRLST:
- nsd_logprintf(NSD_LOG_MIN,
- "callback (winbind) - %d GETGRENT responses\n",
- response.data.num_entries);
- if (response.data.num_entries) {
- gr = (struct winbindd_gr *)response.extra_data.data;
- if (! gr ) {
- nsd_logprintf(NSD_LOG_MIN, " no extra_data.data\n");
- free_response(&response);
- return NSD_ERROR;
- }
- 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",
- gr->gr_name, gr->gr_passwd, gr->gr_gid,
- &members[gr->gr_mem_ofs]);
- nsd_logprintf(NSD_LOG_MIN, " GETGRENT %s\n",result);
- nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
- gr++;
- }
- }
- i = response.data.num_entries;
- free_response(&response);
- if (i < MAX_GETPWENT_USERS)
- return(do_list(2,rq));
- else
- return(do_list(1,rq));
+ {
+ int entries;
+
+ nsd_logprintf(NSD_LOG_MIN,
+ "callback (winbind) GETGRENT | GETGRLIST %d responses\n",
+ response.data.num_entries);
+
+ if (response.data.num_entries) {
+ const struct winbindd_gr *gr = &response.data.gr;
+ const char * members;
+ fstring grp_name;
+ int i;
+
+ gr = (struct winbindd_gr *)response.extra_data.data;
+ if (! gr ) {
+ nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
+ free_response(&response);
+ return NSD_ERROR;
+ }
+
+ members = (char *)response.extra_data.data +
+ (response.data.num_entries * sizeof(struct winbindd_gr));
+
+ for (i = 0; i < response.data.num_entries; i++) {
+ snprintf(grp_name, sizeof(grp_name) - 1, "%s:%s:%d:",
+ gr->gr_name, gr->gr_passwd, gr->gr_gid);
+
+ nsd_append_element(rq, NS_SUCCESS, result, rlen);
+ nsd_append_result(rq, NS_SUCCESS,
+ &members[gr->gr_mem_ofs],
+ strlen(&members[gr->gr_mem_ofs]));
+
+ /* Don't log the whole list, because it might be
+ * _really_ long and we probably don't want to clobber
+ * the log with it.
+ */
+ nsd_logprintf(NSD_LOG_MIN, " %s (...)\n", grp_name);
+
+ gr++;
+ }
+ }
+
+ entries = response.data.num_entries;
+ free_response(&response);
+ if (entries < MAX_GETPWENT_USERS)
+ return(do_list(2,rq));
+ else
+ return(do_list(1,rq));
+ }
+
case WINBINDD_GETPWENT:
- nsd_logprintf(NSD_LOG_MIN,
- "callback (winbind) - %d GETPWENT responses\n",
+ {
+ int entries;
+
+ nsd_logprintf(NSD_LOG_MIN,
+ "callback (winbind) GETPWENT %d responses\n",
response.data.num_entries);
+
if (response.data.num_entries) {
+ struct winbindd_pw *pw = &response.data.pw;
+ int i;
+
pw = (struct winbindd_pw *)response.extra_data.data;
if (! pw ) {
nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
@@ -269,41 +366,46 @@ winbind_callback(nsd_file_t **rqp, int fd)
return NSD_ERROR;
}
for (i = 0; i < response.data.num_entries; i++) {
- snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s",
- pw->pw_name,
- pw->pw_passwd,
- pw->pw_uid,
- pw->pw_gid,
- pw->pw_gecos,
- pw->pw_dir,
- pw->pw_shell);
- nsd_logprintf(NSD_LOG_MIN, " GETPWENT %s\n",result);
- nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
+ result = NULL;
+ rlen = asprintf(&result, "%s:%s:%d:%d:%s:%s:%s",
+ pw->pw_name,
+ pw->pw_passwd,
+ pw->pw_uid,
+ pw->pw_gid,
+ pw->pw_gecos,
+ pw->pw_dir,
+ pw->pw_shell);
+
+ if (rlen != 0 && result != NULL) {
+ nsd_logprintf(NSD_LOG_MIN, " %s\n",result);
+ nsd_append_element(rq, NS_SUCCESS, result, rlen);
+ free(result);
+ }
+
pw++;
}
}
- i = response.data.num_entries;
+
+ entries = response.data.num_entries;
free_response(&response);
- if (i < MAX_GETPWENT_USERS)
+ if (entries < MAX_GETPWENT_USERS)
return(do_list(2,rq));
else
return(do_list(1,rq));
+ }
+
case WINBINDD_ENDGRENT:
case WINBINDD_ENDPWENT:
- nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - ENDPWENT/ENDGRENT\n");
- nsd_append_element(rq,NS_SUCCESS,"\n",1);
+ nsd_logprintf(NSD_LOG_MIN, "callback (winbind) ENDGRENT | ENDPWENT\n");
+ nsd_append_element(rq, NS_SUCCESS, "\n", 1);
free_response(&response);
return NSD_NEXT;
+
default:
free_response(&response);
- nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - no valid command\n");
+ nsd_logprintf(NSD_LOG_MIN, "callback (winbind) invalid command %d\n", (int)rq->f_cmd_data);
return NSD_NEXT;
}
- nsd_logprintf(NSD_LOG_MIN, "callback (winbind) %s\n", result);
- /* free any extra data area in response structure */
- free_response(&response);
- nsd_set_result(rq,NS_SUCCESS,result,strlen(result),VOLATILE);
- return NSD_OK;
}
static int
@@ -349,14 +451,16 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
return NSD_NEXT;
}
- nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d to = %d\n",
+ nsd_logprintf(NSD_LOG_MIN,
+ "send_next_request (winbind) %d, timeout = %d sec\n",
rq->f_cmd_data, timeout);
status = winbindd_send_request((int)rq->f_cmd_data,request);
SAFE_FREE(request);
if (status != NSS_STATUS_SUCCESS) {
nsd_logprintf(NSD_LOG_MIN,
- "send_next_request (winbind) error status = %d\n",status);
+ "send_next_request (winbind) error status = %d\n",
+ status);
rq->f_status = status;
return NSD_NEXT;
}
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index e6c69247f85..cc904c32091 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -769,10 +769,14 @@ static void process_loop(void)
selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
- if (selret == 0)
+ if (selret == 0) {
goto no_fds_ready;
+ }
- if ((selret == -1 && errno != EINTR) || selret == 0) {
+ if (selret == -1) {
+ if (errno == EINTR) {
+ goto no_fds_ready;
+ }
/* Select error, something is badly wrong */
@@ -780,6 +784,8 @@ static void process_loop(void)
exit(1);
}
+ /* selret > 0 */
+
ev = fd_events;
while (ev != NULL) {
struct fd_event *next = ev->next;
@@ -1035,6 +1041,7 @@ int main(int argc, char **argv)
/* Handle online/offline messages. */
message_register(MSG_WINBIND_OFFLINE,winbind_msg_offline);
message_register(MSG_WINBIND_ONLINE,winbind_msg_online);
+ message_register(MSG_WINBIND_ONLINESTATUS,winbind_msg_onlinestatus);
poptFreeContext(pc);
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index e5f1c9699ca..7d5330dccb2 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -33,6 +33,10 @@
#include "libnscd.h"
#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index 5e0d4cfe8e0..8259fd7cd36 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -38,6 +38,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
{
ADS_STRUCT *ads;
ADS_STATUS status;
+ enum wb_posix_mapping map_type;
+
+ DEBUG(10,("ads_cached_connection\n"));
if (domain->private_data) {
ads = (ADS_STRUCT *)domain->private_data;
@@ -125,11 +128,18 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
return NULL;
}
- if (use_nss_info("sfu") && (!ads_check_sfu_mapping(ads))) {
- DEBUG(0,("ads_cached_connection: failed to check sfu attributes\n"));
- return NULL;
- }
+ map_type = get_nss_info(domain->name);
+
+ if ((map_type == WB_POSIX_MAP_RFC2307)||
+ (map_type == WB_POSIX_MAP_SFU)) {
+ status = ads_check_posix_schema_mapping(ads, map_type);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(10,("ads_check_posix_schema_mapping failed "
+ "with: %s\n", ads_errstr(status)));
+ }
+ }
+
/* set the flag that says we don't own the memory even
though we do so that ads_destroy() won't destroy the
structure we pass back by reference */
@@ -155,6 +165,9 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
ADS_ATTR_SFU_HOMEDIR_OID,
ADS_ATTR_SFU_SHELL_OID,
ADS_ATTR_SFU_GECOS_OID,
+ ADS_ATTR_RFC2307_HOMEDIR_OID,
+ ADS_ATTR_RFC2307_SHELL_OID,
+ ADS_ATTR_RFC2307_GECOS_OID,
NULL};
int i, count;
ADS_STATUS rc;
@@ -173,7 +186,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
goto done;
}
- rc = ads_search_retry(ads, &res, "(objectClass=user)", attrs);
+ rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
if (!ADS_ERR_OK(rc) || !res) {
DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
goto done;
@@ -208,13 +221,17 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
name = ads_pull_username(ads, mem_ctx, msg);
- if (use_nss_info("sfu")) {
+ if (get_nss_info(domain->name) && ads->schema.map_type) {
+
+ DEBUG(10,("pulling posix attributes (%s schema)\n",
+ wb_posix_map_str(ads->schema.map_type)));
+
homedir = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.sfu_homedir_attr);
+ ads->schema.posix_homedir_attr);
shell = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.sfu_shell_attr);
+ ads->schema.posix_shell_attr);
gecos = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.sfu_gecos_attr);
+ ads->schema.posix_gecos_attr);
}
if (gecos == NULL) {
@@ -446,6 +463,9 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
ADS_ATTR_SFU_HOMEDIR_OID,
ADS_ATTR_SFU_SHELL_OID,
ADS_ATTR_SFU_GECOS_OID,
+ ADS_ATTR_RFC2307_HOMEDIR_OID,
+ ADS_ATTR_RFC2307_SHELL_OID,
+ ADS_ATTR_RFC2307_GECOS_OID,
NULL};
ADS_STATUS rc;
int count;
@@ -484,13 +504,17 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
info->acct_name = ads_pull_username(ads, mem_ctx, msg);
- if (use_nss_info("sfu")) {
+ if (get_nss_info(domain->name) && ads->schema.map_type) {
+
+ DEBUG(10,("pulling posix attributes (%s schema)\n",
+ wb_posix_map_str(ads->schema.map_type)));
+
info->homedir = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.sfu_homedir_attr);
+ ads->schema.posix_homedir_attr);
info->shell = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.sfu_shell_attr);
+ ads->schema.posix_shell_attr);
info->full_name = ads_pull_string(ads, mem_ctx, msg,
- ads->schema.sfu_gecos_attr);
+ ads->schema.posix_gecos_attr);
}
if (info->full_name == NULL) {
@@ -518,11 +542,11 @@ done:
/* Lookup groups a user is a member of - alternate method, for when
tokenGroups are not available. */
-static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const char *user_dn,
- DOM_SID *primary_group,
- size_t *p_num_groups, DOM_SID **user_sids)
+static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_dn,
+ DOM_SID *primary_group,
+ size_t *p_num_groups, DOM_SID **user_sids)
{
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
@@ -535,7 +559,7 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
char *escaped_dn;
size_t num_groups = 0;
- DEBUG(3,("ads: lookup_usergroups_alt\n"));
+ DEBUG(3,("ads: lookup_usergroups_member\n"));
ads = ads_cached_connection(domain);
@@ -549,10 +573,7 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
goto done;
}
- /* buggy server, no tokenGroups. Instead lookup what groups this user
- is a member of by DN search on member*/
-
- if (!(ldap_exp = talloc_asprintf(mem_ctx, "(&(member=%s)(objectClass=group))", escaped_dn))) {
+ if (!(ldap_exp = talloc_asprintf(mem_ctx, "(&(member=%s)(objectCategory=group))", escaped_dn))) {
DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
SAFE_FREE(escaped_dn);
status = NT_STATUS_NO_MEMORY;
@@ -585,7 +606,12 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
DEBUG(1,("No sid for this group ?!?\n"));
continue;
}
-
+
+ /* ignore Builtin groups from ADS - Guenther */
+ if (sid_check_is_in_builtin(&group_sid)) {
+ continue;
+ }
+
add_sid_to_array(mem_ctx, &group_sid, user_sids,
&num_groups);
}
@@ -595,7 +621,7 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain,
*p_num_groups = num_groups;
status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
- DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn));
+ DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
done:
if (res)
ads_msgfree(ads, res);
@@ -603,6 +629,89 @@ done:
return status;
}
+/* Lookup groups a user is a member of - alternate method, for when
+ tokenGroups are not available. */
+static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *user_dn,
+ DOM_SID *primary_group,
+ size_t *p_num_groups, DOM_SID **user_sids)
+{
+ ADS_STATUS rc;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ int count;
+ void *res = NULL;
+ ADS_STRUCT *ads;
+ const char *attrs[] = {"memberOf", NULL};
+ size_t num_groups = 0;
+ DOM_SID *group_sids = NULL;
+ int i;
+
+ DEBUG(3,("ads: lookup_usergroups_memberof\n"));
+
+ ads = ads_cached_connection(domain);
+
+ if (!ads) {
+ domain->last_status = NT_STATUS_SERVER_DISABLED;
+ goto done;
+ }
+
+ rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs,
+ ADS_EXTENDED_DN_HEX_STRING);
+
+ if (!ADS_ERR_OK(rc) || !res) {
+ DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n",
+ user_dn, ads_errstr(rc)));
+ return ads_ntstatus(rc);
+ }
+
+ count = ads_count_replies(ads, res);
+
+ if (count == 0) {
+ status = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ }
+
+ *user_sids = NULL;
+ num_groups = 0;
+
+ /* always add the primary group to the sid array */
+ add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups);
+
+ count = ads_pull_sids_from_extendeddn(ads, mem_ctx, res, "memberOf",
+ ADS_EXTENDED_DN_HEX_STRING,
+ &group_sids);
+ if (count == 0) {
+ DEBUG(1,("No memberOf for this user?!?\n"));
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i<count; i++) {
+
+ /* ignore Builtin groups from ADS - Guenther */
+ if (sid_check_is_in_builtin(&group_sids[i])) {
+ continue;
+ }
+
+ add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
+ &num_groups);
+
+ }
+
+ *p_num_groups = num_groups;
+ status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+
+ DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n", user_dn));
+done:
+ TALLOC_FREE(group_sids);
+ if (res)
+ ads_msgfree(ads, res);
+
+ return status;
+}
+
+
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -626,6 +735,12 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
DEBUG(3,("ads: lookup_usergroups\n"));
*p_num_groups = 0;
+ status = lookup_usergroups_cached(domain, mem_ctx, sid,
+ p_num_groups, user_sids);
+ if (NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_OK;
+ }
+
ads = ads_cached_connection(domain);
if (!ads) {
@@ -634,13 +749,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
goto done;
}
- rc = ads_sid_to_dn(ads, mem_ctx, sid, &user_dn);
- if (!ADS_ERR_OK(rc)) {
- status = ads_ntstatus(rc);
- goto done;
- }
+ rc = ads_search_retry_sid(ads, (void**)(void *)&msg, sid, attrs);
- rc = ads_search_retry_dn(ads, (void**)(void *)&msg, user_dn, attrs);
if (!ADS_ERR_OK(rc)) {
status = ads_ntstatus(rc);
DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n",
@@ -648,6 +758,15 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
goto done;
}
+ count = ads_count_replies(ads, msg);
+ if (count != 1) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
+ "invalid number of results (count=%d)\n",
+ sid_to_string(sid_string, sid), count));
+ goto done;
+ }
+
if (!msg) {
DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
sid_to_string(sid_string, sid)));
@@ -655,6 +774,12 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
goto done;
}
+ user_dn = ads_get_dn(ads, msg);
+ if (user_dn == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
DEBUG(1,("%s: No primary group for sid=%s !?\n",
domain->name, sid_to_string(sid_string, sid)));
@@ -671,12 +796,30 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
/* there must always be at least one group in the token,
unless we are talking to a buggy Win2k server */
+
+ /* actually this only happens when the machine account has no read
+ * permissions on the tokenGroup attribute - gd */
+
if (count == 0) {
- status = lookup_usergroups_alt(domain, mem_ctx, user_dn,
- &primary_group,
- &num_groups, user_sids);
- *p_num_groups = (uint32)num_groups;
- return status;
+
+ /* no tokenGroups */
+
+ /* lookup what groups this user is a member of by DN search on
+ * "memberOf" */
+
+ status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
+ &primary_group,
+ p_num_groups, user_sids);
+ if (NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* lookup what groups this user is a member of by DN search on
+ * "member" */
+
+ return lookup_usergroups_member(domain, mem_ctx, user_dn,
+ &primary_group,
+ p_num_groups, user_sids);
}
*user_sids = NULL;
@@ -698,7 +841,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
*p_num_groups = (uint32)num_groups;
status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
- DEBUG(3,("ads lookup_usergroups for sid=%s\n",
+ DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
sid_to_string(sid_string, sid)));
done:
return status;
@@ -826,6 +969,14 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
(*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members);
(*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members);
+ if ((num_members != 0) &&
+ ((members == NULL) || (*sid_mem == NULL) ||
+ (*name_types == NULL) || (*names == NULL))) {
+ DEBUG(1, ("talloc failed\n"));
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
for (i=0;i<num_members;i++) {
uint32 name_type;
char *name;
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index 76e49ee96a0..0c096352d39 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -524,6 +524,12 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
char *kstr;
struct cache_entry *centry;
+ extern BOOL opt_nocache;
+
+ if (opt_nocache) {
+ return NULL;
+ }
+
refresh_sequence_number(domain, False);
va_start(ap, format);
@@ -2095,19 +2101,14 @@ 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);
+ centry = wcache_fetch_raw(kbuf.dptr);
if (!centry) {
return 0;
}
if (!NT_STATUS_IS_OK(centry->status)) {
- DEBUG(10,("deleting centry %s\n", buf));
+ DEBUG(10,("deleting centry %s\n", kbuf.dptr));
tdb_delete(the_tdb, kbuf);
}
@@ -2351,6 +2352,11 @@ void set_global_winbindd_state_online(void)
tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE");
}
+BOOL get_global_winbindd_state_online(void)
+{
+ return global_winbindd_offline_state;
+}
+
/* the cache backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
True,
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index 9e450d9de74..6322a33c029 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -618,18 +618,11 @@ static void dcip_to_name( const char *domainname, const char *realm,
if ( lp_security() == SEC_ADS )
{
ADS_STRUCT *ads;
- ADS_STATUS status;
ads = ads_init( realm, domainname, NULL );
ads->auth.flags |= ADS_AUTH_NO_BIND;
- if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
- ads_destroy( &ads );
- return;
- }
-
- status = ads_server_info(ads);
- if ( !ADS_ERR_OK(status) ) {
+ if ( !ads_try_connect( ads, inet_ntoa(ip) ) ) {
ads_destroy( &ads );
return;
}
diff --git a/source/nsswitch/winbindd_cred_cache.c b/source/nsswitch/winbindd_cred_cache.c
index 4c539b9b23a..5fdb79c107a 100644
--- a/source/nsswitch/winbindd_cred_cache.c
+++ b/source/nsswitch/winbindd_cred_cache.c
@@ -74,7 +74,25 @@ NTSTATUS remove_ccache_by_ccname(const char *ccname)
if (strequal(entry->ccname, ccname)) {
DLIST_REMOVE(ccache_list, entry);
TALLOC_FREE(entry->event); /* unregisters events */
+#ifdef HAVE_MUNLOCK
+ if (entry->pass) {
+ size_t len = strlen(entry->pass)+1;
+#ifdef DEBUG_PASSWORD
+ DEBUG(10,("unlocking memory: %p\n", entry->pass));
+#endif
+ memset(&(entry->pass), 0, len);
+ if ((munlock(&entry->pass, len)) == -1) {
+ DEBUG(0,("failed to munlock memory: %s (%d)\n",
+ strerror(errno), errno));
+ return map_nt_error_from_unix(errno);
+ }
+#ifdef DEBUG_PASSWORD
+ DEBUG(10,("munlocked memory: %p\n", entry->pass));
+#endif
+ }
+#endif /* HAVE_MUNLOCK */
TALLOC_FREE(entry);
+ DEBUG(10,("remove_ccache_by_ccname: removed ccache %s\n", ccname));
return NT_STATUS_OK;
}
}
@@ -104,7 +122,7 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
if ((entry->renew_until < time(NULL)) && (entry->pass != NULL)) {
- seteuid(entry->uid);
+ set_effective_uid(entry->uid);
ret = kerberos_kinit_password_ext(entry->principal_name,
entry->pass,
@@ -113,8 +131,9 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
&entry->renew_until,
entry->ccname,
False, /* no PAC required anymore */
+ True,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
- seteuid(0);
+ gain_root_privilege();
if (ret) {
DEBUG(3,("could not re-kinit: %s\n", error_message(ret)));
@@ -130,13 +149,13 @@ static void krb5_ticket_refresh_handler(struct timed_event *te,
goto done;
}
- seteuid(entry->uid);
+ set_effective_uid(entry->uid);
ret = smb_krb5_renew_ticket(entry->ccname,
entry->principal_name,
entry->service,
&new_start);
- seteuid(0);
+ gain_root_privilege();
if (ret) {
DEBUG(3,("could not renew tickets: %s\n", error_message(ret)));
@@ -170,6 +189,7 @@ NTSTATUS add_ccache_to_list(const char *princ_name,
BOOL schedule_refresh_event)
{
struct WINBINDD_CCACHE_ENTRY *new_entry = NULL;
+ struct WINBINDD_CCACHE_ENTRY *old_entry = NULL;
NTSTATUS status;
if ((username == NULL && sid_string == NULL && princ_name == NULL) ||
@@ -191,6 +211,16 @@ NTSTATUS add_ccache_to_list(const char *princ_name,
return NT_STATUS_NO_MORE_ENTRIES;
}
+ /* get rid of old entries */
+ old_entry = get_ccache_by_username(username);
+ if (old_entry) {
+ status = remove_ccache_by_ccname(old_entry->ccname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("add_ccache_to_list: failed to delete old ccache entry\n"));
+ return status;
+ }
+ }
+
new_entry = TALLOC_P(mem_ctx, struct WINBINDD_CCACHE_ENTRY);
if (new_entry == NULL) {
return NT_STATUS_NO_MEMORY;
@@ -214,9 +244,31 @@ NTSTATUS add_ccache_to_list(const char *princ_name,
new_entry->service = talloc_strdup(mem_ctx, service);
NT_STATUS_HAVE_NO_MEMORY(new_entry->service);
}
- if (pass) {
+
+ if (schedule_refresh_event && pass) {
+#ifdef HAVE_MLOCK
+ size_t len = strlen(pass)+1;
+
+ new_entry->pass = TALLOC_ZERO(mem_ctx, len);
+ NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(10,("mlocking memory: %p\n", new_entry->pass));
+#endif
+ if ((mlock(new_entry->pass, len)) == -1) {
+ DEBUG(0,("failed to mlock memory: %s (%d)\n",
+ strerror(errno), errno));
+ return map_nt_error_from_unix(errno);
+ }
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(10,("mlocked memory: %p\n", new_entry->pass));
+#endif
+ memcpy(new_entry->pass, pass, len);
+#else
new_entry->pass = talloc_strdup(mem_ctx, pass);
NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
+#endif /* HAVE_MLOCK */
}
new_entry->create_time = create_time;
@@ -248,6 +300,13 @@ NTSTATUS add_ccache_to_list(const char *princ_name,
NTSTATUS destroy_ccache_list(void)
{
+#ifdef HAVE_MUNLOCKALL
+ if ((munlockall()) == -1) {
+ DEBUG(0,("failed to unlock memory: %s (%d)\n",
+ strerror(errno), errno));
+ return map_nt_error_from_unix(errno);
+ }
+#endif /* HAVE_MUNLOCKALL */
return talloc_destroy(mem_ctx) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index c5d24f98c1b..3003a314c03 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -496,6 +496,26 @@ void winbind_msg_online(int msg_type, struct process_id src, void *buf, size_t l
}
}
+/* Forward the online/offline messages to our children. */
+void winbind_msg_onlinestatus(int msg_type, struct process_id src, void *buf, size_t len)
+{
+ struct winbindd_child *child;
+
+ DEBUG(10,("winbind_msg_onlinestatus: got onlinestatus message.\n"));
+
+ for (child = children; child != NULL; child = child->next) {
+ if (child->domain && child->domain->primary) {
+ DEBUG(10,("winbind_msg_onlinestatus: "
+ "sending message to pid %u of primary domain.\n",
+ (unsigned int)child->pid));
+ message_send_pid(pid_to_procid(child->pid),
+ MSG_WINBIND_ONLINESTATUS, buf, len, False);
+ break;
+ }
+ }
+}
+
+
static void account_lockout_policy_handler(struct timed_event *te,
const struct timeval *now,
void *private_data)
@@ -582,6 +602,60 @@ static void child_msg_online(int msg_type, struct process_id src, void *buf, siz
}
}
+static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
+{
+ struct winbindd_domain *domain;
+ char *buf = NULL;
+
+ if ((buf = talloc_asprintf(mem_ctx, "global:%s ",
+ get_global_winbindd_state_online() ?
+ "Offline":"Online")) == NULL) {
+ return NULL;
+ }
+
+ for (domain = domain_list(); domain; domain = domain->next) {
+ if ((buf = talloc_asprintf_append(buf, "%s:%s ",
+ domain->name,
+ domain->online ?
+ "Online":"Offline")) == NULL) {
+ return NULL;
+ }
+ }
+
+ buf = talloc_asprintf_append(buf, "\n");
+
+ DEBUG(5,("collect_onlinestatus: %s", buf));
+
+ return buf;
+}
+
+static void child_msg_onlinestatus(int msg_type, struct process_id src, void *buf, size_t len)
+{
+ TALLOC_CTX *mem_ctx;
+ const char *message;
+ struct process_id *sender;
+
+ DEBUG(5,("winbind_msg_onlinestatus received.\n"));
+
+ if (!buf) {
+ return;
+ }
+
+ sender = (struct process_id *)buf;
+
+ mem_ctx = talloc_init("winbind_msg_onlinestatus");
+ if (mem_ctx == NULL) {
+ return;
+ }
+
+ message = collect_onlinestatus(mem_ctx);
+
+ message_send_pid(*sender, MSG_WINBIND_ONLINESTATUS,
+ message, strlen(message) + 1, True);
+
+ talloc_destroy(mem_ctx);
+}
+
static BOOL fork_domain_child(struct winbindd_child *child)
{
int fdpair[2];
@@ -646,6 +720,7 @@ static BOOL fork_domain_child(struct winbindd_child *child)
message_deregister(MSG_SHUTDOWN);
message_deregister(MSG_WINBIND_OFFLINE);
message_deregister(MSG_WINBIND_ONLINE);
+ message_deregister(MSG_WINBIND_ONLINESTATUS);
/* The child is ok with online/offline messages now. */
message_unblock();
@@ -667,6 +742,7 @@ static BOOL fork_domain_child(struct winbindd_child *child)
/* Handle online/offline messages. */
message_register(MSG_WINBIND_OFFLINE,child_msg_offline);
message_register(MSG_WINBIND_ONLINE,child_msg_online);
+ message_register(MSG_WINBIND_ONLINESTATUS,child_msg_onlinestatus);
while (1) {
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index fe09cd8a06d..34e0d097219 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -394,7 +394,7 @@ struct WINBINDD_CCACHE_ENTRY {
const char *service;
const char *username;
const char *sid_string;
- const char *pass;
+ char *pass;
uid_t uid;
time_t create_time;
time_t renew_until;
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index 6f077294934..b02ba8e36ca 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -478,7 +478,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
if (!internal_ccache) {
- seteuid(uid);
+ set_effective_uid(uid);
DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
}
@@ -489,6 +489,7 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
&renewal_until,
cc,
True,
+ True,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
if (krb5_ret) {
@@ -532,13 +533,14 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
}
if (!internal_ccache) {
- seteuid(0);
+ gain_root_privilege();
}
/************************ NON-ROOT **********************/
result = ads_verify_ticket(state->mem_ctx,
lp_realm(),
+ time_offset,
&tkt,
&client_princ_out,
&pac_data,
@@ -610,11 +612,16 @@ failed:
krb5_ret = ads_kdestroy(cc);
if (krb5_ret) {
- DEBUG(0,("winbindd_raw_kerberos_login: "
+ DEBUG(3,("winbindd_raw_kerberos_login: "
"could not destroy krb5 credential cache: "
"%s\n", error_message(krb5_ret)));
}
+ if (!NT_STATUS_IS_OK(remove_ccache_by_ccname(cc))) {
+ DEBUG(3,("winbindd_raw_kerberos_login: "
+ "could not remove ccache\n"));
+ }
+
done:
data_blob_free(&session_key);
data_blob_free(&session_key_krb5);
@@ -624,7 +631,7 @@ done:
SAFE_FREE(client_princ_out);
if (!internal_ccache) {
- seteuid(0);
+ gain_root_privilege();
}
return result;
@@ -1105,7 +1112,9 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result)));
}
- if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)) {
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_IO_TIMEOUT) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
domain->online = False;
}
@@ -1644,6 +1653,9 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
oldpass = state->request.data.chauthtok.oldpass;
newpass = state->request.data.chauthtok.newpass;
+ /* Initialize reject reason */
+ state->response.data.auth.reject_reason = Undefined;
+
/* Get sam handle */
result = cm_connect_sam(contact_domain, state->mem_ctx, &cli,
@@ -1682,8 +1694,6 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
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);
}
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 4aaedad4a21..22df8d4db96 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -412,7 +412,6 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
unsigned int i;
fstring sid_string;
uint32 user_rid;
- NET_USER_INFO_3 *user;
struct rpc_pipe_client *cli;
DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
@@ -425,23 +424,10 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
*user_grpsids = NULL;
/* so lets see if we have a cached user_info_3 */
-
- if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
- {
- DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
- sid_string_static(user_sid)));
-
- *num_groups = user->num_groups;
-
- (*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
- for (i=0;i<(*num_groups);i++) {
- sid_copy(&((*user_grpsids)[i]), &domain->sid);
- sid_append_rid(&((*user_grpsids)[i]),
- user->gids[i].g_rid);
- }
-
- SAFE_FREE(user);
-
+ result = lookup_usergroups_cached(domain, mem_ctx, user_sid,
+ num_groups, user_grpsids);
+
+ if (NT_STATUS_IS_OK(result)) {
return NT_STATUS_OK;
}
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 6179e497b78..07bd2a30bf7 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -43,7 +43,7 @@ static BOOL fillup_pw_field(const char *lp_template,
if (out == NULL)
return False;
- if (in && !strequal(in,"") && lp_security() == SEC_ADS && use_nss_info("sfu")) {
+ if (in && !strequal(in,"") && lp_security() == SEC_ADS && (get_nss_info(domname))) {
safe_strcpy(out, in, sizeof(fstring) - 1);
return True;
}
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index d64345a36f3..4e5075d89d0 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -1232,3 +1232,52 @@ void winbindd_flush_nscd_cache(void)
#endif
}
+NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *user_sid,
+ uint32 *p_num_groups, DOM_SID **user_sids)
+{
+ NET_USER_INFO_3 *info3 = NULL;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+ int i;
+ size_t num_groups = 0;
+ DOM_SID group_sid, primary_group;
+
+ DEBUG(3,(": lookup_usergroups_cached\n"));
+
+ *user_sids = NULL;
+ num_groups = 0;
+ *p_num_groups = 0;
+
+ info3 = netsamlogon_cache_get(mem_ctx, user_sid);
+
+ if (info3 == NULL) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ if (info3->num_groups == 0) {
+ SAFE_FREE(info3);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* always add the primary group to the sid array */
+ sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
+
+ add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups);
+
+ for (i=0; i<info3->num_groups; i++) {
+ sid_copy(&group_sid, &info3->dom_sid.sid);
+ sid_append_rid(&group_sid, info3->gids[i].g_rid);
+
+ add_sid_to_array(mem_ctx, &group_sid, user_sids,
+ &num_groups);
+ }
+
+ SAFE_FREE(info3);
+ *p_num_groups = num_groups;
+ status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
+
+ DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
+
+ return status;
+}
diff --git a/source/pam_smbpass/general.h b/source/pam_smbpass/general.h
index 4f13d601313..f84c2544440 100644
--- a/source/pam_smbpass/general.h
+++ b/source/pam_smbpass/general.h
@@ -50,10 +50,6 @@ typedef struct {
#define set(x,ctrl) (ctrl = ((ctrl)&smb_args[x].mask)|smb_args[x].flag)
#define unset(x,ctrl) (ctrl &= ~(smb_args[x].flag))
-#ifndef __linux__
-#define strncasecmp(s1,s2,n) StrnCaseCmp(s1,s2,n)
-#endif
-
/* the generic mask */
#define _ALL_ON_ (~0U)
diff --git a/source/pam_smbpass/support.c b/source/pam_smbpass/support.c
index c318a5c3ed1..2ee43ffa1e1 100644
--- a/source/pam_smbpass/support.c
+++ b/source/pam_smbpass/support.c
@@ -114,7 +114,7 @@
struct pam_response *resp;
pmsg[0] = &msg[0];
- msg[0].msg = text;
+ msg[0].msg = CONST_DISCARD(char *, text);
msg[0].msg_style = type;
resp = NULL;
@@ -515,7 +515,7 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl,
if (comment != NULL && off(SMB__QUIET, ctrl)) {
pmsg[0] = &msg[0];
msg[0].msg_style = PAM_TEXT_INFO;
- msg[0].msg = comment;
+ msg[0].msg = CONST_DISCARD(char *, comment);
i = 1;
} else {
i = 0;
@@ -523,12 +523,12 @@ int _smb_read_password( pam_handle_t * pamh, unsigned int ctrl,
pmsg[i] = &msg[i];
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
- msg[i++].msg = prompt1;
+ msg[i++].msg = CONST_DISCARD(char *, prompt1);
if (prompt2 != NULL) {
pmsg[i] = &msg[i];
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
- msg[i++].msg = prompt2;
+ msg[i++].msg = CONST_DISCARD(char *, prompt2);
expect = 2;
} else
expect = 1;
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 34b463de221..fadd4d0ee3f 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -56,7 +56,6 @@
BOOL in_client = False; /* Not in the client by default */
BOOL bLoaded = False;
-extern userdom_struct current_user_info;
extern pstring user_socket_options;
extern enum protocol_types Protocol;
@@ -115,7 +114,6 @@ typedef struct {
char *szGetQuota;
char *szSetQuota;
char *szMsgCommand;
- char *szHostsEquiv;
char *szServerString;
char *szAutoServices;
char *szPasswdProgram;
@@ -164,7 +162,6 @@ typedef struct {
char *szUsernameMapScript;
char *szCheckPasswordScript;
char *szWINSHook;
- char *szWINSPartners;
char *szUtmpDir;
char *szWtmpDir;
BOOL bUtmp;
@@ -223,7 +220,6 @@ typedef struct {
int lm_interval;
int announce_as; /* This is initialised in init_globals */
int machine_password_timeout;
- int change_notify_timeout;
int map_to_guest;
int oplock_break_wait_time;
int winbind_cache_time;
@@ -235,10 +231,6 @@ typedef struct {
char *szLdapUserSuffix;
char *szLdapIdmapSuffix;
char *szLdapGroupSuffix;
-#ifdef WITH_LDAP_SAMCONFIG
- int ldap_port;
- char *szLdapServer;
-#endif
int ldap_ssl;
char *szLdapSuffix;
char *szLdapAdminDn;
@@ -297,6 +289,7 @@ typedef struct {
BOOL bDebugHiresTimestamp;
BOOL bDebugPid;
BOOL bDebugUid;
+ BOOL bEnableCoreFiles;
BOOL bHostMSDfs;
BOOL bUseMmap;
BOOL bHostnameLookups;
@@ -309,6 +302,7 @@ typedef struct {
BOOL bEnablePrivileges;
BOOL bASUSupport;
BOOL bUsershareOwnerOnly;
+ BOOL bUsershareAllowGuests;
int restrict_anonymous;
int name_cache_timeout;
int client_signing;
@@ -455,6 +449,7 @@ typedef struct {
int iAioReadSize;
int iAioWriteSize;
int iMap_readonly;
+ int ichange_notify_timeout;
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
@@ -593,6 +588,7 @@ static service sDefault = {
0, /* iAioReadSize */
0, /* iAioWriteSize */
MAP_READONLY_YES, /* iMap_readonly */
+ 60, /* ichange_notify_timeout = 1 minute default. */
NULL, /* Parametric options */
@@ -671,12 +667,6 @@ static const struct enum_list enum_printing[] = {
};
static const struct enum_list enum_ldap_ssl[] = {
-#ifdef WITH_LDAP_SAMCONFIG
- {LDAP_SSL_ON, "Yes"},
- {LDAP_SSL_ON, "yes"},
- {LDAP_SSL_ON, "on"},
- {LDAP_SSL_ON, "On"},
-#endif
{LDAP_SSL_OFF, "no"},
{LDAP_SSL_OFF, "No"},
{LDAP_SSL_OFF, "off"},
@@ -863,7 +853,6 @@ static struct parm_struct parm_table[] = {
{"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED},
{"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED},
{"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED},
- {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED},
{"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED},
{"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED},
{"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED},
@@ -959,6 +948,7 @@ static struct parm_struct parm_table[] = {
{"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED},
{"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED},
{"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED},
+ {"enable core files", P_BOOL, P_GLOBAL, &Globals.bEnableCoreFiles, NULL, NULL, FLAG_ADVANCED},
{N_("Protocol Options"), P_SEP, P_SEPARATOR},
@@ -1009,7 +999,7 @@ static struct parm_struct parm_table[] = {
{N_("Tuning Options"), P_SEP, P_SEPARATOR},
{"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
- {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL, NULL, FLAG_ADVANCED},
+ {"change notify timeout", P_INTEGER, P_LOCAL, &sDefault.ichange_notify_timeout, NULL, NULL, FLAG_ADVANCED},
{"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED},
{"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED},
{"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED},
@@ -1150,7 +1140,6 @@ static struct parm_struct parm_table[] = {
{"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD},
{"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD},
{"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED},
- {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD},
{N_("Locking Options"), P_SEP, P_SEPARATOR},
@@ -1172,10 +1161,6 @@ static struct parm_struct parm_table[] = {
{N_("Ldap Options"), P_SEP, P_SEPARATOR},
-#ifdef WITH_LDAP_SAMCONFIG
- {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, FLAG_ADVANCED},
- {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, FLAG_ADVANCED},
-#endif
{"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED},
{"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED},
{"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED},
@@ -1239,6 +1224,7 @@ 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 allow guests", P_BOOL, P_GLOBAL, &Globals.bUsershareAllowGuests, NULL, NULL, FLAG_ADVANCED},
{"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},
@@ -1520,11 +1506,11 @@ static void init_globals(BOOL first_time_only)
Globals.bDebugHiresTimestamp = False;
Globals.bDebugPid = False;
Globals.bDebugUid = False;
+ Globals.bEnableCoreFiles = True;
Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
- Globals.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 */
@@ -1573,13 +1559,7 @@ static void init_globals(BOOL first_time_only)
a large number of sites (tridge) */
Globals.bHostnameLookups = False;
-#ifdef WITH_LDAP_SAMCONFIG
- string_set(&Globals.szLdapServer, "localhost");
- Globals.ldap_port = 636;
- string_set(&Globals.szPassdbBackend, "ldapsam_compat");
-#else
string_set(&Globals.szPassdbBackend, "smbpasswd");
-#endif /* WITH_LDAP_SAMCONFIG */
string_set(&Globals.szLdapSuffix, "");
string_set(&Globals.szLdapMachineSuffix, "");
string_set(&Globals.szLdapUserSuffix, "");
@@ -1645,7 +1625,7 @@ static void init_globals(BOOL first_time_only)
Globals.bWinbindRefreshTickets = False;
Globals.bWinbindOfflineLogon = False;
- Globals.bPassdbExpandExplicit = True;
+ Globals.bPassdbExpandExplicit = False;
Globals.name_cache_timeout = 660; /* In seconds */
@@ -1670,6 +1650,8 @@ static void init_globals(BOOL first_time_only)
Globals.iUsershareMaxShares = 0;
/* By default disallow sharing of directories not owned by the sharer. */
Globals.bUsershareOwnerOnly = True;
+ /* By default disallow guest access to usershares. */
+ Globals.bUsershareAllowGuests = False;
}
static TALLOC_CTX *lp_talloc;
@@ -1792,7 +1774,6 @@ FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
-FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
@@ -1838,7 +1819,6 @@ FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
-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)
@@ -1854,10 +1834,6 @@ FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
-#ifdef WITH_LDAP_SAMCONFIG
-FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
-FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
-#endif
FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
@@ -1875,6 +1851,7 @@ FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList
FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
+FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
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)
@@ -1901,6 +1878,7 @@ FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
+FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
@@ -1960,7 +1938,6 @@ static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
-FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
FN_GLOBAL_INTEGER(lp_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)
@@ -2092,6 +2069,7 @@ FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
+FN_LOCAL_INTEGER(lp_change_notify_timeout, ichange_notify_timeout)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
@@ -4318,29 +4296,40 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
int numlines,
pstring sharepath,
pstring comment,
- SEC_DESC **ppsd)
+ SEC_DESC **ppsd,
+ BOOL *pallow_guest)
{
const char **prefixallowlist = lp_usershare_prefix_allow_list();
const char **prefixdenylist = lp_usershare_prefix_deny_list();
+ int us_vers;
SMB_STRUCT_DIR *dp;
SMB_STRUCT_STAT sbuf;
+ *pallow_guest = False;
+
if (numlines < 4) {
return USERSHARE_MALFORMED_FILE;
}
- if (!strequal(lines[0], "#VERSION 1")) {
+ if (strcmp(lines[0], "#VERSION 1") == 0) {
+ us_vers = 1;
+ } else if (strcmp(lines[0], "#VERSION 2") == 0) {
+ us_vers = 2;
+ if (numlines < 5) {
+ return USERSHARE_MALFORMED_FILE;
+ }
+ } else {
return USERSHARE_BAD_VERSION;
}
- if (!strnequal(lines[1], "path=", 5)) {
+ if (strncmp(lines[1], "path=", 5) != 0) {
return USERSHARE_MALFORMED_PATH;
}
pstrcpy(sharepath, &lines[1][5]);
trim_string(sharepath, " ", " ");
- if (!strnequal(lines[2], "comment=", 8)) {
+ if (strncmp(lines[2], "comment=", 8) != 0) {
return USERSHARE_MALFORMED_COMMENT_DEF;
}
@@ -4348,7 +4337,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
trim_string(comment, " ", " ");
trim_char(comment, '"', '"');
- if (!strnequal(lines[3], "usershare_acl=", 14)) {
+ if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
return USERSHARE_MALFORMED_ACL_DEF;
}
@@ -4356,7 +4345,16 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
return USERSHARE_ACL_ERR;
}
- if (snum != -1 && strequal(sharepath, ServicePtrs[snum]->szPath)) {
+ if (us_vers == 2) {
+ if (strncmp(lines[4], "guest_ok=", 9) != 0) {
+ return USERSHARE_MALFORMED_ACL_DEF;
+ }
+ if (lines[4][9] == 'y') {
+ *pallow_guest = True;
+ }
+ }
+
+ if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
/* Path didn't change, no checks needed. */
return USERSHARE_OK;
}
@@ -4468,6 +4466,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
int iService = -1;
TALLOC_CTX *ctx = NULL;
SEC_DESC *psd = NULL;
+ BOOL guest_ok = False;
/* Ensure share name doesn't contain invalid characters. */
if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
@@ -4561,7 +4560,9 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
return 1;
}
- if (parse_usershare_file(ctx, &sbuf, service_name, iService, lines, numlines, sharepath, comment, &psd) != USERSHARE_OK) {
+ if (parse_usershare_file(ctx, &sbuf, service_name,
+ iService, lines, numlines, sharepath,
+ comment, &psd, &guest_ok) != USERSHARE_OK) {
talloc_destroy(ctx);
SAFE_FREE(lines);
return -1;
@@ -4605,6 +4606,11 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
/* Set the service as a valid usershare. */
ServicePtrs[iService]->usershare = USERSHARE_VALID;
+ /* Set guest access. */
+ if (lp_usershare_allow_guests()) {
+ ServicePtrs[iService]->bGuest_ok = guest_ok;
+ }
+
/* And note when it was loaded. */
ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
string_set(&ServicePtrs[iService]->szPath, sharepath);
diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c
index 942d2771782..751fa597c04 100644
--- a/source/passdb/lookup_sid.c
+++ b/source/passdb/lookup_sid.c
@@ -128,11 +128,30 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
* 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;
+ if (flags & LOOKUP_NAME_GROUP) {
+ struct group *grp;
+
+ /* If we are using the smbpasswd backend, we need to use the
+ * algorithmic mapping for the unix group we find. This is
+ * necessary because when creating the NT token from the unix
+ * gid list we got from initgroups() we use gid_to_sid() that
+ * uses algorithmic mapping if pdb_rid_algorithm() is true. */
+
+ if (pdb_rid_algorithm() && ((grp = getgrnam(name)) != NULL) &&
+ (grp->gr_gid < max_algorithmic_gid())) {
+ domain = talloc_strdup(tmp_ctx, get_global_sam_name());
+ sid_compose(&sid, get_global_sam_sid(),
+ pdb_gid_to_group_rid(grp->gr_gid));
+ type = SID_NAME_DOM_GRP;
+ 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;
+ }
}
/* Now the guesswork begins, we haven't been given an explicit
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 876f04bdfe7..60f360bde9b 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -136,6 +136,7 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p
{
const char *guest_account = lp_guestaccount();
const char *domain = global_myname();
+ DOM_SID group_sid;
uint32 urid;
if ( !pwd ) {
@@ -147,6 +148,8 @@ static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *p
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);
+ gid_to_sid(&group_sid, pwd->pw_gid);
+ pdb_set_group_sid(user, &group_sid, PDB_SET);
/* save the password structure for later use */
diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c
index 5cb72e7f863..0b93c42a416 100644
--- a/source/passdb/pdb_get_set.c
+++ b/source/passdb/pdb_get_set.c
@@ -3,7 +3,7 @@
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
+ Copyright (C) Gerald (Jerry) Carter 2000-2006
Copyright (C) Andrew Bartlett 2001-2002
Copyright (C) Stefan (metze) Metzmacher 2002
@@ -1016,12 +1016,13 @@ BOOL pdb_set_lanman_passwd (struct samu *sampass, const uint8 pwd[LM_HASH_LEN],
data_blob_clear_free(&sampass->lm_pw);
- if (pwd) {
- sampass->lm_pw =
- data_blob_talloc(sampass, pwd, LM_HASH_LEN);
- } else {
- sampass->lm_pw = data_blob(NULL, 0);
- }
+ /* on keep the password if we are allowing LANMAN authentication */
+
+ if (pwd && lp_lanman_auth() ) {
+ sampass->lm_pw = data_blob_talloc(sampass, pwd, LM_HASH_LEN);
+ } else {
+ sampass->lm_pw = data_blob(NULL, 0);
+ }
return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag);
}
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index b3522e33a7f..393b60516cc 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -30,6 +30,8 @@
static struct samu *csamuser = NULL;
+static_decl_pdb;
+
static struct pdb_init_function_entry *backends = NULL;
static void lazy_initialize_passdb(void)
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 1e3a5fdb6f0..70d9e6024c8 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -212,7 +212,7 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_
return ntstatus;
}
- if (!smbldap_has_naming_context(ldap_state->smbldap_state, lp_ldap_suffix())) {
+ if (!smbldap_has_naming_context(ldap_state->smbldap_state->ldap_struct, lp_ldap_suffix())) {
DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
"as top-level namingContext\n", lp_ldap_suffix()));
return ntstatus;
@@ -773,9 +773,9 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
if (pwHistLen > 0){
uint8 *pwhist = NULL;
int i;
+ char history_string[MAX_PW_HISTORY_LEN*64];
- /* We can only store (sizeof(pstring)-1)/64 password history entries. */
- pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/64));
+ pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
@@ -783,19 +783,20 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
}
memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
- if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), temp)) {
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY),
+ history_string, sizeof(history_string))) {
/* leave as default - zeros */
} else {
BOOL hex_failed = False;
for (i = 0; i < pwHistLen; i++){
/* Get the 16 byte salt. */
- if (!pdb_gethexpwd(&temp[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
+ if (!pdb_gethexpwd(&history_string[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
hex_failed = True;
break;
}
/* Get the 16 byte MD5 hash of salt+passwd. */
- if (!pdb_gethexpwd(&temp[(i*64)+32],
+ if (!pdb_gethexpwd(&history_string[(i*64)+32],
&pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN])) {
hex_failed = True;
break;
@@ -1505,11 +1506,6 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu
return NT_STATUS_OK;
}
-static BOOL ldapsam_can_pwchange_exop(struct smbldap_state *ldap_state)
-{
- return smbldap_has_extension(ldap_state, LDAP_EXOP_MODIFY_PASSWD);
-}
-
/********************************************************************
Do the actual modification - also change a plaintext passord if
it it set.
@@ -1572,7 +1568,9 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
char *utf8_dn;
if (!ldap_state->is_nds_ldap) {
- if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
+
+ if (!smbldap_has_extension(ldap_state->smbldap_state->ldap_struct,
+ LDAP_EXOP_MODIFY_PASSWD)) {
DEBUG(2, ("ldap password change requested, but LDAP "
"server does not support it -- ignoring\n"));
return NT_STATUS_OK;
@@ -4303,7 +4301,7 @@ 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)(sambaSID=%s))",
+ "(sambaGroupType=%d)(sambaSID=%s*))",
type, sid_string_static(sid));
state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
"displayName", "description",
@@ -4356,6 +4354,7 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
char *value;
int rc;
uint32 nextRid = 0;
+ const char *dn;
TALLOC_CTX *mem_ctx;
@@ -4419,9 +4418,12 @@ static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
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);
+ if ((dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)) == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ rc = smbldap_modify(smbldap_state, dn, mods);
/* ACCESS_DENIED is used as a placeholder for "the modify failed,
* please retry" */
@@ -5427,23 +5429,6 @@ NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *lo
struct ldapsam_privates *ldap_state;
char *uri = talloc_strdup( NULL, location );
-#ifdef WITH_LDAP_SAMCONFIG
- if (!uri) {
- int ldap_port = lp_ldap_port();
-
- /* remap default port if not using SSL (ie clear or TLS) */
- if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
- ldap_port = 389;
- }
-
- 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_method, uri ))) {
return nt_status;
}
diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c
index a82f4e48d4e..08ad96efa4b 100644
--- a/source/passdb/pdb_nds.c
+++ b/source/passdb/pdb_nds.c
@@ -817,9 +817,9 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
/* Attempt simple bind with real or bogus password */
rc = ldap_simple_bind_s(ld, dn, clear_text_pw);
+ ldap_unbind(ld);
if (rc == LDAP_SUCCESS) {
DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Successful for %s\n", username));
- 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));
diff --git a/source/popt/CHANGES b/source/popt/CHANGES
index b6ab2aa3088..db16a5fdd00 100644
--- a/source/popt/CHANGES
+++ b/source/popt/CHANGES
@@ -1,4 +1,7 @@
-1.3 ->
+1.5 -> 1.6
+ - add ability to perform callbacks for every, not just first, match.
+
+1.3 -> 1.5
- heavy dose of const's
- poptParseArgvString() now NULL terminates the list
diff --git a/source/popt/README b/source/popt/README
index 7fccc836ffa..0b5205bfdd7 100644
--- a/source/popt/README
+++ b/source/popt/README
@@ -5,7 +5,7 @@ to getopt(3), it contains a number of enhancements, including:
2) popt can parse arbitrary argv[] style arrays while
getopt(2) makes this quite difficult
3) popt allows users to alias command line arguments
- 4) popt provides convience functions for parsting strings
+ 4) popt provides convience functions for parsing strings
into argv[] style arrays
popt is used by rpm, the Red Hat install program, and many other Red Hat
diff --git a/source/popt/findme.c b/source/popt/findme.c
index f2ad05bb3fb..a950e50018b 100644
--- a/source/popt/findme.c
+++ b/source/popt/findme.c
@@ -1,6 +1,10 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/findme.c
+ */
+
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "findme.h"
@@ -9,38 +13,38 @@ const char * findProgramPath(const char * argv0) {
char * path = getenv("PATH");
char * pathbuf;
char * start, * chptr;
- char * buf, *local = NULL;
+ char * buf;
- /* If there is a / in the argv[0], it has to be an absolute
- path */
+ if (argv0 == NULL) return NULL; /* XXX can't happen */
+ /* If there is a / in the argv[0], it has to be an absolute path */
if (strchr(argv0, '/'))
return xstrdup(argv0);
- if (!path) return NULL;
+ if (path == NULL) return NULL;
- local = start = pathbuf = malloc(strlen(path) + 1);
- buf = malloc(strlen(path) + strlen(argv0) + 2);
+ start = pathbuf = alloca(strlen(path) + 1);
+ buf = malloc(strlen(path) + strlen(argv0) + sizeof("/"));
+ if (buf == NULL) return NULL; /* XXX can't happen */
strcpy(pathbuf, path);
chptr = NULL;
+ /*@-branchstate@*/
do {
if ((chptr = strchr(start, ':')))
*chptr = '\0';
sprintf(buf, "%s/%s", start, argv0);
- if (!access(buf, X_OK)) {
- if (local) free(local);
- return buf;
- }
+ if (!access(buf, X_OK))
+ return buf;
if (chptr)
start = chptr + 1;
else
start = NULL;
} while (start && *start);
+ /*@=branchstate@*/
free(buf);
- if (local) free(local);
return NULL;
}
diff --git a/source/popt/findme.h b/source/popt/findme.h
index 5e93963d603..a016b867ea2 100644
--- a/source/popt/findme.h
+++ b/source/popt/findme.h
@@ -1,10 +1,20 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/findme.h
+ */
+
+/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_FINDME
#define H_FINDME
-const char * findProgramPath(const char * argv0);
+/**
+ * Return absolute path to executable by searching PATH.
+ * @param argv0 name of executable
+ * @return (malloc'd) absolute path to executable (or NULL)
+ */
+/*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0)
+ /*@*/;
#endif
diff --git a/source/popt/popt.c b/source/popt/popt.c
index 9fa8650312c..e9c4c17de50 100644
--- a/source/popt/popt.c
+++ b/source/popt/popt.c
@@ -1,11 +1,28 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/popt.c
+ */
+
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist */
+
+#undef MYDEBUG
#include "system.h"
+
+#if HAVE_FLOAT_H
+#include <float.h>
+#endif
+#include <math.h>
+
#include "findme.h"
#include "poptint.h"
+#ifdef MYDEBUG
+/*@unchecked@*/
+int _popt_debug = 0;
+#endif
+
#ifndef HAVE_STRERROR
static char * strerror(int errno) {
extern int sys_nerr;
@@ -18,47 +35,143 @@ static char * strerror(int errno) {
}
#endif
-void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) {
- if (con->execPath) xfree(con->execPath);
+#ifdef MYDEBUG
+/*@unused@*/ static void prtcon(const char *msg, poptContext con)
+{
+ if (msg) fprintf(stderr, "%s", msg);
+ fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
+ con, con->os,
+ (con->os->nextCharArg ? con->os->nextCharArg : ""),
+ (con->os->nextArg ? con->os->nextArg : ""),
+ con->os->next,
+ (con->os->argv && con->os->argv[con->os->next]
+ ? con->os->argv[con->os->next] : ""));
+}
+#endif
+
+void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
+{
+ con->execPath = _free(con->execPath);
con->execPath = xstrdup(path);
con->execAbsolute = allowAbsolute;
+ /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */
+ return;
+ /*@=nullstate@*/
+}
+
+static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
+ /*@globals internalState@*/
+ /*@modifies internalState@*/
+{
+ if (opt != NULL)
+ for (; opt->longName || opt->shortName || opt->arg; opt++) {
+ if (opt->arg == NULL) continue; /* XXX program error. */
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ /* Recurse on included sub-tables. */
+ invokeCallbacksPRE(con, opt->arg);
+ } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
+ (opt->argInfo & POPT_CBFLAG_PRE))
+ { /*@-castfcnptr@*/
+ poptCallbackType cb = (poptCallbackType)opt->arg;
+ /*@=castfcnptr@*/
+ /* Perform callback. */
+ /*@-moduncon -noeffectuncon @*/
+ cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
+ /*@=moduncon =noeffectuncon @*/
+ }
+ }
}
-static void invokeCallbacks(poptContext con, const struct poptOption * table,
- int post) {
- const struct poptOption * opt = table;
- poptCallbackType cb;
+static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
+ /*@globals internalState@*/
+ /*@modifies internalState@*/
+{
+ if (opt != NULL)
+ for (; opt->longName || opt->shortName || opt->arg; opt++) {
+ if (opt->arg == NULL) continue; /* XXX program error. */
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ /* Recurse on included sub-tables. */
+ invokeCallbacksPOST(con, opt->arg);
+ } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
+ (opt->argInfo & POPT_CBFLAG_POST))
+ { /*@-castfcnptr@*/
+ poptCallbackType cb = (poptCallbackType)opt->arg;
+ /*@=castfcnptr@*/
+ /* Perform callback. */
+ /*@-moduncon -noeffectuncon @*/
+ cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
+ /*@=moduncon =noeffectuncon @*/
+ }
+ }
+}
- while (opt->longName || opt->shortName || opt->arg) {
+static void invokeCallbacksOPTION(poptContext con,
+ const struct poptOption * opt,
+ const struct poptOption * myOpt,
+ /*@null@*/ const void * myData, int shorty)
+ /*@globals internalState@*/
+ /*@modifies internalState@*/
+{
+ const struct poptOption * cbopt = NULL;
+
+ if (opt != NULL)
+ for (; opt->longName || opt->shortName || opt->arg; opt++) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
- invokeCallbacks(con, opt->arg, post);
- } else if (((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) &&
- ((!post && (opt->argInfo & POPT_CBFLAG_PRE)) ||
- ( post && (opt->argInfo & POPT_CBFLAG_POST)))) {
- cb = (poptCallbackType)opt->arg;
- cb(con, post ? POPT_CALLBACK_REASON_POST : POPT_CALLBACK_REASON_PRE,
- NULL, NULL, opt->descrip);
+ /* Recurse on included sub-tables. */
+ if (opt->arg != NULL) /* XXX program error */
+ invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
+ } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
+ !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) {
+ /* Save callback info. */
+ cbopt = opt;
+ } else if (cbopt != NULL &&
+ ((myOpt->shortName && opt->shortName && shorty &&
+ myOpt->shortName == opt->shortName) ||
+ (myOpt->longName && opt->longName &&
+ /*@-nullpass@*/ /* LCL: opt->longName != NULL */
+ !strcmp(myOpt->longName, opt->longName)))
+ /*@=nullpass@*/
+ )
+ { /*@-castfcnptr@*/
+ poptCallbackType cb = (poptCallbackType)cbopt->arg;
+ /*@=castfcnptr@*/
+ const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
+ /* Perform callback. */
+ if (cb != NULL) { /* XXX program error */
+ /*@-moduncon -noeffectuncon @*/
+ cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
+ con->os->nextArg, cbData);
+ /*@=moduncon =noeffectuncon @*/
+ }
+ /* Terminate (unless explcitly continuing). */
+ if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
+ return;
}
- opt++;
}
}
poptContext poptGetContext(const char * name, int argc, const char ** argv,
- const struct poptOption * options, int flags) {
+ const struct poptOption * options, int flags)
+{
poptContext con = malloc(sizeof(*con));
+ if (con == NULL) return NULL; /* XXX can't happen */
memset(con, 0, sizeof(*con));
con->os = con->optionStack;
con->os->argc = argc;
+ /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
con->os->argv = argv;
+ /*@=dependenttrans =assignexpose@*/
con->os->argb = NULL;
if (!(flags & POPT_CONTEXT_KEEP_FIRST))
con->os->next = 1; /* skip argv[0] */
- con->leftovers = calloc( (argc + 1), sizeof(char *) );
+ con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) );
+ /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */
con->options = options;
+ /*@=dependenttrans =assignexpose@*/
con->aliases = NULL;
con->numAliases = 0;
con->flags = flags;
@@ -72,40 +185,38 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
con->flags |= POPT_CONTEXT_POSIXMEHARDER;
- if (name)
- con->appName = strcpy(malloc(strlen(name) + 1), name);
+ if (name) {
+ char * t = malloc(strlen(name) + 1);
+ if (t) con->appName = strcpy(t, name);
+ }
- invokeCallbacks(con, con->options, 0);
+ /*@-internalglobs@*/
+ invokeCallbacksPRE(con, con->options);
+ /*@=internalglobs@*/
return con;
}
-static void cleanOSE(struct optionStackEntry *os)
+static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
+ /*@uses os @*/
+ /*@releases os->nextArg, os->argv, os->argb @*/
+ /*@modifies os @*/
{
- if (os->nextArg) {
- xfree(os->nextArg);
- os->nextArg = NULL;
- }
- if (os->argv) {
- xfree(os->argv);
- os->argv = NULL;
- }
- if (os->argb) {
- PBM_FREE(os->argb);
- os->argb = NULL;
- }
+ os->nextArg = _free(os->nextArg);
+ os->argv = _free(os->argv);
+ os->argb = PBM_FREE(os->argb);
}
-void poptResetContext(poptContext con) {
+/*@-boundswrite@*/
+void poptResetContext(poptContext con)
+{
int i;
+ if (con == NULL) return;
while (con->os > con->optionStack) {
cleanOSE(con->os--);
}
- if (con->os->argb) {
- PBM_FREE(con->os->argb);
- con->os->argb = NULL;
- }
+ con->os->argb = PBM_FREE(con->os->argb);
con->os->currAlias = NULL;
con->os->nextCharArg = NULL;
con->os->nextArg = NULL;
@@ -116,36 +227,47 @@ void poptResetContext(poptContext con) {
con->restLeftover = 0;
con->doExec = NULL;
+ if (con->finalArgv != NULL)
for (i = 0; i < con->finalArgvCount; i++) {
- if (con->finalArgv[i]) {
- xfree(con->finalArgv[i]);
- con->finalArgv[i] = NULL;
- }
+ /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */
+ con->finalArgv[i] = _free(con->finalArgv[i]);
+ /*@=unqualifiedtrans@*/
}
con->finalArgvCount = 0;
-
- if (con->arg_strip) {
- PBM_FREE(con->arg_strip);
- con->arg_strip = NULL;
- }
+ con->arg_strip = PBM_FREE(con->arg_strip);
+ /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */
+ return;
+ /*@=nullstate@*/
}
-
-/* Only one of longName, shortName may be set at a time */
-static int handleExec(poptContext con, char * longName, char shortName) {
+/*@=boundswrite@*/
+
+/* Only one of longName, shortName should be set, not both. */
+/*@-boundswrite@*/
+static int handleExec(/*@special@*/ poptContext con,
+ /*@null@*/ const char * longName, char shortName)
+ /*@uses con->execs, con->numExecs, con->flags, con->doExec,
+ con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
+ /*@modifies con @*/
+{
+ poptItem item;
int i;
- i = con->numExecs - 1;
- if (longName) {
- while (i >= 0 && (!con->execs[i].longName ||
- strcmp(con->execs[i].longName, longName))) i--;
- } else {
- while (i >= 0 &&
- con->execs[i].shortName != shortName) i--;
- }
+ if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */
+ return 0;
+ for (i = con->numExecs - 1; i >= 0; i--) {
+ item = con->execs + i;
+ if (longName && !(item->option.longName &&
+ !strcmp(longName, item->option.longName)))
+ continue;
+ else if (shortName != item->option.shortName)
+ continue;
+ break;
+ }
if (i < 0) return 0;
+
if (con->flags & POPT_CONTEXT_NO_EXEC)
return 1;
@@ -163,45 +285,65 @@ static int handleExec(poptContext con, char * longName, char shortName) {
}
i = con->finalArgvCount++;
+ if (con->finalArgv != NULL) /* XXX can't happen */
{ char *s = malloc((longName ? strlen(longName) : 0) + 3);
- if (longName)
- sprintf(s, "--%s", longName);
- else
- sprintf(s, "-%c", shortName);
- con->finalArgv[i] = s;
+ if (s != NULL) { /* XXX can't happen */
+ if (longName)
+ sprintf(s, "--%s", longName);
+ else
+ sprintf(s, "-%c", shortName);
+ con->finalArgv[i] = s;
+ } else
+ con->finalArgv[i] = NULL;
}
+ /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */
return 1;
+ /*@=nullstate@*/
}
+/*@=boundswrite@*/
/* Only one of longName, shortName may be set at a time */
-static int handleAlias(poptContext con, const char * longName, char shortName,
- /*@keep@*/ const char * nextCharArg) {
+static int handleAlias(/*@special@*/ poptContext con,
+ /*@null@*/ const char * longName, char shortName,
+ /*@exposed@*/ /*@null@*/ const char * nextCharArg)
+ /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
+ con->os->currAlias, con->os->currAlias->option.longName @*/
+ /*@modifies con @*/
+{
+ poptItem item = con->os->currAlias;
+ int rc;
int i;
- if (con->os->currAlias && con->os->currAlias->longName && longName &&
- !strcmp(con->os->currAlias->longName, longName))
- return 0;
- if (con->os->currAlias && shortName &&
- shortName == con->os->currAlias->shortName)
+ if (item) {
+ if (longName && (item->option.longName &&
+ !strcmp(longName, item->option.longName)))
+ return 0;
+ if (shortName && shortName == item->option.shortName)
+ return 0;
+ }
+
+ if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */
return 0;
- i = con->numAliases - 1;
- if (longName) {
- while (i >= 0 && (!con->aliases[i].longName ||
- strcmp(con->aliases[i].longName, longName))) i--;
- } else {
- while (i >= 0 &&
- con->aliases[i].shortName != shortName) i--;
+ for (i = con->numAliases - 1; i >= 0; i--) {
+ item = con->aliases + i;
+ if (longName && !(item->option.longName &&
+ !strcmp(longName, item->option.longName)))
+ continue;
+ else if (shortName != item->option.shortName)
+ continue;
+ break;
}
-
if (i < 0) return 0;
if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
+/*@-boundsread@*/
if (nextCharArg && *nextCharArg)
con->os->nextCharArg = nextCharArg;
+/*@=boundsread@*/
con->os++;
con->os->next = 0;
@@ -209,49 +351,67 @@ static int handleAlias(poptContext con, const char * longName, char shortName,
con->os->nextArg = NULL;
con->os->nextCharArg = NULL;
con->os->currAlias = con->aliases + i;
- poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
+ rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
&con->os->argc, &con->os->argv);
con->os->argb = NULL;
- return 1;
+ return (rc ? rc : 1);
}
-static void execCommand(poptContext con) {
+/*@-bounds -boundswrite @*/
+static int execCommand(poptContext con)
+ /*@globals internalState @*/
+ /*@modifies internalState @*/
+{
+ poptItem item = con->doExec;
const char ** argv;
- int pos = 0;
- const char * script = con->doExec->script;
+ int argc = 0;
+ int rc;
- argv = malloc(sizeof(*argv) *
- (6 + con->numLeftovers + con->finalArgvCount));
+ if (item == NULL) /*XXX can't happen*/
+ return POPT_ERROR_NOARG;
+
+ if (item->argv == NULL || item->argc < 1 ||
+ (!con->execAbsolute && strchr(item->argv[0], '/')))
+ return POPT_ERROR_NOARG;
- if (!con->execAbsolute && strchr(script, '/')) return;
+ argv = malloc(sizeof(*argv) *
+ (6 + item->argc + con->numLeftovers + con->finalArgvCount));
+ if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */
- if (!strchr(script, '/') && con->execPath) {
- char *s = malloc(strlen(con->execPath) + strlen(script) + 2);
- sprintf(s, "%s/%s", con->execPath, script);
- argv[pos] = s;
+ if (!strchr(item->argv[0], '/') && con->execPath) {
+ char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/"));
+ sprintf(s, "%s/%s", con->execPath, item->argv[0]);
+ argv[argc] = s;
} else {
- argv[pos] = script;
+ argv[argc] = findProgramPath(item->argv[0]);
}
- pos++;
+ if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
- argv[pos] = findProgramPath(con->os->argv[0]);
- if (argv[pos]) pos++;
- argv[pos++] = ";";
+ if (item->argc > 1) {
+ memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
+ argc += (item->argc - 1);
+ }
- memcpy(argv + pos, con->finalArgv, sizeof(*argv) * con->finalArgvCount);
- pos += con->finalArgvCount;
+ if (con->finalArgv != NULL && con->finalArgvCount > 0) {
+ memcpy(argv + argc, con->finalArgv,
+ sizeof(*argv) * con->finalArgvCount);
+ argc += con->finalArgvCount;
+ }
- if (con->numLeftovers) {
- argv[pos++] = "--";
- memcpy(argv + pos, con->leftovers, sizeof(*argv) * con->numLeftovers);
- pos += con->numLeftovers;
+ if (con->leftovers != NULL && con->numLeftovers > 0) {
+#if 0
+ argv[argc++] = "--";
+#endif
+ memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
+ argc += con->numLeftovers;
}
- argv[pos++] = NULL;
+ argv[argc] = NULL;
#ifdef __hpux
- setresuid(getuid(), getuid(),-1);
+ rc = setresuid(getuid(), getuid(),-1);
+ if (rc) return POPT_ERROR_ERRNO;
#else
/*
* XXX " ... on BSD systems setuid() should be preferred over setreuid()"
@@ -259,65 +419,109 @@ static void execCommand(poptContext con) {
* XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
*/
#if defined(HAVE_SETUID)
- setuid(getuid());
+ rc = setuid(getuid());
+ if (rc) return POPT_ERROR_ERRNO;
#elif defined (HAVE_SETREUID)
- setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
+ rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */
+ if (rc) return POPT_ERROR_ERRNO;
#else
; /* Can't drop privileges */
#endif
#endif
- execvp(argv[0], (char *const *)argv);
-}
+ if (argv[0] == NULL)
+ return POPT_ERROR_NOARG;
-/*@observer@*/ static const struct poptOption *
-findOption(const struct poptOption * table, const char * longName,
- char shortName,
- /*@out@*/ poptCallbackType * callback, /*@out@*/ const void ** callbackData,
- int singleDash)
+#ifdef MYDEBUG
+if (_popt_debug)
+ { const char ** avp;
+ fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
+ for (avp = argv; *avp; avp++)
+ fprintf(stderr, " '%s'", *avp);
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ rc = execvp(argv[0], (char *const *)argv);
+
+ return POPT_ERROR_ERRNO;
+}
+/*@=bounds =boundswrite @*/
+
+/*@-boundswrite@*/
+/*@observer@*/ /*@null@*/ static const struct poptOption *
+findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
+ char shortName,
+ /*@null@*/ /*@out@*/ poptCallbackType * callback,
+ /*@null@*/ /*@out@*/ const void ** callbackData,
+ int singleDash)
+ /*@modifies *callback, *callbackData */
{
- const struct poptOption * opt = table;
- const struct poptOption * opt2;
const struct poptOption * cb = NULL;
/* This happens when a single - is given */
- if (singleDash && !shortName && !*longName)
+ if (singleDash && !shortName && (longName && *longName == '\0'))
shortName = '-';
- while (opt->longName || opt->shortName || opt->arg) {
+ for (; opt->longName || opt->shortName || opt->arg; opt++) {
+
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ const struct poptOption * opt2;
+
+ /* Recurse on included sub-tables. */
+ if (opt->arg == NULL) continue; /* XXX program error */
opt2 = findOption(opt->arg, longName, shortName, callback,
callbackData, singleDash);
- if (opt2) {
- if (*callback && !*callbackData)
- *callbackData = opt->descrip;
- return opt2;
- }
+ if (opt2 == NULL) continue;
+ /* Sub-table data will be inheirited if no data yet. */
+ if (!(callback && *callback)) return opt2;
+ if (!(callbackData && *callbackData == NULL)) return opt2;
+ /*@-observertrans -dependenttrans @*/
+ *callbackData = opt->descrip;
+ /*@=observertrans =dependenttrans @*/
+ return opt2;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
cb = opt;
} else if (longName && opt->longName &&
(!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
- !strcmp(longName, opt->longName)) {
+ /*@-nullpass@*/ /* LCL: opt->longName != NULL */
+ !strcmp(longName, opt->longName))
+ /*@=nullpass@*/
+ {
break;
} else if (shortName && shortName == opt->shortName) {
break;
}
- opt++;
}
- if (!opt->longName && !opt->shortName) return NULL;
- *callbackData = NULL;
- *callback = NULL;
+ if (!opt->longName && !opt->shortName)
+ return NULL;
+ /*@-modobserver -mods @*/
+ if (callback) *callback = NULL;
+ if (callbackData) *callbackData = NULL;
if (cb) {
- *callback = (poptCallbackType)cb->arg;
- if (!(cb->argInfo & POPT_CBFLAG_INC_DATA))
- *callbackData = cb->descrip;
+ if (callback)
+ /*@-castfcnptr@*/
+ *callback = (poptCallbackType)cb->arg;
+ /*@=castfcnptr@*/
+ if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) {
+ if (callbackData)
+ /*@-observertrans@*/ /* FIX: typedef double indirection. */
+ *callbackData = cb->descrip;
+ /*@=observertrans@*/
+ }
}
+ /*@=modobserver =mods @*/
return opt;
}
+/*@=boundswrite@*/
-static const char *findNextArg(poptContext con, unsigned argx, int delete)
+static const char * findNextArg(/*@special@*/ poptContext con,
+ unsigned argx, int delete_arg)
+ /*@uses con->optionStack, con->os,
+ con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
+ /*@modifies con @*/
{
struct optionStackEntry * os = con->os;
const char * arg;
@@ -327,43 +531,59 @@ static const char *findNextArg(poptContext con, unsigned argx, int delete)
arg = NULL;
while (os->next == os->argc && os > con->optionStack) os--;
if (os->next == os->argc && os == con->optionStack) break;
+ if (os->argv != NULL)
for (i = os->next; i < os->argc; i++) {
- if (os->argb && PBM_ISSET(i, os->argb)) continue;
- if (*os->argv[i] == '-') continue;
- if (--argx > 0) continue;
+ /*@-sizeoftype@*/
+ if (os->argb && PBM_ISSET(i, os->argb))
+ /*@innercontinue@*/ continue;
+ if (*os->argv[i] == '-')
+ /*@innercontinue@*/ continue;
+ if (--argx > 0)
+ /*@innercontinue@*/ continue;
arg = os->argv[i];
- if (delete) {
+ if (delete_arg) {
if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
+ if (os->argb != NULL) /* XXX can't happen */
PBM_SET(i, os->argb);
}
- break;
+ /*@innerbreak@*/ break;
+ /*@=sizeoftype@*/
}
if (os > con->optionStack) os--;
} while (arg == NULL);
return arg;
}
-static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
+/*@-boundswrite@*/
+static /*@only@*/ /*@null@*/ const char *
+expandNextArg(/*@special@*/ poptContext con, const char * s)
+ /*@uses con->optionStack, con->os,
+ con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
+ /*@modifies con @*/
{
- const char *a;
+ const char * a = NULL;
size_t alen;
char *t, *te;
size_t tn = strlen(s) + 1;
char c;
te = t = malloc(tn);;
+ if (t == NULL) return NULL; /* XXX can't happen */
while ((c = *s++) != '\0') {
switch (c) {
#if 0 /* XXX can't do this */
case '\\': /* escape */
c = *s++;
- break;
+ /*@switchbreak@*/ break;
#endif
case '!':
if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
- break;
- if ((a = findNextArg(con, 1, 1)) == NULL)
- break;
+ /*@switchbreak@*/ break;
+ /* XXX Make sure that findNextArg deletes only next arg. */
+ if (a == NULL) {
+ if ((a = findNextArg(con, 1, 1)) == NULL)
+ /*@switchbreak@*/ break;
+ }
s += 3;
alen = strlen(a);
@@ -373,53 +593,116 @@ static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
te = t + strlen(t);
strncpy(te, a, alen); te += alen;
continue;
- /*@notreached@*/ break;
+ /*@notreached@*/ /*@switchbreak@*/ break;
default:
- break;
+ /*@switchbreak@*/ break;
}
*te++ = c;
}
*te = '\0';
- t = realloc(t, strlen(t)+1); /* XXX memory leak, hard to plug */
+ t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */
return t;
}
+/*@=boundswrite@*/
-static void poptStripArg(poptContext con, int which)
+static void poptStripArg(/*@special@*/ poptContext con, int which)
+ /*@uses con->arg_strip, con->optionStack @*/
+ /*@defines con->arg_strip @*/
+ /*@modifies con @*/
{
- if(con->arg_strip == NULL) {
+ /*@-sizeoftype@*/
+ if (con->arg_strip == NULL)
con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
- }
+ if (con->arg_strip != NULL) /* XXX can't happen */
PBM_SET(which, con->arg_strip);
+ /*@=sizeoftype@*/
+ /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
+ return;
+ /*@=compdef@*/
+}
+
+int poptSaveLong(long * arg, int argInfo, long aLong)
+{
+ /* XXX Check alignment, may fail on funky platforms. */
+ if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
+ return POPT_ERROR_NULLARG;
+
+ if (argInfo & POPT_ARGFLAG_NOT)
+ aLong = ~aLong;
+ switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
+ case 0:
+ *arg = aLong;
+ break;
+ case POPT_ARGFLAG_OR:
+ *arg |= aLong;
+ break;
+ case POPT_ARGFLAG_AND:
+ *arg &= aLong;
+ break;
+ case POPT_ARGFLAG_XOR:
+ *arg ^= aLong;
+ break;
+ default:
+ return POPT_ERROR_BADOPERATION;
+ /*@notreached@*/ break;
+ }
+ return 0;
}
+int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
+{
+ /* XXX Check alignment, may fail on funky platforms. */
+ if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
+ return POPT_ERROR_NULLARG;
+
+ if (argInfo & POPT_ARGFLAG_NOT)
+ aLong = ~aLong;
+ switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
+ case 0:
+ *arg = aLong;
+ break;
+ case POPT_ARGFLAG_OR:
+ *arg |= aLong;
+ break;
+ case POPT_ARGFLAG_AND:
+ *arg &= aLong;
+ break;
+ case POPT_ARGFLAG_XOR:
+ *arg ^= aLong;
+ break;
+ default:
+ return POPT_ERROR_BADOPERATION;
+ /*@notreached@*/ break;
+ }
+ return 0;
+}
+
+/*@-boundswrite@*/
/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con)
{
const struct poptOption * opt = NULL;
int done = 0;
- /* looks a bit tricky to get rid of alloca properly in this fn */
-#if HAVE_ALLOCA_H
-#define ALLOCA(x) alloca(x)
-#else
-#define ALLOCA(x) malloc(x)
-#endif
-
-
+ if (con == NULL)
+ return -1;
while (!done) {
const char * origOptString = NULL;
poptCallbackType cb = NULL;
const void * cbData = NULL;
const char * longArg = NULL;
int canstrip = 0;
+ int shorty = 0;
while (!con->os->nextCharArg && con->os->next == con->os->argc
&& con->os > con->optionStack) {
cleanOSE(con->os--);
}
if (!con->os->nextCharArg && con->os->next == con->os->argc) {
- invokeCallbacks(con, con->options, 1);
- if (con->doExec) execCommand(con);
+ /*@-internalglobs@*/
+ invokeCallbacksPOST(con, con->options);
+ /*@=internalglobs@*/
+ if (con->doExec) return execCommand(con);
return -1;
}
@@ -428,26 +711,36 @@ int poptGetNextOpt(poptContext con)
char * localOptString, * optString;
int thisopt;
+ /*@-sizeoftype@*/
if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
con->os->next++;
continue;
}
- thisopt=con->os->next;
+ /*@=sizeoftype@*/
+ thisopt = con->os->next;
+ if (con->os->argv != NULL) /* XXX can't happen */
origOptString = con->os->argv[con->os->next++];
+ if (origOptString == NULL) /* XXX can't happen */
+ return POPT_ERROR_BADOPT;
+
if (con->restLeftover || *origOptString != '-') {
- con->leftovers[con->numLeftovers++] = origOptString;
if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
con->restLeftover = 1;
+ if (con->flags & POPT_CONTEXT_ARG_OPTS) {
+ con->os->nextArg = xstrdup(origOptString);
+ return 0;
+ }
+ if (con->leftovers != NULL) /* XXX can't happen */
+ con->leftovers[con->numLeftovers++] = origOptString;
continue;
}
/* Make a copy we can hack at */
localOptString = optString =
- strcpy(ALLOCA(strlen(origOptString) + 1),
- origOptString);
+ strcpy(alloca(strlen(origOptString) + 1), origOptString);
- if (!optString[0])
+ if (optString[0] == '\0')
return POPT_ERROR_BADOPT;
if (optString[1] == '-' && !optString[2]) {
@@ -466,12 +759,13 @@ int poptGetNextOpt(poptContext con)
/* XXX aliases with arg substitution need "--alias=arg" */
if (handleAlias(con, optString, '\0', NULL))
continue;
+
if (handleExec(con, optString, '\0'))
continue;
/* Check for "--long=arg" option. */
for (oe = optString; *oe && *oe != '='; oe++)
- ;
+ {};
if (*oe == '=') {
*oe++ = '\0';
/* XXX longArg is mapped back to persistent storage. */
@@ -487,110 +781,175 @@ int poptGetNextOpt(poptContext con)
if (!opt) {
con->os->nextCharArg = origOptString + 1;
} else {
- if(con->os == con->optionStack &&
- opt->argInfo & POPT_ARGFLAG_STRIP) {
+ if (con->os == con->optionStack &&
+ opt->argInfo & POPT_ARGFLAG_STRIP)
+ {
canstrip = 1;
poptStripArg(con, thisopt);
}
+ shorty = 0;
}
}
/* Process next short option */
+ /*@-branchstate@*/ /* FIX: W2DO? */
if (con->os->nextCharArg) {
origOptString = con->os->nextCharArg;
con->os->nextCharArg = NULL;
- if (handleAlias(con, NULL, *origOptString,
- origOptString + 1)) {
+ if (handleAlias(con, NULL, *origOptString, origOptString + 1))
+ continue;
+
+ if (handleExec(con, NULL, *origOptString)) {
+ /* Restore rest of short options for further processing */
origOptString++;
+ if (*origOptString != '\0')
+ con->os->nextCharArg = origOptString;
continue;
}
- if (handleExec(con, NULL, *origOptString))
- continue;
opt = findOption(con->options, NULL, *origOptString, &cb,
&cbData, 0);
if (!opt)
return POPT_ERROR_BADOPT;
+ shorty = 1;
origOptString++;
- if (*origOptString)
+ if (*origOptString != '\0')
con->os->nextCharArg = origOptString;
}
+ /*@=branchstate@*/
+ if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
- *((int *)opt->arg) = 1;
+ if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
+ return POPT_ERROR_BADOPERATION;
} else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
- if (opt->arg)
- *((int *) opt->arg) = opt->val;
- } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
- if (con->os->nextArg) {
- xfree(con->os->nextArg);
- con->os->nextArg = NULL;
+ if (opt->arg) {
+ if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
+ return POPT_ERROR_BADOPERATION;
}
+ } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
+ con->os->nextArg = _free(con->os->nextArg);
+ /*@-usedef@*/ /* FIX: W2DO? */
if (longArg) {
- con->os->nextArg = expandNextArg(con, longArg);
+ /*@=usedef@*/
+ longArg = expandNextArg(con, longArg);
+ con->os->nextArg = longArg;
} else if (con->os->nextCharArg) {
- con->os->nextArg = expandNextArg(con, con->os->nextCharArg);
+ longArg = expandNextArg(con, con->os->nextCharArg);
+ con->os->nextArg = longArg;
con->os->nextCharArg = NULL;
} else {
while (con->os->next == con->os->argc &&
con->os > con->optionStack) {
cleanOSE(con->os--);
}
- if (con->os->next == con->os->argc)
- return POPT_ERROR_NOARG;
-
- /* make sure this isn't part of a short arg or the
- result of an alias expansion */
- if(con->os == con->optionStack &&
- opt->argInfo & POPT_ARGFLAG_STRIP &&
- canstrip) {
- poptStripArg(con, con->os->next);
- }
+ if (con->os->next == con->os->argc) {
+ if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL))
+ /*@-compdef@*/ /* FIX: con->os->argv not defined */
+ return POPT_ERROR_NOARG;
+ /*@=compdef@*/
+ con->os->nextArg = NULL;
+ } else {
+
+ /*
+ * Make sure this isn't part of a short arg or the
+ * result of an alias expansion.
+ */
+ if (con->os == con->optionStack &&
+ (opt->argInfo & POPT_ARGFLAG_STRIP) &&
+ canstrip) {
+ poptStripArg(con, con->os->next);
+ }
- con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]);
+ if (con->os->argv != NULL) { /* XXX can't happen */
+ /* XXX watchout: subtle side-effects live here. */
+ longArg = con->os->argv[con->os->next++];
+ longArg = expandNextArg(con, longArg);
+ con->os->nextArg = longArg;
+ }
+ }
}
+ longArg = NULL;
if (opt->arg) {
- long aLong;
- char *end;
-
switch (opt->argInfo & POPT_ARG_MASK) {
- case POPT_ARG_STRING:
+ case POPT_ARG_STRING:
/* XXX memory leak, hard to plug */
- *((const char **) opt->arg) = xstrdup(con->os->nextArg);
- break;
-
- case POPT_ARG_INT:
- case POPT_ARG_LONG:
- aLong = strtol(con->os->nextArg, &end, 0);
- if (!(end && *end == '\0'))
- return POPT_ERROR_BADNUMBER;
+ *((const char **) opt->arg) = (con->os->nextArg)
+ ? xstrdup(con->os->nextArg) : NULL;
+ /*@switchbreak@*/ break;
+
+ case POPT_ARG_INT:
+ case POPT_ARG_LONG:
+ { long aLong = 0;
+ char *end;
+
+ if (con->os->nextArg) {
+ aLong = strtol(con->os->nextArg, &end, 0);
+ if (!(end && *end == '\0'))
+ return POPT_ERROR_BADNUMBER;
+ }
- if (aLong == LONG_MIN || aLong == LONG_MAX)
- return POPT_ERROR_OVERFLOW;
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
- *((long *) opt->arg) = aLong;
+ if (aLong == LONG_MIN || aLong == LONG_MAX)
+ return POPT_ERROR_OVERFLOW;
+ if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong))
+ return POPT_ERROR_BADOPERATION;
} else {
if (aLong > INT_MAX || aLong < INT_MIN)
return POPT_ERROR_OVERFLOW;
- *((int *) opt->arg) = aLong;
+ if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong))
+ return POPT_ERROR_BADOPERATION;
+ }
+ } /*@switchbreak@*/ break;
+
+ case POPT_ARG_FLOAT:
+ case POPT_ARG_DOUBLE:
+ { double aDouble = 0.0;
+ char *end;
+
+ if (con->os->nextArg) {
+ /*@-mods@*/
+ int saveerrno = errno;
+ errno = 0;
+ aDouble = strtod(con->os->nextArg, &end);
+ if (errno == ERANGE)
+ return POPT_ERROR_OVERFLOW;
+ errno = saveerrno;
+ /*@=mods@*/
+ if (*end != '\0')
+ return POPT_ERROR_BADNUMBER;
}
- break;
- default:
- fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"),
- opt->argInfo & POPT_ARG_MASK);
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
+ *((double *) opt->arg) = aDouble;
+ } else {
+#define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
+ if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
+ return POPT_ERROR_OVERFLOW;
+ if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON)
+ return POPT_ERROR_OVERFLOW;
+ *((float *) opt->arg) = aDouble;
+ }
+ } /*@switchbreak@*/ break;
+ default:
+ fprintf(stdout,
+ POPT_("option type (%d) not implemented in popt\n"),
+ (opt->argInfo & POPT_ARG_MASK));
exit(EXIT_FAILURE);
+ /*@notreached@*/ /*@switchbreak@*/ break;
}
}
}
- if (cb)
- cb(con, POPT_CALLBACK_REASON_OPTION, opt, con->os->nextArg, cbData);
- else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
+ if (cb) {
+ /*@-internalglobs@*/
+ invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
+ /*@=internalglobs@*/
+ } else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
done = 1;
if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
@@ -599,131 +958,222 @@ int poptGetNextOpt(poptContext con)
sizeof(*con->finalArgv) * con->finalArgvAlloced);
}
- { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
- if (opt->longName)
- sprintf(s, "--%s", opt->longName);
- else
- sprintf(s, "-%c", opt->shortName);
- con->finalArgv[con->finalArgvCount++] = s;
+ if (con->finalArgv != NULL)
+ { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3);
+ if (s != NULL) { /* XXX can't happen */
+ if (opt->longName)
+ sprintf(s, "%s%s",
+ ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
+ opt->longName);
+ else
+ sprintf(s, "-%c", opt->shortName);
+ con->finalArgv[con->finalArgvCount++] = s;
+ } else
+ con->finalArgv[con->finalArgvCount++] = NULL;
}
- if (opt->arg && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE
- && (opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL) {
- con->finalArgv[con->finalArgvCount++] = xstrdup(con->os->nextArg);
+ if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE)
+ /*@-ifempty@*/ ; /*@=ifempty@*/
+ else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL)
+ /*@-ifempty@*/ ; /*@=ifempty@*/
+ else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
+ if (con->finalArgv != NULL && con->os->nextArg)
+ con->finalArgv[con->finalArgvCount++] =
+ /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
+ xstrdup(con->os->nextArg);
+ /*@=nullpass@*/
}
}
- return opt->val;
+ return (opt ? opt->val : -1); /* XXX can't happen */
}
+/*@=boundswrite@*/
-const char * poptGetOptArg(poptContext con) {
- const char * ret = con->os->nextArg;
- con->os->nextArg = NULL;
+const char * poptGetOptArg(poptContext con)
+{
+ const char * ret = NULL;
+ /*@-branchstate@*/
+ if (con) {
+ ret = con->os->nextArg;
+ con->os->nextArg = NULL;
+ }
+ /*@=branchstate@*/
return ret;
}
-const char * poptGetArg(poptContext con) {
- if (con->numLeftovers == con->nextLeftover) return NULL;
- return con->leftovers[con->nextLeftover++];
+const char * poptGetArg(poptContext con)
+{
+ const char * ret = NULL;
+ if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
+ ret = con->leftovers[con->nextLeftover++];
+ return ret;
}
-const char * poptPeekArg(poptContext con) {
- if (con->numLeftovers == con->nextLeftover) return NULL;
- return con->leftovers[con->nextLeftover];
+const char * poptPeekArg(poptContext con)
+{
+ const char * ret = NULL;
+ if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
+ ret = con->leftovers[con->nextLeftover];
+ return ret;
}
-const char ** poptGetArgs(poptContext con) {
- if (con->numLeftovers == con->nextLeftover) return NULL;
+/*@-boundswrite@*/
+const char ** poptGetArgs(poptContext con)
+{
+ if (con == NULL ||
+ con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
+ return NULL;
/* some apps like [like RPM ;-) ] need this NULL terminated */
con->leftovers[con->numLeftovers] = NULL;
+ /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
return (con->leftovers + con->nextLeftover);
+ /*@=nullret =nullstate @*/
}
+/*@=boundswrite@*/
-void poptFreeContext(poptContext con) {
+poptContext poptFreeContext(poptContext con)
+{
+ poptItem item;
int i;
+ if (con == NULL) return con;
poptResetContext(con);
- if (con->os->argb) free(con->os->argb);
+ con->os->argb = _free(con->os->argb);
+ if (con->aliases != NULL)
for (i = 0; i < con->numAliases; i++) {
- if (con->aliases[i].longName) xfree(con->aliases[i].longName);
- free(con->aliases[i].argv);
+ item = con->aliases + i;
+ /*@-modobserver -observertrans -dependenttrans@*/
+ item->option.longName = _free(item->option.longName);
+ item->option.descrip = _free(item->option.descrip);
+ item->option.argDescrip = _free(item->option.argDescrip);
+ /*@=modobserver =observertrans =dependenttrans@*/
+ item->argv = _free(item->argv);
}
+ con->aliases = _free(con->aliases);
+ if (con->execs != NULL)
for (i = 0; i < con->numExecs; i++) {
- if (con->execs[i].longName) xfree(con->execs[i].longName);
- xfree(con->execs[i].script);
+ item = con->execs + i;
+ /*@-modobserver -observertrans -dependenttrans@*/
+ item->option.longName = _free(item->option.longName);
+ item->option.descrip = _free(item->option.descrip);
+ item->option.argDescrip = _free(item->option.argDescrip);
+ /*@=modobserver =observertrans =dependenttrans@*/
+ item->argv = _free(item->argv);
}
- if (con->execs) xfree(con->execs);
-
- free(con->leftovers);
- free(con->finalArgv);
- if (con->appName) xfree(con->appName);
- if (con->aliases) free(con->aliases);
- if (con->otherHelp) xfree(con->otherHelp);
- if (con->execPath) xfree(con->execPath);
- if (con->arg_strip) PBM_FREE(con->arg_strip);
+ con->execs = _free(con->execs);
+
+ con->leftovers = _free(con->leftovers);
+ con->finalArgv = _free(con->finalArgv);
+ con->appName = _free(con->appName);
+ con->otherHelp = _free(con->otherHelp);
+ con->execPath = _free(con->execPath);
+ con->arg_strip = PBM_FREE(con->arg_strip);
- free(con);
+ con = _free(con);
+ return con;
}
-int poptAddAlias(poptContext con, struct poptAlias newAlias,
+int poptAddAlias(poptContext con, struct poptAlias alias,
/*@unused@*/ int flags)
{
- int aliasNum = con->numAliases++;
- struct poptAlias * alias;
+ poptItem item = alloca(sizeof(*item));
+ memset(item, 0, sizeof(*item));
+ item->option.longName = alias.longName;
+ item->option.shortName = alias.shortName;
+ item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
+ item->option.arg = 0;
+ item->option.val = 0;
+ item->option.descrip = NULL;
+ item->option.argDescrip = NULL;
+ item->argc = alias.argc;
+ item->argv = alias.argv;
+ return poptAddItem(con, item, 0);
+}
- /* SunOS won't realloc(NULL, ...) */
- if (!con->aliases)
- con->aliases = malloc(sizeof(newAlias) * con->numAliases);
- else
- con->aliases = realloc(con->aliases,
- sizeof(newAlias) * con->numAliases);
- alias = con->aliases + aliasNum;
+/*@-boundswrite@*/
+/*@-mustmod@*/ /* LCL: con not modified? */
+int poptAddItem(poptContext con, poptItem newItem, int flags)
+{
+ poptItem * items, item;
+ int * nitems;
+
+ switch (flags) {
+ case 1:
+ items = &con->execs;
+ nitems = &con->numExecs;
+ break;
+ case 0:
+ items = &con->aliases;
+ nitems = &con->numAliases;
+ break;
+ default:
+ return 1;
+ /*@notreached@*/ break;
+ }
+
+ *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
+ if ((*items) == NULL)
+ return 1;
- alias->longName = (newAlias.longName)
- ? strcpy(malloc(strlen(newAlias.longName) + 1), newAlias.longName)
- : NULL;
- alias->shortName = newAlias.shortName;
- alias->argc = newAlias.argc;
- alias->argv = newAlias.argv;
+ item = (*items) + (*nitems);
+
+ item->option.longName =
+ (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL);
+ item->option.shortName = newItem->option.shortName;
+ item->option.argInfo = newItem->option.argInfo;
+ item->option.arg = newItem->option.arg;
+ item->option.val = newItem->option.val;
+ item->option.descrip =
+ (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL);
+ item->option.argDescrip =
+ (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL);
+ item->argc = newItem->argc;
+ item->argv = newItem->argv;
+
+ (*nitems)++;
return 0;
}
+/*@=mustmod@*/
+/*@=boundswrite@*/
-const char * poptBadOption(poptContext con, int flags) {
- struct optionStackEntry * os;
+const char * poptBadOption(poptContext con, int flags)
+{
+ struct optionStackEntry * os = NULL;
- if (flags & POPT_BADOPTION_NOALIAS)
- os = con->optionStack;
- else
- os = con->os;
+ if (con != NULL)
+ os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
- return os->argv[os->next - 1];
+ /*@-nullderef@*/ /* LCL: os->argv != NULL */
+ return (os && os->argv ? os->argv[os->next - 1] : NULL);
+ /*@=nullderef@*/
}
-#define POPT_ERROR_NOARG -10
-#define POPT_ERROR_BADOPT -11
-#define POPT_ERROR_OPTSTOODEEP -13
-#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
-#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
-
-const char *poptStrerror(const int error) {
+const char *poptStrerror(const int error)
+{
switch (error) {
case POPT_ERROR_NOARG:
return POPT_("missing argument");
case POPT_ERROR_BADOPT:
return POPT_("unknown option");
+ case POPT_ERROR_BADOPERATION:
+ return POPT_("mutually exclusive logical operations requested");
+ case POPT_ERROR_NULLARG:
+ return POPT_("opt->arg should not be NULL");
case POPT_ERROR_OPTSTOODEEP:
return POPT_("aliases nested too deeply");
case POPT_ERROR_BADQUOTE:
- return POPT_("error in paramter quoting");
+ return POPT_("error in parameter quoting");
case POPT_ERROR_BADNUMBER:
return POPT_("invalid numeric value");
case POPT_ERROR_OVERFLOW:
return POPT_("number too large or too small");
+ case POPT_ERROR_MALLOC:
+ return POPT_("memory allocation failed");
case POPT_ERROR_ERRNO:
return strerror(errno);
default:
@@ -731,52 +1181,56 @@ const char *poptStrerror(const int error) {
}
}
-int poptStuffArgs(poptContext con, const char ** argv) {
+int poptStuffArgs(poptContext con, const char ** argv)
+{
int argc;
+ int rc;
if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
return POPT_ERROR_OPTSTOODEEP;
for (argc = 0; argv[argc]; argc++)
- ;
+ {};
con->os++;
con->os->next = 0;
con->os->nextArg = NULL;
con->os->nextCharArg = NULL;
con->os->currAlias = NULL;
- poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
+ rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
con->os->argb = NULL;
con->os->stuffed = 1;
- return 0;
+ return rc;
}
-const char * poptGetInvocationName(poptContext con) {
- return con->os->argv[0];
+const char * poptGetInvocationName(poptContext con)
+{
+ return (con->os->argv ? con->os->argv[0] : "");
}
-int poptStrippedArgv(poptContext con, int argc, char **argv)
+/*@-boundswrite@*/
+int poptStrippedArgv(poptContext con, int argc, char ** argv)
{
- int i,j=1, numargs=argc;
+ int numargs = argc;
+ int j = 1;
+ int i;
- for(i=1; i<argc; i++) {
- if(PBM_ISSET(i, con->arg_strip)) {
+ /*@-sizeoftype@*/
+ if (con->arg_strip)
+ for (i = 1; i < argc; i++) {
+ if (PBM_ISSET(i, con->arg_strip))
numargs--;
- }
}
- for(i=1; i<argc; i++) {
- if(PBM_ISSET(i, con->arg_strip)) {
+ for (i = 1; i < argc; i++) {
+ if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
continue;
- } else {
- if(j<numargs) {
- argv[j++]=argv[i];
- } else {
- argv[j++]='\0';
- }
- }
+ argv[j] = (j < numargs) ? argv[i] : NULL;
+ j++;
}
+ /*@=sizeoftype@*/
- return(numargs);
+ return numargs;
}
+/*@=boundswrite@*/
diff --git a/source/popt/popt.h b/source/popt/popt.h
index c33cedaec99..08701d73b5e 100644
--- a/source/popt/popt.h
+++ b/source/popt/popt.h
@@ -1,128 +1,543 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \file popt/popt.h
+ * \ingroup popt
+ */
+
+/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPT
#define H_POPT
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <stdio.h> /* for FILE * */
#define POPT_OPTION_DEPTH 10
-#define POPT_ARG_NONE 0
-#define POPT_ARG_STRING 1
-#define POPT_ARG_INT 2
-#define POPT_ARG_LONG 3
-#define POPT_ARG_INCLUDE_TABLE 4 /* arg points to table */
-#define POPT_ARG_CALLBACK 5 /* table-wide callback... must be
+/** \ingroup popt
+ * \name Arg type identifiers
+ */
+/*@{*/
+#define POPT_ARG_NONE 0 /*!< no arg */
+#define POPT_ARG_STRING 1 /*!< arg will be saved as string */
+#define POPT_ARG_INT 2 /*!< arg will be converted to int */
+#define POPT_ARG_LONG 3 /*!< arg will be converted to long */
+#define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */
+#define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be
set first in table; arg points
to callback, descrip points to
callback data to pass */
-#define POPT_ARG_INTL_DOMAIN 6 /* set the translation domain
+#define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain
for this table and any
included tables; arg points
to the domain string */
-#define POPT_ARG_VAL 7 /* arg should take value val */
+#define POPT_ARG_VAL 7 /*!< arg should take value val */
+#define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */
+#define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */
+
#define POPT_ARG_MASK 0x0000FFFF
-#define POPT_ARGFLAG_ONEDASH 0x80000000 /* allow -longoption */
-#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /* don't show in help/usage */
-#define POPT_ARGFLAG_STRIP 0x20000000 /* strip this arg from argv (only applies to long args) */
-#define POPT_CBFLAG_PRE 0x80000000 /* call the callback before parse */
-#define POPT_CBFLAG_POST 0x40000000 /* call the callback after parse */
-#define POPT_CBFLAG_INC_DATA 0x20000000 /* use data from the include line,
+/*@}*/
+
+/** \ingroup popt
+ * \name Arg modifiers
+ */
+/*@{*/
+#define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */
+#define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */
+#define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */
+#define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */
+
+#define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */
+#define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */
+#define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */
+#define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */
+#define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */
+#define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */
+#define POPT_ARGFLAG_LOGICALOPS \
+ (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR)
+
+#define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR)
+ /*!< set arg bit(s) */
+#define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND)
+ /*!< clear arg bit(s) */
+
+#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */
+
+/*@}*/
+
+/** \ingroup popt
+ * \name Callback modifiers
+ */
+/*@{*/
+#define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */
+#define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */
+#define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line,
not the subtable */
+#define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */
+#define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */
+/*@}*/
-#define POPT_ERROR_NOARG -10
-#define POPT_ERROR_BADOPT -11
-#define POPT_ERROR_OPTSTOODEEP -13
-#define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */
-#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */
-#define POPT_ERROR_BADNUMBER -17
-#define POPT_ERROR_OVERFLOW -18
+/** \ingroup popt
+ * \name Error return values
+ */
+/*@{*/
+#define POPT_ERROR_NOARG -10 /*!< missing argument */
+#define POPT_ERROR_BADOPT -11 /*!< unknown option */
+#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
+#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
+#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
+#define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */
+#define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */
+#define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */
+#define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */
+#define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */
+/*@}*/
-/* poptBadOption() flags */
-#define POPT_BADOPTION_NOALIAS (1 << 0) /* don't go into an alias */
+/** \ingroup popt
+ * \name poptBadOption() flags
+ */
+/*@{*/
+#define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */
+/*@}*/
-/* poptGetContext() flags */
-#define POPT_CONTEXT_NO_EXEC (1 << 0) /* ignore exec expansions */
-#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /* pay attention to argv[0] */
-#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /* options can't follow args */
+/** \ingroup popt
+ * \name poptGetContext() flags
+ */
+/*@{*/
+#define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */
+#define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */
+#define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */
+#define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */
+/*@}*/
+/** \ingroup popt
+ */
struct poptOption {
- /*@observer@*/ /*@null@*/ const char * longName; /* may be NULL */
- char shortName; /* may be '\0' */
+/*@observer@*/ /*@null@*/
+ const char * longName; /*!< may be NULL */
+ char shortName; /*!< may be '\0' */
int argInfo;
- /*@shared@*/ /*@null@*/ void * arg; /* depends on argInfo */
- int val; /* 0 means don't return, just update flag */
- /*@shared@*/ /*@null@*/ const char * descrip; /* description for autohelp -- may be NULL */
- /*@shared@*/ /*@null@*/ const char * argDescrip; /* argument description for autohelp */
+/*@shared@*/ /*@null@*/
+ void * arg; /*!< depends on argInfo */
+ int val; /*!< 0 means don't return, just update flag */
+/*@observer@*/ /*@null@*/
+ const char * descrip; /*!< description for autohelp -- may be NULL */
+/*@observer@*/ /*@null@*/
+ const char * argDescrip; /*!< argument description for autohelp */
};
+/** \ingroup popt
+ * A popt alias argument for poptAddAlias().
+ */
struct poptAlias {
- /*@owned@*/ /*@null@*/ const char * longName; /* may be NULL */
- char shortName; /* may be '\0' */
+/*@owned@*/ /*@null@*/
+ const char * longName; /*!< may be NULL */
+ char shortName; /*!< may be '\0' */
int argc;
- /*@owned@*/ const char ** argv; /* must be free()able */
+/*@owned@*/
+ const char ** argv; /*!< must be free()able */
};
+/** \ingroup popt
+ * A popt alias or exec argument for poptAddItem().
+ */
+/*@-exporttype@*/
+typedef struct poptItem_s {
+ struct poptOption option; /*!< alias/exec name(s) and description. */
+ int argc; /*!< (alias) no. of args. */
+/*@owned@*/
+ const char ** argv; /*!< (alias) args, must be free()able. */
+} * poptItem;
+/*@=exporttype@*/
+
+/** \ingroup popt
+ * \name Auto-generated help/usage
+ */
+/*@{*/
+
+/**
+ * Empty table marker to enable displaying popt alias/exec options.
+ */
+/*@-exportvar@*/
+/*@unchecked@*/ /*@observer@*/
+extern struct poptOption poptAliasOptions[];
+/*@=exportvar@*/
+#define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \
+ 0, "Options implemented via popt alias/exec:", NULL },
+
+/**
+ * Auto help table options.
+ */
+/*@-exportvar@*/
+/*@unchecked@*/ /*@observer@*/
extern struct poptOption poptHelpOptions[];
+/*@=exportvar@*/
#define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \
- 0, "Help options", NULL },
+ 0, "Help options:", NULL },
+
+#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
+/*@}*/
-typedef struct poptContext_s * poptContext;
+/** \ingroup popt
+ */
+/*@-exporttype@*/
+typedef /*@abstract@*/ struct poptContext_s * poptContext;
+/*@=exporttype@*/
+
+/** \ingroup popt
+ */
#ifndef __cplusplus
+/*@-exporttype -typeuse@*/
typedef struct poptOption * poptOption;
+/*@=exporttype =typeuse@*/
+#endif
+
+/*@-exportconst@*/
+enum poptCallbackReason {
+ POPT_CALLBACK_REASON_PRE = 0,
+ POPT_CALLBACK_REASON_POST = 1,
+ POPT_CALLBACK_REASON_OPTION = 2
+};
+/*@=exportconst@*/
+
+#ifdef __cplusplus
+extern "C" {
#endif
+/*@-type@*/
+
+/** \ingroup popt
+ * Table callback prototype.
+ * @param con context
+ * @param reason reason for callback
+ * @param opt option that triggered callback
+ * @param arg @todo Document.
+ * @param data @todo Document.
+ */
+typedef void (*poptCallbackType) (poptContext con,
+ enum poptCallbackReason reason,
+ /*@null@*/ const struct poptOption * opt,
+ /*@null@*/ const char * arg,
+ /*@null@*/ const void * data)
+ /*@*/;
+
+/** \ingroup popt
+ * Initialize popt context.
+ * @param name context name (usually argv[0] program name)
+ * @param argc no. of arguments
+ * @param argv argument array
+ * @param options address of popt option table
+ * @param flags or'd POPT_CONTEXT_* bits
+ * @return initialized popt context
+ */
+/*@only@*/ /*@null@*/ poptContext poptGetContext(
+ /*@dependent@*/ /*@keep@*/ const char * name,
+ int argc, /*@dependent@*/ /*@keep@*/ const char ** argv,
+ /*@dependent@*/ /*@keep@*/ const struct poptOption * options,
+ int flags)
+ /*@*/;
-enum poptCallbackReason { POPT_CALLBACK_REASON_PRE,
- POPT_CALLBACK_REASON_POST,
- POPT_CALLBACK_REASON_OPTION };
-typedef void (*poptCallbackType)(poptContext con,
- enum poptCallbackReason reason,
- const struct poptOption * opt,
- const char * arg, const void * data);
-
-/*@only@*/ poptContext poptGetContext(/*@keep@*/ const char * name,
- int argc, /*@keep@*/ const char ** argv,
- /*@keep@*/ const struct poptOption * options, int flags);
-void poptResetContext(poptContext con);
-
-/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
-int poptGetNextOpt(poptContext con);
-/* returns NULL if no argument is available */
-/*@observer@*/ /*@null@*/ const char * poptGetOptArg(poptContext con);
-/* returns NULL if no more options are available */
-/*@observer@*/ /*@null@*/ const char * poptGetArg(poptContext con);
-/*@observer@*/ /*@null@*/ const char * poptPeekArg(poptContext con);
-/*@observer@*/ /*@null@*/ const char ** poptGetArgs(poptContext con);
-/* returns the option which caused the most recent error */
-/*@observer@*/ const char * poptBadOption(poptContext con, int flags);
-void poptFreeContext( /*@only@*/ poptContext con);
-int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv);
-int poptAddAlias(poptContext con, struct poptAlias alias, int flags);
-int poptReadConfigFile(poptContext con, const char * fn);
-/* like above, but reads /etc/popt and $HOME/.popt along with environment
- vars */
-int poptReadDefaultConfig(poptContext con, int useEnv);
-/* argv should be freed -- this allows ', ", and \ quoting, but ' is treated
- the same as " and both may include \ quotes */
-int poptDupArgv(int argc, const char **argv,
- /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr);
+/** \ingroup popt
+ * Reinitialize popt context.
+ * @param con context
+ */
+/*@unused@*/
+void poptResetContext(/*@null@*/poptContext con)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Return value of next option found.
+ * @param con context
+ * @return next option val, -1 on last item, POPT_ERROR_* on error
+ */
+int poptGetNextOpt(/*@null@*/poptContext con)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies con, fileSystem, internalState @*/;
+
+/** \ingroup popt
+ * Return next option argument (if any).
+ * @param con context
+ * @return option argument, NULL if no argument is available
+ */
+/*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Return next argument.
+ * @param con context
+ * @return next argument, NULL if no argument is available
+ */
+/*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Peek at current argument.
+ * @param con context
+ * @return current argument, NULL if no argument is available
+ */
+/*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con)
+ /*@*/;
+
+/** \ingroup popt
+ * Return remaining arguments.
+ * @param con context
+ * @return argument array, NULL terminated
+ */
+/*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Return the option which caused the most recent error.
+ * @param con context
+ * @param flags
+ * @return offending option
+ */
+/*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags)
+ /*@*/;
+
+/** \ingroup popt
+ * Destroy context.
+ * @param con context
+ * @return NULL always
+ */
+/*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Add arguments to context.
+ * @param con context
+ * @param argv argument array, NULL terminated
+ * @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure
+ */
+int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Add alias to context.
+ * @todo Pass alias by reference, not value.
+ * @deprecated Use poptAddItem instead.
+ * @param con context
+ * @param alias alias to add
+ * @param flags (unused)
+ * @return 0 on success
+ */
+/*@unused@*/
+int poptAddAlias(poptContext con, struct poptAlias alias, int flags)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Add alias/exec item to context.
+ * @param con context
+ * @param newItem alias/exec item to add
+ * @param flags 0 for alias, 1 for exec
+ * @return 0 on success
+ */
+int poptAddItem(poptContext con, poptItem newItem, int flags)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Read configuration file.
+ * @param con context
+ * @param fn file name to read
+ * @return 0 on success, POPT_ERROR_ERRNO on failure
+ */
+int poptReadConfigFile(poptContext con, const char * fn)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies con->execs, con->numExecs,
+ fileSystem, internalState @*/;
+
+/** \ingroup popt
+ * Read default configuration from /etc/popt and $HOME/.popt.
+ * @param con context
+ * @param useEnv (unused)
+ * @return 0 on success, POPT_ERROR_ERRNO on failure
+ */
+int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies con->execs, con->numExecs,
+ fileSystem, internalState @*/;
+
+/** \ingroup popt
+ * Duplicate an argument array.
+ * @note: The argument array is malloc'd as a single area, so only argv must
+ * be free'd.
+ *
+ * @param argc no. of arguments
+ * @param argv argument array
+ * @retval argcPtr address of returned no. of arguments
+ * @retval argvPtr address of returned argument array
+ * @return 0 on success, POPT_ERROR_NOARG on failure
+ */
+int poptDupArgv(int argc, /*@null@*/ const char **argv,
+ /*@null@*/ /*@out@*/ int * argcPtr,
+ /*@null@*/ /*@out@*/ const char *** argvPtr)
+ /*@modifies *argcPtr, *argvPtr @*/;
+
+/** \ingroup popt
+ * Parse a string into an argument array.
+ * The parse allows ', ", and \ quoting, but ' is treated the same as " and
+ * both may include \ quotes.
+ * @note: The argument array is malloc'd as a single area, so only argv must
+ * be free'd.
+ *
+ * @param s string to parse
+ * @retval argcPtr address of returned no. of arguments
+ * @retval argvPtr address of returned argument array
+ */
int poptParseArgvString(const char * s,
- /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr);
-/*@observer@*/ const char *poptStrerror(const int error);
-void poptSetExecPath(poptContext con, const char * path, int allowAbsolute);
-void poptPrintHelp(poptContext con, FILE * f, int flags);
-void poptPrintUsage(poptContext con, FILE * f, int flags);
-void poptSetOtherOptionHelp(poptContext con, const char * text);
-/*@observer@*/ const char * poptGetInvocationName(poptContext con);
-/* shuffles argv pointers to remove stripped args, returns new argc */
-int poptStrippedArgv(poptContext con, int argc, char **argv);
+ /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
+ /*@modifies *argcPtr, *argvPtr @*/;
+
+/** \ingroup popt
+ * Parses an input configuration file and returns an string that is a
+ * command line. For use with popt. You must free the return value when done.
+ *
+ * Given the file:
+\verbatim
+# this line is ignored
+ # this one too
+aaa
+ bbb
+ ccc
+bla=bla
+
+this_is = fdsafdas
+ bad_line=
+ reall bad line
+ reall bad line = again
+5555= 55555
+ test = with lots of spaces
+\endverbatim
+*
+* The result is:
+\verbatim
+--aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces"
+\endverbatim
+*
+* Passing this to poptParseArgvString() yields an argv of:
+\verbatim
+'--aaa'
+'--bbb'
+'--ccc'
+'--bla=bla'
+'--this_is=fdsafdas'
+'--5555=55555'
+'--test=with lots of spaces'
+\endverbatim
+ *
+ * @bug NULL is returned if file line is too long.
+ * @bug Silently ignores invalid lines.
+ *
+ * @param fp file handle to read
+ * @param *argstrp return string of options (malloc'd)
+ * @param flags unused
+ * @return 0 on success
+ * @see poptParseArgvString
+ */
+/*@-fcnuse@*/
+int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, *argstrp, fileSystem @*/;
+/*@=fcnuse@*/
+
+/** \ingroup popt
+ * Return formatted error string for popt failure.
+ * @param error popt error
+ * @return error string
+ */
+/*@observer@*/ const char* poptStrerror(const int error)
+ /*@*/;
+
+/** \ingroup popt
+ * Limit search for executables.
+ * @param con context
+ * @param path single path to search for executables
+ * @param allowAbsolute absolute paths only?
+ */
+void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
+ /*@modifies con @*/;
+
+/** \ingroup popt
+ * Print detailed description of options.
+ * @param con context
+ * @param fp ouput file handle
+ * @param flags (unused)
+ */
+void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/;
+
+/** \ingroup popt
+ * Print terse description of options.
+ * @param con context
+ * @param fp ouput file handle
+ * @param flags (unused)
+ */
+void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/;
+
+/** \ingroup popt
+ * Provide text to replace default "[OPTION...]" in help/usage output.
+ * @param con context
+ * @param text replacement text
+ */
+/*@-fcnuse@*/
+void poptSetOtherOptionHelp(poptContext con, const char * text)
+ /*@modifies con @*/;
+/*@=fcnuse@*/
+
+/** \ingroup popt
+ * Return argv[0] from context.
+ * @param con context
+ * @return argv[0]
+ */
+/*@-fcnuse@*/
+/*@observer@*/ const char * poptGetInvocationName(poptContext con)
+ /*@*/;
+/*@=fcnuse@*/
+
+/** \ingroup popt
+ * Shuffle argv pointers to remove stripped args, returns new argc.
+ * @param con context
+ * @param argc no. of args
+ * @param argv arg vector
+ * @return new argc
+ */
+/*@-fcnuse@*/
+int poptStrippedArgv(poptContext con, int argc, char ** argv)
+ /*@modifies *argv @*/;
+/*@=fcnuse@*/
+
+/**
+ * Save a long, performing logical operation with value.
+ * @warning Alignment check may be too strict on certain platorms.
+ * @param arg integer pointer, aligned on int boundary.
+ * @param argInfo logical operation (see POPT_ARGFLAG_*)
+ * @param aLong value to use
+ * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
+ */
+/*@-incondefs@*/
+/*@unused@*/
+int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong)
+ /*@modifies *arg @*/
+ /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
+/*@=incondefs@*/
+
+/**
+ * Save an integer, performing logical operation with value.
+ * @warning Alignment check may be too strict on certain platorms.
+ * @param arg integer pointer, aligned on int boundary.
+ * @param argInfo logical operation (see POPT_ARGFLAG_*)
+ * @param aLong value to use
+ * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION
+ */
+/*@-incondefs@*/
+/*@unused@*/
+int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
+ /*@modifies *arg @*/
+ /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/;
+/*@=incondefs@*/
+/*@=type@*/
#ifdef __cplusplus
}
#endif
diff --git a/source/popt/poptconfig.c b/source/popt/poptconfig.c
index eb769413630..5941c2b7045 100644
--- a/source/popt/poptconfig.c
+++ b/source/popt/poptconfig.c
@@ -1,101 +1,147 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/poptconfig.c
+ */
+
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
-static void configLine(poptContext con, char * line) {
+/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
+static void configLine(poptContext con, char * line)
+ /*@modifies con @*/
+{
+ /*@-type@*/
int nameLength = strlen(con->appName);
- char * opt;
- struct poptAlias alias;
- char * entryType;
- char * longName = NULL;
- char shortName = '\0';
+ /*@=type@*/
+ const char * entryType;
+ const char * opt;
+ poptItem item = alloca(sizeof(*item));
+ int i, j;
+/*@-boundswrite@*/
+ memset(item, 0, sizeof(*item));
+
+ /*@-type@*/
if (strncmp(line, con->appName, nameLength)) return;
+ /*@=type@*/
+
line += nameLength;
- if (!*line || !isspace(*line)) return;
- while (*line && isspace(*line)) line++;
- entryType = line;
+ if (*line == '\0' || !isspace(*line)) return;
- while (!*line || !isspace(*line)) line++;
+ while (*line != '\0' && isspace(*line)) line++;
+ entryType = line;
+ while (*line == '\0' || !isspace(*line)) line++;
*line++ = '\0';
- while (*line && isspace(*line)) line++;
- if (!*line) return;
- opt = line;
- while (!*line || !isspace(*line)) line++;
+ while (*line != '\0' && isspace(*line)) line++;
+ if (*line == '\0') return;
+ opt = line;
+ while (*line == '\0' || !isspace(*line)) line++;
*line++ = '\0';
- while (*line && isspace(*line)) line++;
- if (!*line) return;
+ while (*line != '\0' && isspace(*line)) line++;
+ if (*line == '\0') return;
+
+ /*@-temptrans@*/ /* FIX: line alias is saved */
if (opt[0] == '-' && opt[1] == '-')
- longName = opt + 2;
- else if (opt[0] == '-' && !opt[2])
- shortName = opt[1];
-
- if (!strcmp(entryType, "alias")) {
- if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
- alias.longName = longName, alias.shortName = shortName;
- poptAddAlias(con, alias, 0);
- } else if (!strcmp(entryType, "exec")) {
- con->execs = realloc(con->execs,
- sizeof(*con->execs) * (con->numExecs + 1));
- if (longName)
- con->execs[con->numExecs].longName = xstrdup(longName);
- else
- con->execs[con->numExecs].longName = NULL;
-
- con->execs[con->numExecs].shortName = shortName;
- con->execs[con->numExecs].script = xstrdup(line);
-
- con->numExecs++;
+ item->option.longName = opt + 2;
+ else if (opt[0] == '-' && opt[2] == '\0')
+ item->option.shortName = opt[1];
+ /*@=temptrans@*/
+
+ if (poptParseArgvString(line, &item->argc, &item->argv)) return;
+
+ /*@-modobserver@*/
+ item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
+ for (i = 0, j = 0; i < item->argc; i++, j++) {
+ const char * f;
+ if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
+ f = item->argv[i] + sizeof("--POPTdesc=");
+ if (f[0] == '$' && f[1] == '"') f++;
+ item->option.descrip = f;
+ item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
+ j--;
+ } else
+ if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
+ f = item->argv[i] + sizeof("--POPTargs=");
+ if (f[0] == '$' && f[1] == '"') f++;
+ item->option.argDescrip = f;
+ item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
+ item->option.argInfo |= POPT_ARG_STRING;
+ j--;
+ } else
+ if (j != i)
+ item->argv[j] = item->argv[i];
+ }
+ if (j != i) {
+ item->argv[j] = NULL;
+ item->argc = j;
}
+ /*@=modobserver@*/
+/*@=boundswrite@*/
+
+ /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
+ if (!strcmp(entryType, "alias"))
+ (void) poptAddItem(con, item, 0);
+ else if (!strcmp(entryType, "exec"))
+ (void) poptAddItem(con, item, 1);
+ /*@=nullstate@*/
}
+/*@=compmempass@*/
-int poptReadConfigFile(poptContext con, const char * fn) {
- char * file=NULL, * chptr, * end;
- char * buf=NULL, * dst;
+int poptReadConfigFile(poptContext con, const char * fn)
+{
+ const char * file, * chptr, * end;
+ char * buf;
+/*@dependent@*/ char * dst;
int fd, rc;
- int fileLength;
+ off_t fileLength;
fd = open(fn, O_RDONLY);
- if (fd < 0) {
- if (errno == ENOENT)
- return 0;
- else
- return POPT_ERROR_ERRNO;
- }
+ if (fd < 0)
+ return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
fileLength = lseek(fd, 0, SEEK_END);
- (void) lseek(fd, 0, 0);
+ if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
+ rc = errno;
+ (void) close(fd);
+ /*@-mods@*/
+ errno = rc;
+ /*@=mods@*/
+ return POPT_ERROR_ERRNO;
+ }
- file = malloc(fileLength + 1);
- if (read(fd, file, fileLength) != fileLength) {
+ file = alloca(fileLength + 1);
+ if (read(fd, (char *)file, fileLength) != fileLength) {
rc = errno;
- close(fd);
+ (void) close(fd);
+ /*@-mods@*/
errno = rc;
- if (file) free(file);
+ /*@=mods@*/
return POPT_ERROR_ERRNO;
}
- close(fd);
+ if (close(fd) == -1)
+ return POPT_ERROR_ERRNO;
- dst = buf = malloc(fileLength + 1);
+/*@-boundswrite@*/
+ dst = buf = alloca(fileLength + 1);
chptr = file;
end = (file + fileLength);
+ /*@-infloops@*/ /* LCL: can't detect chptr++ */
while (chptr < end) {
switch (*chptr) {
case '\n':
*dst = '\0';
dst = buf;
while (*dst && isspace(*dst)) dst++;
- if (*dst && *dst != '#') {
+ if (*dst && *dst != '#')
configLine(con, dst);
- }
chptr++;
- break;
+ /*@switchbreak@*/ break;
case '\\':
*dst++ = *chptr++;
if (chptr < end) {
@@ -105,38 +151,40 @@ int poptReadConfigFile(poptContext con, const char * fn) {
else
*dst++ = *chptr++;
}
- break;
+ /*@switchbreak@*/ break;
default:
*dst++ = *chptr++;
- break;
+ /*@switchbreak@*/ break;
}
}
-
- free(file);
- free(buf);
+ /*@=infloops@*/
+/*@=boundswrite@*/
return 0;
}
-int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) {
+int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
+{
char * fn, * home;
int rc;
+ /*@-type@*/
if (!con->appName) return 0;
+ /*@=type@*/
rc = poptReadConfigFile(con, "/etc/popt");
if (rc) return rc;
+#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
if (getuid() != geteuid()) return 0;
+#endif
if ((home = getenv("HOME"))) {
- fn = malloc(strlen(home) + 20);
+ fn = alloca(strlen(home) + 20);
strcpy(fn, home);
strcat(fn, "/.popt");
rc = poptReadConfigFile(con, fn);
- free(fn);
if (rc) return rc;
}
return 0;
}
-
diff --git a/source/popt/popthelp.c b/source/popt/popthelp.c
index 6b790a63e78..70566a389e2 100644
--- a/source/popt/popthelp.c
+++ b/source/popt/popthelp.c
@@ -1,48 +1,96 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/*@-type@*/
+/** \ingroup popt
+ * \file popt/popthelp.c
+ */
+
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#include "poptint.h"
+/**
+ * Display arguments.
+ * @param con context
+ * @param foo (unused)
+ * @param key option(s)
+ * @param arg (unused)
+ * @param data (unused)
+ */
static void displayArgs(poptContext con,
/*@unused@*/ enum poptCallbackReason foo,
struct poptOption * key,
- /*@unused@*/ const char * arg, /*@unused@*/ void * data) {
- if (key->shortName== '?')
+ /*@unused@*/ const char * arg, /*@unused@*/ void * data)
+ /*@globals fileSystem@*/
+ /*@modifies fileSystem@*/
+{
+ if (key->shortName == '?')
poptPrintHelp(con, stdout, 0);
else
poptPrintUsage(con, stdout, 0);
exit(0);
}
+#ifdef NOTYET
+/*@unchecked@*/
+static int show_option_defaults = 0;
+#endif
+
+/**
+ * Empty table marker to enable displaying popt alias/exec options.
+ */
+/*@observer@*/ /*@unchecked@*/
+struct poptOption poptAliasOptions[] = {
+ POPT_TABLEEND
+};
+
+/**
+ * Auto help table options.
+ */
+/*@-castfcnptr@*/
+/*@observer@*/ /*@unchecked@*/
struct poptOption poptHelpOptions[] = {
- { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
- { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
- { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
- { NULL, '\0', 0, NULL, 0, NULL, NULL }
+ { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
+ { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
+ { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
+#ifdef NOTYET
+ { "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
+ N_("Display option defaults in message"), NULL },
+#endif
+ POPT_TABLEEND
} ;
+/*@=castfcnptr@*/
-
+/**
+ * @param table option(s)
+ */
/*@observer@*/ /*@null@*/ static const char *
-getTableTranslationDomain(const struct poptOption *table)
+getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
+ /*@*/
{
- const struct poptOption *opt;
+ const struct poptOption *opt;
- for(opt = table;
- opt->longName || opt->shortName || opt->arg;
- opt++) {
- if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
- return opt->arg;
- }
-
- return NULL;
+ if (table != NULL)
+ for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
+ if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
+ return opt->arg;
+ }
+ return NULL;
}
+/**
+ * @param opt option(s)
+ * @param translation_domain translation domain
+ */
/*@observer@*/ /*@null@*/ static const char *
-getArgDescrip(const struct poptOption * opt, const char *translation_domain)
+getArgDescrip(const struct poptOption * opt,
+ /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
+ /*@null@*/ const char * translation_domain)
+ /*@=paramuse@*/
+ /*@*/
{
if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
@@ -50,45 +98,242 @@ getArgDescrip(const struct poptOption * opt, const char *translation_domain)
if (opt->argDescrip) return POPT_(opt->argDescrip);
if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
- return POPT_("ARG");
+
+ switch (opt->argInfo & POPT_ARG_MASK) {
+ case POPT_ARG_NONE: return POPT_("NONE");
+#ifdef DYING
+ case POPT_ARG_VAL: return POPT_("VAL");
+#else
+ case POPT_ARG_VAL: return NULL;
+#endif
+ case POPT_ARG_INT: return POPT_("INT");
+ case POPT_ARG_LONG: return POPT_("LONG");
+ case POPT_ARG_STRING: return POPT_("STRING");
+ case POPT_ARG_FLOAT: return POPT_("FLOAT");
+ case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
+ default: return POPT_("ARG");
+ }
+}
+
+/**
+ * Display default value for an option.
+ * @param lineLength
+ * @param opt option(s)
+ * @param translation_domain translation domain
+ * @return
+ */
+static /*@only@*/ /*@null@*/ char *
+singleOptionDefaultValue(int lineLength,
+ const struct poptOption * opt,
+ /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
+ /*@null@*/ const char * translation_domain)
+ /*@=paramuse@*/
+ /*@*/
+{
+ const char * defstr = D_(translation_domain, "default");
+ char * le = malloc(4*lineLength + 1);
+ char * l = le;
+
+ if (le == NULL) return NULL; /* XXX can't happen */
+/*@-boundswrite@*/
+ *le = '\0';
+ *le++ = '(';
+ strcpy(le, defstr); le += strlen(le);
+ *le++ = ':';
+ *le++ = ' ';
+ if (opt->arg) /* XXX programmer error */
+ switch (opt->argInfo & POPT_ARG_MASK) {
+ case POPT_ARG_VAL:
+ case POPT_ARG_INT:
+ { long aLong = *((int *)opt->arg);
+ le += sprintf(le, "%ld", aLong);
+ } break;
+ case POPT_ARG_LONG:
+ { long aLong = *((long *)opt->arg);
+ le += sprintf(le, "%ld", aLong);
+ } break;
+ case POPT_ARG_FLOAT:
+ { double aDouble = *((float *)opt->arg);
+ le += sprintf(le, "%g", aDouble);
+ } break;
+ case POPT_ARG_DOUBLE:
+ { double aDouble = *((double *)opt->arg);
+ le += sprintf(le, "%g", aDouble);
+ } break;
+ case POPT_ARG_STRING:
+ { const char * s = *(const char **)opt->arg;
+ if (s == NULL) {
+ strcpy(le, "null"); le += strlen(le);
+ } else {
+ size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
+ *le++ = '"';
+ strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
+ if (slen < strlen(s)) {
+ strcpy(le, "..."); le += strlen(le);
+ }
+ *le++ = '"';
+ }
+ } break;
+ case POPT_ARG_NONE:
+ default:
+ l = _free(l);
+ return NULL;
+ /*@notreached@*/ break;
+ }
+ *le++ = ')';
+ *le = '\0';
+/*@=boundswrite@*/
+
+ return l;
}
-static void singleOptionHelp(FILE * f, int maxLeftCol,
- const struct poptOption * opt,
- const char *translation_domain) {
+/**
+ * Display help text for an option.
+ * @param fp output file handle
+ * @param maxLeftCol
+ * @param opt option(s)
+ * @param translation_domain translation domain
+ */
+static void singleOptionHelp(FILE * fp, int maxLeftCol,
+ const struct poptOption * opt,
+ /*@null@*/ const char * translation_domain)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/
+{
int indentLength = maxLeftCol + 5;
int lineLength = 79 - indentLength;
const char * help = D_(translation_domain, opt->descrip);
+ const char * argDescrip = getArgDescrip(opt, translation_domain);
int helpLength;
- const char * ch;
- char format[10];
+ char * defs = NULL;
char * left;
- const char * argDescrip = getArgDescrip(opt, translation_domain);
+ int nb = maxLeftCol + 1;
+
+ /* Make sure there's more than enough room in target buffer. */
+ if (opt->longName) nb += strlen(opt->longName);
+ if (argDescrip) nb += strlen(argDescrip);
- left = malloc(maxLeftCol + 1);
- *left = '\0';
+/*@-boundswrite@*/
+ left = malloc(nb);
+ if (left == NULL) return; /* XXX can't happen */
+ left[0] = '\0';
+ left[maxLeftCol] = '\0';
if (opt->longName && opt->shortName)
- sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
- else if (opt->shortName)
+ sprintf(left, "-%c, %s%s", opt->shortName,
+ ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
+ opt->longName);
+ else if (opt->shortName != '\0')
sprintf(left, "-%c", opt->shortName);
else if (opt->longName)
- sprintf(left, "--%s", opt->longName);
- if (!*left) return ;
+ sprintf(left, "%s%s",
+ ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
+ opt->longName);
+ if (!*left) goto out;
+
if (argDescrip) {
- strcat(left, "=");
- strcat(left, argDescrip);
+ char * le = left + strlen(left);
+
+ if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
+ *le++ = '[';
+
+ /* Choose type of output */
+ /*@-branchstate@*/
+ if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) {
+ defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
+ if (defs) {
+ char * t = malloc((help ? strlen(help) : 0) +
+ strlen(defs) + sizeof(" "));
+ if (t) {
+ char * te = t;
+ *te = '\0';
+ if (help) {
+ strcpy(te, help); te += strlen(te);
+ }
+ *te++ = ' ';
+ strcpy(te, defs);
+ defs = _free(defs);
+ }
+ defs = t;
+ }
+ }
+ /*@=branchstate@*/
+
+ if (opt->argDescrip == NULL) {
+ switch (opt->argInfo & POPT_ARG_MASK) {
+ case POPT_ARG_NONE:
+ break;
+ case POPT_ARG_VAL:
+#ifdef NOTNOW /* XXX pug ugly nerdy output */
+ { long aLong = opt->val;
+ int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
+ int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
+
+ /* Don't bother displaying typical values */
+ if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
+ break;
+ *le++ = '[';
+ switch (ops) {
+ case POPT_ARGFLAG_OR:
+ *le++ = '|';
+ /*@innerbreak@*/ break;
+ case POPT_ARGFLAG_AND:
+ *le++ = '&';
+ /*@innerbreak@*/ break;
+ case POPT_ARGFLAG_XOR:
+ *le++ = '^';
+ /*@innerbreak@*/ break;
+ default:
+ /*@innerbreak@*/ break;
+ }
+ *le++ = '=';
+ if (negate) *le++ = '~';
+ /*@-formatconst@*/
+ le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
+ /*@=formatconst@*/
+ *le++ = ']';
+ }
+#endif
+ break;
+ case POPT_ARG_INT:
+ case POPT_ARG_LONG:
+ case POPT_ARG_FLOAT:
+ case POPT_ARG_DOUBLE:
+ case POPT_ARG_STRING:
+ *le++ = '=';
+ strcpy(le, argDescrip); le += strlen(le);
+ break;
+ default:
+ break;
+ }
+ } else {
+ *le++ = '=';
+ strcpy(le, argDescrip); le += strlen(le);
+ }
+ if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
+ *le++ = ']';
+ *le = '\0';
}
+/*@=boundswrite@*/
if (help)
- fprintf(f," %-*s ", maxLeftCol, left);
+ fprintf(fp," %-*s ", maxLeftCol, left);
else {
- fprintf(f," %s\n", left);
+ fprintf(fp," %s\n", left);
goto out;
}
+ left = _free(left);
+ if (defs) {
+ help = defs; defs = NULL;
+ }
+
helpLength = strlen(help);
+/*@-boundsread@*/
while (helpLength > lineLength) {
+ const char * ch;
+ char format[16];
+
ch = help + lineLength - 1;
while (ch > help && !isspace(*ch)) ch--;
if (ch == help) break; /* give up */
@@ -96,39 +341,57 @@ static void singleOptionHelp(FILE * f, int maxLeftCol,
ch++;
sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
- fprintf(f, format, help, " ");
+ /*@-formatconst@*/
+ fprintf(fp, format, help, " ");
+ /*@=formatconst@*/
help = ch;
while (isspace(*help) && *help) help++;
helpLength = strlen(help);
}
+/*@=boundsread@*/
- if (helpLength) fprintf(f, "%s\n", help);
+ if (helpLength) fprintf(fp, "%s\n", help);
out:
- free(left);
+ /*@-dependenttrans@*/
+ defs = _free(defs);
+ /*@=dependenttrans@*/
+ left = _free(left);
}
+/**
+ * @param opt option(s)
+ * @param translation_domain translation domain
+ */
static int maxArgWidth(const struct poptOption * opt,
- const char * translation_domain) {
+ /*@null@*/ const char * translation_domain)
+ /*@*/
+{
int max = 0;
- int this;
+ int len = 0;
const char * s;
+ if (opt != NULL)
while (opt->longName || opt->shortName || opt->arg) {
if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
- this = maxArgWidth(opt->arg, translation_domain);
- if (this > max) max = this;
+ if (opt->arg) /* XXX program error */
+ len = maxArgWidth(opt->arg, translation_domain);
+ if (len > max) max = len;
} else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
- this = opt->shortName ? 2 : 0;
+ len = sizeof(" ")-1;
+ if (opt->shortName != '\0') len += sizeof("-X")-1;
+ if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1;
if (opt->longName) {
- if (this) this += 2;
- this += strlen(opt->longName) + 2;
+ len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH)
+ ? sizeof("-")-1 : sizeof("--")-1);
+ len += strlen(opt->longName);
}
s = getArgDescrip(opt, translation_domain);
if (s)
- this += strlen(s) + 1;
- if (this > max) max = this;
+ len += sizeof("=")-1 + strlen(s);
+ if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
+ if (len > max) max = len;
}
opt++;
@@ -137,165 +400,339 @@ static int maxArgWidth(const struct poptOption * opt,
return max;
}
-static void singleTableHelp(FILE * f, const struct poptOption * table,
- int left,
- const char *translation_domain) {
+/**
+ * Display popt alias and exec help.
+ * @param fp output file handle
+ * @param items alias/exec array
+ * @param nitems no. of alias/exec entries
+ * @param left
+ * @param translation_domain translation domain
+ */
+static void itemHelp(FILE * fp,
+ /*@null@*/ poptItem items, int nitems, int left,
+ /*@null@*/ const char * translation_domain)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/
+{
+ poptItem item;
+ int i;
+
+ if (items != NULL)
+ for (i = 0, item = items; i < nitems; i++, item++) {
+ const struct poptOption * opt;
+ opt = &item->option;
+ if ((opt->longName || opt->shortName) &&
+ !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
+ singleOptionHelp(fp, left, opt, translation_domain);
+ }
+}
+
+/**
+ * Display help text for a table of options.
+ * @param con context
+ * @param fp output file handle
+ * @param table option(s)
+ * @param left
+ * @param translation_domain translation domain
+ */
+static void singleTableHelp(poptContext con, FILE * fp,
+ /*@null@*/ const struct poptOption * table, int left,
+ /*@null@*/ const char * translation_domain)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/
+{
const struct poptOption * opt;
const char *sub_transdom;
- opt = table;
- while (opt->longName || opt->shortName || opt->arg) {
+ if (table == poptAliasOptions) {
+ itemHelp(fp, con->aliases, con->numAliases, left, NULL);
+ itemHelp(fp, con->execs, con->numExecs, left, NULL);
+ return;
+ }
+
+ if (table != NULL)
+ for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
if ((opt->longName || opt->shortName) &&
!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
- singleOptionHelp(f, left, opt, translation_domain);
- opt++;
+ singleOptionHelp(fp, left, opt, translation_domain);
}
- opt = table;
- while (opt->longName || opt->shortName || opt->arg) {
- if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
- sub_transdom = getTableTranslationDomain(opt->arg);
- if(!sub_transdom)
- sub_transdom = translation_domain;
+ if (table != NULL)
+ for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
+ if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE)
+ continue;
+ sub_transdom = getTableTranslationDomain(opt->arg);
+ if (sub_transdom == NULL)
+ sub_transdom = translation_domain;
- if (opt->descrip)
- fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
+ if (opt->descrip)
+ fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
- singleTableHelp(f, opt->arg, left, sub_transdom);
- }
- opt++;
+ singleTableHelp(con, fp, opt->arg, left, sub_transdom);
}
}
-static int showHelpIntro(poptContext con, FILE * f) {
+/**
+ * @param con context
+ * @param fp output file handle
+ */
+static int showHelpIntro(poptContext con, FILE * fp)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/
+{
int len = 6;
const char * fn;
- fprintf(f, POPT_("Usage:"));
+ fprintf(fp, POPT_("Usage:"));
if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
+/*@-boundsread@*/
+ /*@-nullderef@*/ /* LCL: wazzup? */
fn = con->optionStack->argv[0];
- if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
- fprintf(f, " %s", fn);
+ /*@=nullderef@*/
+/*@=boundsread@*/
+ if (fn == NULL) return len;
+ if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
+ fprintf(fp, " %s", fn);
len += strlen(fn) + 1;
}
return len;
}
-void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int flags) {
+void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
+{
int leftColWidth;
- showHelpIntro(con, f);
+ (void) showHelpIntro(con, fp);
if (con->otherHelp)
- fprintf(f, " %s\n", con->otherHelp);
+ fprintf(fp, " %s\n", con->otherHelp);
else
- fprintf(f, " %s\n", POPT_("[OPTION...]"));
+ fprintf(fp, " %s\n", POPT_("[OPTION...]"));
leftColWidth = maxArgWidth(con->options, NULL);
- singleTableHelp(f, con->options, leftColWidth, NULL);
+ singleTableHelp(con, fp, con->options, leftColWidth, NULL);
}
-static int singleOptionUsage(FILE * f, int cursor,
- const struct poptOption * opt,
- const char *translation_domain) {
- int len = 3;
+/**
+ * @param fp output file handle
+ * @param cursor
+ * @param opt option(s)
+ * @param translation_domain translation domain
+ */
+static int singleOptionUsage(FILE * fp, int cursor,
+ const struct poptOption * opt,
+ /*@null@*/ const char *translation_domain)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/
+{
+ int len = 4;
char shortStr[2] = { '\0', '\0' };
const char * item = shortStr;
const char * argDescrip = getArgDescrip(opt, translation_domain);
- if (opt->shortName) {
- if (!(opt->argInfo & POPT_ARG_MASK))
- return cursor; /* we did these already */
+ if (opt->shortName != '\0' && opt->longName != NULL) {
+ len += 2;
+ if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
+ len += strlen(opt->longName);
+ } else if (opt->shortName != '\0') {
len++;
- *shortStr = opt->shortName;
+ shortStr[0] = opt->shortName;
shortStr[1] = '\0';
} else if (opt->longName) {
- len += 1 + strlen(opt->longName);
+ len += strlen(opt->longName);
+ if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
item = opt->longName;
}
- if (len == 3) return cursor;
+ if (len == 4) return cursor;
if (argDescrip)
len += strlen(argDescrip) + 1;
if ((cursor + len) > 79) {
- fprintf(f, "\n ");
+ fprintf(fp, "\n ");
cursor = 7;
}
- fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
- argDescrip ? (opt->shortName ? " " : "=") : "",
- argDescrip ? argDescrip : "");
+ if (opt->longName && opt->shortName) {
+ fprintf(fp, " [-%c|-%s%s%s%s]",
+ opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"),
+ opt->longName,
+ (argDescrip ? " " : ""),
+ (argDescrip ? argDescrip : ""));
+ } else {
+ fprintf(fp, " [-%s%s%s%s]",
+ ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
+ item,
+ (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
+ (argDescrip ? argDescrip : ""));
+ }
return cursor + len + 1;
}
-static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
- const char *translation_domain) {
- const struct poptOption * opt;
-
- opt = table;
- while (opt->longName || opt->shortName || opt->arg) {
- if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
+/**
+ * Display popt alias and exec usage.
+ * @param fp output file handle
+ * @param cursor
+ * @param item alias/exec array
+ * @param nitems no. of ara/exec entries
+ * @param translation_domain translation domain
+ */
+static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
+ /*@null@*/ const char * translation_domain)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, fileSystem @*/
+{
+ int i;
+
+ /*@-branchstate@*/ /* FIX: W2DO? */
+ if (item != NULL)
+ for (i = 0; i < nitems; i++, item++) {
+ const struct poptOption * opt;
+ opt = &item->option;
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
translation_domain = (const char *)opt->arg;
- else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
- cursor = singleTableUsage(f, cursor, opt->arg,
- translation_domain);
- else if ((opt->longName || opt->shortName) &&
- !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
- cursor = singleOptionUsage(f, cursor, opt, translation_domain);
-
- opt++;
+ } else if ((opt->longName || opt->shortName) &&
+ !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
+ cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
+ }
}
+ /*@=branchstate@*/
return cursor;
}
-static int showShortOptions(const struct poptOption * opt, FILE * f,
- char * str) {
- char s[300]; /* this is larger then the ascii set, so
- it should do just fine */
-
- s[0] = '\0';
- if (str == NULL) {
- memset(s, 0, sizeof(s));
- str = s;
+/**
+ * Keep track of option tables already processed.
+ */
+typedef struct poptDone_s {
+ int nopts;
+ int maxopts;
+ const void ** opts;
+} * poptDone;
+
+/**
+ * Display usage text for a table of options.
+ * @param con context
+ * @param fp output file handle
+ * @param cursor
+ * @param opt option(s)
+ * @param translation_domain translation domain
+ * @param done tables already processed
+ * @return
+ */
+static int singleTableUsage(poptContext con, FILE * fp, int cursor,
+ /*@null@*/ const struct poptOption * opt,
+ /*@null@*/ const char * translation_domain,
+ /*@null@*/ poptDone done)
+ /*@globals fileSystem @*/
+ /*@modifies *fp, done, fileSystem @*/
+{
+ /*@-branchstate@*/ /* FIX: W2DO? */
+ if (opt != NULL)
+ for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
+ translation_domain = (const char *)opt->arg;
+ } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
+ if (done) {
+ int i = 0;
+ for (i = 0; i < done->nopts; i++) {
+/*@-boundsread@*/
+ const void * that = done->opts[i];
+/*@=boundsread@*/
+ if (that == NULL || that != opt->arg)
+ /*@innercontinue@*/ continue;
+ /*@innerbreak@*/ break;
+ }
+ /* Skip if this table has already been processed. */
+ if (opt->arg == NULL || i < done->nopts)
+ continue;
+/*@-boundswrite@*/
+ if (done->nopts < done->maxopts)
+ done->opts[done->nopts++] = (const void *) opt->arg;
+/*@=boundswrite@*/
+ }
+ cursor = singleTableUsage(con, fp, cursor, opt->arg,
+ translation_domain, done);
+ } else if ((opt->longName || opt->shortName) &&
+ !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
+ cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
+ }
}
+ /*@=branchstate@*/
- while (opt->longName || opt->shortName || opt->arg) {
+ return cursor;
+}
+
+/**
+ * Return concatenated short options for display.
+ * @todo Sub-tables should be recursed.
+ * @param opt option(s)
+ * @param fp output file handle
+ * @retval str concatenation of short options
+ * @return length of display string
+ */
+static int showShortOptions(const struct poptOption * opt, FILE * fp,
+ /*@null@*/ char * str)
+ /*@globals fileSystem @*/
+ /*@modifies *str, *fp, fileSystem @*/
+ /*@requires maxRead(str) >= 0 @*/
+{
+ /* bufsize larger then the ascii set, lazy alloca on top level call. */
+ char * s = (str != NULL ? str : memset(alloca(300), 0, 300));
+ int len = 0;
+
+/*@-boundswrite@*/
+ if (opt != NULL)
+ for (; (opt->longName || opt->shortName || opt->arg); opt++) {
if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
- str[strlen(str)] = opt->shortName;
+ s[strlen(s)] = opt->shortName;
else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
- showShortOptions(opt->arg, f, str);
-
- opt++;
+ if (opt->arg) /* XXX program error */
+ len = showShortOptions(opt->arg, fp, s);
}
+/*@=boundswrite@*/
- if (s != str || !*s)
- return 0;
-
- fprintf(f, " [-%s]", s);
- return strlen(s) + 4;
+ /* On return to top level, print the short options, return print length. */
+ if (s == str && *s != '\0') {
+ fprintf(fp, " [-%s]", s);
+ len = strlen(s) + sizeof(" [-]")-1;
+ }
+ return len;
}
-void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int flags) {
+void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
+{
+ poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done));
int cursor;
- cursor = showHelpIntro(con, f);
- cursor += showShortOptions(con->options, f, NULL);
- singleTableUsage(f, cursor, con->options, NULL);
+ done->nopts = 0;
+ done->maxopts = 64;
+ cursor = done->maxopts * sizeof(*done->opts);
+/*@-boundswrite@*/
+ done->opts = memset(alloca(cursor), 0, cursor);
+ done->opts[done->nopts++] = (const void *) con->options;
+/*@=boundswrite@*/
+
+ cursor = showHelpIntro(con, fp);
+ cursor += showShortOptions(con->options, fp, NULL);
+ cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done);
+ cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
+ cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
if (con->otherHelp) {
cursor += strlen(con->otherHelp) + 1;
- if (cursor > 79) fprintf(f, "\n ");
- fprintf(f, " %s", con->otherHelp);
+ if (cursor > 79) fprintf(fp, "\n ");
+ fprintf(fp, " %s", con->otherHelp);
}
- fprintf(f, "\n");
+ fprintf(fp, "\n");
}
-void poptSetOtherOptionHelp(poptContext con, const char * text) {
- if (con->otherHelp) xfree(con->otherHelp);
+void poptSetOtherOptionHelp(poptContext con, const char * text)
+{
+ con->otherHelp = _free(con->otherHelp);
con->otherHelp = xstrdup(text);
}
+/*@=type@*/
diff --git a/source/popt/poptint.h b/source/popt/poptint.h
index 1847ffafe67..5d308efe96a 100644
--- a/source/popt/poptint.h
+++ b/source/popt/poptint.h
@@ -1,71 +1,116 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/poptint.h
+ */
+
+/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#ifndef H_POPTINT
#define H_POPTINT
+/**
+ * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
+ * @param p memory to free
+ * @retval NULL always
+ */
+/*@unused@*/ static inline /*@null@*/ void *
+_free(/*@only@*/ /*@null@*/ const void * p)
+ /*@modifies p @*/
+{
+ if (p != NULL) free((void *)p);
+ return NULL;
+}
+
/* Bit mask macros. */
+/*@-exporttype -redef @*/
typedef unsigned int __pbm_bits;
+/*@=exporttype =redef @*/
#define __PBM_NBITS (8 * sizeof (__pbm_bits))
#define __PBM_IX(d) ((d) / __PBM_NBITS)
-#define __PBM_MASK(d) ((__pbm_bits) 1 << ((d) % __PBM_NBITS))
+#define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS))
+/*@-exporttype -redef @*/
typedef struct {
__pbm_bits bits[1];
} pbm_set;
+/*@=exporttype =redef @*/
#define __PBM_BITS(set) ((set)->bits)
#define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits))
-#define PBM_FREE(s) free(s);
+#define PBM_FREE(s) _free(s);
#define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d))
#define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d))
#define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0)
struct optionStackEntry {
int argc;
- /*@only@*/ const char ** argv;
- /*@only@*/ pbm_set * argb;
+/*@only@*/ /*@null@*/
+ const char ** argv;
+/*@only@*/ /*@null@*/
+ pbm_set * argb;
int next;
- /*@only@*/ const char * nextArg;
- /*@keep@*/ const char * nextCharArg;
- /*@dependent@*/ struct poptAlias * currAlias;
+/*@only@*/ /*@null@*/
+ const char * nextArg;
+/*@observer@*/ /*@null@*/
+ const char * nextCharArg;
+/*@dependent@*/ /*@null@*/
+ poptItem currAlias;
int stuffed;
};
-struct execEntry {
- const char * longName;
- char shortName;
- const char * script;
-};
-
struct poptContext_s {
struct optionStackEntry optionStack[POPT_OPTION_DEPTH];
- /*@dependent@*/ struct optionStackEntry * os;
- /*@owned@*/ const char ** leftovers;
+/*@dependent@*/
+ struct optionStackEntry * os;
+/*@owned@*/ /*@null@*/
+ const char ** leftovers;
int numLeftovers;
int nextLeftover;
- /*@keep@*/ const struct poptOption * options;
+/*@keep@*/
+ const struct poptOption * options;
int restLeftover;
- /*@only@*/ const char * appName;
- /*@only@*/ struct poptAlias * aliases;
+/*@only@*/ /*@null@*/
+ const char * appName;
+/*@only@*/ /*@null@*/
+ poptItem aliases;
int numAliases;
int flags;
- struct execEntry * execs;
+/*@owned@*/ /*@null@*/
+ poptItem execs;
int numExecs;
- /*@only@*/ const char ** finalArgv;
+/*@only@*/ /*@null@*/
+ const char ** finalArgv;
int finalArgvCount;
int finalArgvAlloced;
- /*@dependent@*/ struct execEntry * doExec;
- /*@only@*/ const char * execPath;
+/*@dependent@*/ /*@null@*/
+ poptItem doExec;
+/*@only@*/
+ const char * execPath;
int execAbsolute;
- /*@only@*/ const char * otherHelp;
+/*@only@*/
+ const char * otherHelp;
+/*@null@*/
pbm_set * arg_strip;
};
-#define xfree(_a) free((void *)_a)
+#ifdef HAVE_LIBINTL_H
+#include <libintl.h>
+#endif
+
+#if defined(HAVE_GETTEXT) && !defined(__LCLINT__)
+#define _(foo) gettext(foo)
+#else
+#define _(foo) foo
+#endif
+
+#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
+#define D_(dom, str) dgettext(dom, str)
+#define POPT_(foo) D_("popt", foo)
+#else
+#define D_(dom, str) str
+#define POPT_(foo) foo
+#endif
-#define POPT_(foo) (foo)
-#define D_(dom, str) (str)
-#define N_(foo) (foo)
+#define N_(foo) foo
#endif
diff --git a/source/popt/poptparse.c b/source/popt/poptparse.c
index 8f00769be9f..537ec443981 100644
--- a/source/popt/poptparse.c
+++ b/source/popt/poptparse.c
@@ -1,11 +1,16 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/poptparse.c
+ */
+
+/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
file accompanying popt source distributions, available from
- ftp://ftp.redhat.com/pub/code/popt */
+ ftp://ftp.rpm.org/pub/rpm/dist. */
#include "system.h"
#define POPT_ARGV_ARRAY_GROW_DELTA 5
+/*@-boundswrite@*/
int poptDupArgv(int argc, const char **argv,
int * argcPtr, const char *** argvPtr)
{
@@ -14,6 +19,8 @@ int poptDupArgv(int argc, const char **argv,
char * dst;
int i;
+ if (argc <= 0 || argv == NULL) /* XXX can't happen */
+ return POPT_ERROR_NOARG;
for (i = 0; i < argc; i++) {
if (argv[i] == NULL)
return POPT_ERROR_NOARG;
@@ -21,20 +28,32 @@ int poptDupArgv(int argc, const char **argv,
}
dst = malloc(nb);
+ if (dst == NULL) /* XXX can't happen */
+ return POPT_ERROR_MALLOC;
argv2 = (void *) dst;
dst += (argc + 1) * sizeof(*argv);
+ /*@-branchstate@*/
for (i = 0; i < argc; i++) {
argv2[i] = dst;
dst += strlen(strcpy(dst, argv[i])) + 1;
}
+ /*@=branchstate@*/
argv2[argc] = NULL;
- *argvPtr = argv2;
- *argcPtr = argc;
+ if (argvPtr) {
+ *argvPtr = argv2;
+ } else {
+ free(argv2);
+ argv2 = NULL;
+ }
+ if (argcPtr)
+ *argcPtr = argc;
return 0;
}
+/*@=boundswrite@*/
+/*@-bounds@*/
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
{
const char * src;
@@ -43,31 +62,32 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
int argc = 0;
int buflen = strlen(s) + 1;
- char *buf0 = calloc(buflen, 1);
- char *buf = buf0;
+ char * buf = memset(alloca(buflen), 0, buflen);
+ int rc = POPT_ERROR_MALLOC;
+ if (argv == NULL) return rc;
argv[argc] = buf;
- for (src = s; *src; src++) {
+ for (src = s; *src != '\0'; src++) {
if (quote == *src) {
quote = '\0';
- } else if (quote) {
+ } else if (quote != '\0') {
if (*src == '\\') {
src++;
if (!*src) {
- free(argv);
- free(buf0);
- return POPT_ERROR_BADQUOTE;
+ rc = POPT_ERROR_BADQUOTE;
+ goto exit;
}
if (*src != quote) *buf++ = '\\';
}
*buf++ = *src;
} else if (isspace(*src)) {
- if (*argv[argc]) {
+ if (*argv[argc] != '\0') {
buf++, argc++;
if (argc == argvAlloced) {
argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
argv = realloc(argv, sizeof(*argv) * argvAlloced);
+ if (argv == NULL) goto exit;
}
argv[argc] = buf;
}
@@ -75,18 +95,17 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
case '"':
case '\'':
quote = *src;
- break;
+ /*@switchbreak@*/ break;
case '\\':
src++;
if (!*src) {
- free(argv);
- free(buf0);
- return POPT_ERROR_BADQUOTE;
+ rc = POPT_ERROR_BADQUOTE;
+ goto exit;
}
/*@fallthrough@*/
default:
*buf++ = *src;
- break;
+ /*@switchbreak@*/ break;
}
}
@@ -94,9 +113,115 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
argc++, buf++;
}
- (void) poptDupArgv(argc, argv, argcPtr, argvPtr);
+ rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
+
+exit:
+ if (argv) free(argv);
+ return rc;
+}
+/*@=bounds@*/
+
+/* still in the dev stage.
+ * return values, perhaps 1== file erro
+ * 2== line to long
+ * 3== umm.... more?
+ */
+int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ int flags)
+{
+ char line[999];
+ char * argstr;
+ char * p;
+ char * q;
+ char * x;
+ int t;
+ int argvlen = 0;
+ size_t maxlinelen = sizeof(line);
+ size_t linelen;
+ int maxargvlen = 480;
+ int linenum = 0;
+
+ *argstrp = NULL;
+
+ /* | this_is = our_line
+ * p q x
+ */
+
+ if (fp == NULL)
+ return POPT_ERROR_NULLARG;
+
+ argstr = calloc(maxargvlen, sizeof(*argstr));
+ if (argstr == NULL) return POPT_ERROR_MALLOC;
+
+ while (fgets(line, (int)maxlinelen, fp) != NULL) {
+ linenum++;
+ p = line;
+
+ /* loop until first non-space char or EOL */
+ while( *p != '\0' && isspace(*p) )
+ p++;
+
+ linelen = strlen(p);
+ if (linelen >= maxlinelen-1)
+ return POPT_ERROR_OVERFLOW; /* XXX line too long */
+
+ if (*p == '\0' || *p == '\n') continue; /* line is empty */
+ if (*p == '#') continue; /* comment line */
+
+ q = p;
+
+ while (*q != '\0' && (!isspace(*q)) && *q != '=')
+ q++;
+
+ if (isspace(*q)) {
+ /* a space after the name, find next non space */
+ *q++='\0';
+ while( *q != '\0' && isspace((int)*q) ) q++;
+ }
+ if (*q == '\0') {
+ /* single command line option (ie, no name=val, just name) */
+ q[-1] = '\0'; /* kill off newline from fgets() call */
+ argvlen += (t = q - p) + (sizeof(" --")-1);
+ if (argvlen >= maxargvlen) {
+ maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
+ argstr = realloc(argstr, maxargvlen);
+ if (argstr == NULL) return POPT_ERROR_MALLOC;
+ }
+ strcat(argstr, " --");
+ strcat(argstr, p);
+ continue;
+ }
+ if (*q != '=')
+ continue; /* XXX for now, silently ignore bogus line */
+
+ /* *q is an equal sign. */
+ *q++ = '\0';
+
+ /* find next non-space letter of value */
+ while (*q != '\0' && isspace(*q))
+ q++;
+ if (*q == '\0')
+ continue; /* XXX silently ignore missing value */
+
+ /* now, loop and strip all ending whitespace */
+ x = p + linelen;
+ while (isspace(*--x))
+ *x = 0; /* null out last char if space (including fgets() NL) */
+
+ /* rest of line accept */
+ t = x - p;
+ argvlen += t + (sizeof("' --='")-1);
+ if (argvlen >= maxargvlen) {
+ maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
+ argstr = realloc(argstr, maxargvlen);
+ if (argstr == NULL) return POPT_ERROR_MALLOC;
+ }
+ strcat(argstr, " --");
+ strcat(argstr, p);
+ strcat(argstr, "=\"");
+ strcat(argstr, q);
+ strcat(argstr, "\"");
+ }
- free(argv);
- free(buf0);
+ *argstrp = argstr;
return 0;
}
diff --git a/source/popt/system.h b/source/popt/system.h
index 059c0458176..1d1b9dae887 100644
--- a/source/popt/system.h
+++ b/source/popt/system.h
@@ -1,6 +1,18 @@
+#ifdef HAVE_CONFIG_H
#include "config.h"
+#endif
+
+#if defined (__GLIBC__) && defined(__LCLINT__)
+/*@-declundef@*/
+/*@unchecked@*/
+extern __const __int32_t *__ctype_tolower;
+/*@unchecked@*/
+extern __const __int32_t *__ctype_toupper;
+/*@=declundef@*/
+#endif
#include <ctype.h>
+
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -23,6 +35,14 @@
#include <libc.h>
#endif
+#if defined(__LCLINT__)
+/*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */
+/*@only@*/ void * alloca (size_t __size)
+ /*@ensures MaxSet(result) == (__size - 1) @*/
+ /*@*/;
+/*@=declundef =incondefs =redecl@*/
+#endif
+
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
@@ -40,7 +60,10 @@ char *alloca ();
#define alloca __builtin_alloca
#endif
-/*@only@*/ char * xstrdup (const char *str);
+/*@-redecl -redef@*/
+/*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str)
+ /*@*/;
+/*@=redecl =redef@*/
#if HAVE_MCHECK_H && defined(__GNUC__)
#define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL)
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 1a664fbb34e..79061ebd416 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -2298,18 +2298,14 @@ static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
uint32 del_a_printer(const char *sharename)
{
- pstring key;
TDB_DATA kbuf;
pstring printdb_path;
- slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
- kbuf.dptr=key;
- kbuf.dsize=strlen(key)+1;
+ kbuf = make_printer_tdbkey( sharename );
tdb_delete(tdb_printers, kbuf);
- slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
- kbuf.dptr=key;
- kbuf.dsize=strlen(key)+1;
+ kbuf.dptr = make_printers_secdesc_tdbkey( sharename );
+ kbuf.dsize = strlen(kbuf.dptr) + 1;
tdb_delete(tdb_printers, kbuf);
close_all_print_db();
@@ -3024,8 +3020,19 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
/* build the ads mods */
ctx = talloc_init("nt_printer_publish_ads");
+ if (ctx == NULL) {
+ SAFE_FREE(prt_dn);
+ return WERR_NOMEM;
+ }
+
mods = ads_init_mods(ctx);
+ if (mods == NULL) {
+ SAFE_FREE(prt_dn);
+ talloc_destroy(ctx);
+ return WERR_NOMEM;
+ }
+
get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
printer->info_2->sharename);
@@ -3162,7 +3169,7 @@ WERROR check_published_printers(void)
int n_services = lp_numservices();
NT_PRINTER_INFO_LEVEL *printer = NULL;
- ads = ads_init(NULL, NULL, NULL);
+ ads = ads_init(lp_realm(), lp_workgroup(), NULL);
if (!ads) {
DEBUG(3, ("ads_init() failed\n"));
return WERR_SERVER_UNAVAILABLE;
diff --git a/source/profile/profile.c b/source/profile/profile.c
index 838383b1afe..ba9596301c6 100644
--- a/source/profile/profile.c
+++ b/source/profile/profile.c
@@ -28,6 +28,9 @@
#ifdef WITH_PROFILE
static int shm_id;
static BOOL read_only;
+#if defined(HAVE_CLOCK_GETTIME)
+clockid_t __profile_clock;
+#endif
#endif
struct profile_header *profile_h;
@@ -36,11 +39,6 @@ struct profile_stats *profile_p;
BOOL do_profile_flag = False;
BOOL do_profile_times = False;
-struct timeval profile_starttime;
-struct timeval profile_endtime;
-struct timeval profile_starttime_nested;
-struct timeval profile_endtime_nested;
-
/****************************************************************************
receive a set profile level message
****************************************************************************/
@@ -108,6 +106,24 @@ BOOL profile_setup(BOOL rdonly)
read_only = rdonly;
+#if defined(HAVE_CLOCK_GETTIME)
+ if (this_is_smp()) {
+ /* This is faster that gettimeofday, but not fast enough to
+ * leave it enabled in production.
+ */
+ __profile_clock = CLOCK_MONOTONIC;
+ } else {
+ /* CLOCK_PROCESS_CPUTIME_ID is sufficiently fast that the
+ * always profiling times is plausible. Unfortunately it is
+ * only accurate if we can guarantee we will not be scheduled
+ * onto a different CPU between samples. Until there is some
+ * way to set processor affinity, we can only use this on
+ * uniprocessors.
+ */
+ __profile_clock = CLOCK_PROCESS_CPUTIME_ID;
+ }
+#endif
+
again:
/* try to use an existing key */
shm_id = shmget(PROF_SHMEM_KEY, 0, 0);
@@ -142,8 +158,12 @@ BOOL profile_setup(BOOL rdonly)
return False;
}
- if (shm_ds.shm_perm.cuid != sec_initial_uid() || shm_ds.shm_perm.cgid != sec_initial_gid()) {
- DEBUG(0,("ERROR: we did not create the shmem (owned by another user)\n"));
+ if (shm_ds.shm_perm.cuid != sec_initial_uid() ||
+ shm_ds.shm_perm.cgid != sec_initial_gid()) {
+ DEBUG(0,("ERROR: we did not create the shmem "
+ "(owned by another user, uid %u, gid %u)\n",
+ shm_ds.shm_perm.cuid,
+ shm_ds.shm_perm.cgid));
return False;
}
diff --git a/source/python/py_common.c b/source/python/py_common.c
index 70d478b9797..14c3b83e547 100644
--- a/source/python/py_common.c
+++ b/source/python/py_common.c
@@ -45,6 +45,8 @@ void py_samba_init(void)
if (initialised)
return;
+ load_case_tables();
+
/* Load configuration file */
if (!lp_load(dyn_CONFIGFILE, True, False, False, True))
@@ -212,6 +214,7 @@ struct cli_state *open_pipe_creds(char *server, PyObject *creds,
{
char *username, *password, *domain;
struct cli_state *cli;
+ struct rpc_pipe_client *pipe_hnd;
NTSTATUS result;
/* Extract credentials from the python dictionary */
@@ -230,7 +233,8 @@ struct cli_state *open_pipe_creds(char *server, PyObject *creds,
return NULL;
}
- if (!cli_nt_session_open(cli, pipe_idx)) {
+ pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &result);
+ if (!pipe_hnd) {
cli_shutdown(cli);
asprintf(errstr, "error opening pipe index %d", pipe_idx);
return NULL;
diff --git a/source/python/py_lsa.c b/source/python/py_lsa.c
index a4e8254e0d1..915223a5bb7 100644
--- a/source/python/py_lsa.c
+++ b/source/python/py_lsa.c
@@ -20,7 +20,7 @@
#include "python/py_lsa.h"
-PyObject *new_lsa_policy_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+PyObject *new_lsa_policy_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol)
{
lsa_policy_hnd_object *o;
@@ -90,14 +90,14 @@ static PyObject *lsa_open_policy(PyObject *self, PyObject *args,
}
ntstatus = rpccli_lsa_open_policy(
- cli, mem_ctx, True, desired_access, &hnd);
+ cli->pipe_list, mem_ctx, True, desired_access, &hnd);
if (!NT_STATUS_IS_OK(ntstatus)) {
PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus));
goto done;
}
- result = new_lsa_policy_hnd_object(cli, mem_ctx, &hnd);
+ result = new_lsa_policy_hnd_object(cli->pipe_list, mem_ctx, &hnd);
done:
if (!result) {
diff --git a/source/python/py_lsa.h b/source/python/py_lsa.h
index 99f3de50b1f..44a0b37b35a 100644
--- a/source/python/py_lsa.h
+++ b/source/python/py_lsa.h
@@ -27,7 +27,7 @@
typedef struct {
PyObject_HEAD
- struct cli_state *cli;
+ struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx;
POLICY_HND pol;
} lsa_policy_hnd_object;
diff --git a/source/python/py_samr.c b/source/python/py_samr.c
index a26cd8d132e..fced5b3ddd8 100644
--- a/source/python/py_samr.c
+++ b/source/python/py_samr.c
@@ -283,7 +283,7 @@ PyTypeObject samr_user_hnd_type = {
0, /*tp_hash */
};
-PyObject *new_samr_user_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+PyObject *new_samr_user_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol)
{
samr_user_hnd_object *o;
@@ -304,7 +304,7 @@ static void py_samr_connect_hnd_dealloc(PyObject* self)
PyObject_Del(self);
}
-PyObject *new_samr_domain_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+PyObject *new_samr_domain_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol)
{
samr_domain_hnd_object *o;
@@ -396,7 +396,7 @@ PyTypeObject samr_connect_hnd_type = {
0, /*tp_hash */
};
-PyObject *new_samr_connect_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+PyObject *new_samr_connect_hnd_object(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol)
{
samr_connect_hnd_object *o;
@@ -569,7 +569,7 @@ static PyObject *samr_connect(PyObject *self, PyObject *args, PyObject *kw)
goto done;
}
- ntstatus = rpccli_samr_connect(cli, mem_ctx, desired_access, &hnd);
+ ntstatus = rpccli_samr_connect(cli->pipe_list, mem_ctx, desired_access, &hnd);
if (!NT_STATUS_IS_OK(ntstatus)) {
cli_shutdown(cli);
@@ -577,7 +577,7 @@ static PyObject *samr_connect(PyObject *self, PyObject *args, PyObject *kw)
goto done;
}
- result = new_samr_connect_hnd_object(cli, mem_ctx, &hnd);
+ result = new_samr_connect_hnd_object(cli->pipe_list, mem_ctx, &hnd);
done:
if (!result) {
diff --git a/source/python/py_samr.h b/source/python/py_samr.h
index 8e91b1671ec..9cde99e2d04 100644
--- a/source/python/py_samr.h
+++ b/source/python/py_samr.h
@@ -27,7 +27,7 @@
typedef struct {
PyObject_HEAD
- struct cli_state *cli;
+ struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx;
POLICY_HND connect_pol;
} samr_connect_hnd_object;
@@ -36,7 +36,7 @@ typedef struct {
typedef struct {
PyObject_HEAD
- struct cli_state *cli;
+ struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx;
POLICY_HND domain_pol;
} samr_domain_hnd_object;
@@ -45,7 +45,7 @@ typedef struct {
typedef struct {
PyObject_HEAD
- struct cli_state *cli;
+ struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx;
POLICY_HND user_pol;
} samr_user_hnd_object;
diff --git a/source/python/py_spoolss_drivers.c b/source/python/py_spoolss_drivers.c
index 3d7ca3a8fc7..1ececf1e377 100644
--- a/source/python/py_spoolss_drivers.c
+++ b/source/python/py_spoolss_drivers.c
@@ -70,7 +70,7 @@ PyObject *spoolss_enumprinterdrivers(PyObject *self, PyObject *args,
}
werror = rpccli_spoolss_enumprinterdrivers(
- cli, mem_ctx, level, arch,
+ cli->pipe_list, mem_ctx, level, arch,
&num_drivers, &ctr);
if (!W_ERROR_IS_OK(werror)) {
@@ -263,7 +263,7 @@ PyObject *spoolss_getprinterdriverdir(PyObject *self, PyObject *args,
}
werror = rpccli_spoolss_getprinterdriverdir(
- cli, mem_ctx, level, arch, &ctr);
+ cli->pipe_list, mem_ctx, level, arch, &ctr);
if (!W_ERROR_IS_OK(werror)) {
PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
@@ -361,7 +361,7 @@ PyObject *spoolss_addprinterdriver(PyObject *self, PyObject *args,
goto done;
}
- werror = rpccli_spoolss_addprinterdriver(cli, mem_ctx, level, &ctr);
+ werror = rpccli_spoolss_addprinterdriver(cli->pipe_list, mem_ctx, level, &ctr);
if (!W_ERROR_IS_OK(werror)) {
PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
diff --git a/source/python/py_spoolss_ports.c b/source/python/py_spoolss_ports.c
index 721ac956eb4..96b81589f9e 100644
--- a/source/python/py_spoolss_ports.c
+++ b/source/python/py_spoolss_ports.c
@@ -68,7 +68,7 @@ PyObject *spoolss_enumports(PyObject *self, PyObject *args, PyObject *kw)
/* Call rpc function */
werror = rpccli_spoolss_enum_ports(
- cli, mem_ctx, level, &num_ports, &ctr);
+ cli->pipe_list, mem_ctx, level, &num_ports, &ctr);
if (!W_ERROR_IS_OK(werror)) {
PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
diff --git a/source/python/py_spoolss_printerdata.c b/source/python/py_spoolss_printerdata.c
index 195f01f62d8..ed9e1cbd82d 100644
--- a/source/python/py_spoolss_printerdata.c
+++ b/source/python/py_spoolss_printerdata.c
@@ -315,11 +315,16 @@ PyObject *spoolss_hnd_enumprinterdataex(PyObject *self, PyObject *args, PyObject
char *key;
WERROR werror;
PyObject *result;
- REGVAL_CTR ctr;
+ REGVAL_CTR *ctr;
if (!PyArg_ParseTupleAndKeywords(args, kw, "s", kwlist, &key))
return NULL;
+ if (!(ctr = TALLOC_ZERO_P(hnd->mem_ctx, REGVAL_CTR))) {
+ PyErr_SetString(spoolss_error, "talloc failed");
+ return NULL;
+ }
+
/* Get max buffer sizes for value and data */
werror = rpccli_spoolss_enumprinterdataex(
diff --git a/source/python/py_spoolss_printers.c b/source/python/py_spoolss_printers.c
index 50c19fcf045..25cd051f3cc 100644
--- a/source/python/py_spoolss_printers.c
+++ b/source/python/py_spoolss_printers.c
@@ -69,7 +69,7 @@ PyObject *spoolss_openprinter(PyObject *self, PyObject *args, PyObject *kw)
}
werror = rpccli_spoolss_open_printer_ex(
- cli, mem_ctx, unc_name, "", desired_access, server,
+ cli->pipe_list, mem_ctx, unc_name, "", desired_access, server,
"", &hnd);
if (!W_ERROR_IS_OK(werror)) {
@@ -327,7 +327,7 @@ PyObject *spoolss_enumprinters(PyObject *self, PyObject *args, PyObject *kw)
/* Call rpc function */
werror = rpccli_spoolss_enum_printers(
- cli, mem_ctx, name, flags, level, &num_printers, &ctr);
+ cli->pipe_list, mem_ctx, name, flags, level, &num_printers, &ctr);
if (!W_ERROR_IS_OK(werror)) {
PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
@@ -448,7 +448,7 @@ PyObject *spoolss_addprinterex(PyObject *self, PyObject *args, PyObject *kw)
ctr.printers_2 = &info2;
- werror = rpccli_spoolss_addprinterex(cli, mem_ctx, 2, &ctr);
+ werror = rpccli_spoolss_addprinterex(cli->pipe_list, mem_ctx, 2, &ctr);
Py_INCREF(Py_None);
result = Py_None;
diff --git a/source/python/py_srvsvc.c b/source/python/py_srvsvc.c
index 567572a9e5c..03ed7fd84b1 100644
--- a/source/python/py_srvsvc.c
+++ b/source/python/py_srvsvc.c
@@ -120,7 +120,7 @@ PyObject *srvsvc_netservergetinfo(PyObject *self, PyObject *args,
ZERO_STRUCT(ctr);
- status = rpccli_srvsvc_net_srv_get_info(cli, mem_ctx, level, &ctr);
+ status = rpccli_srvsvc_net_srv_get_info(cli->pipe_list, mem_ctx, level, &ctr);
if (!NT_STATUS_IS_OK(status)) {
PyErr_SetObject(srvsvc_error, py_werror_tuple(status));
diff --git a/source/python/py_tdb.c b/source/python/py_tdb.c
index f73aa0ba8be..322d367eda4 100644
--- a/source/python/py_tdb.c
+++ b/source/python/py_tdb.c
@@ -494,7 +494,7 @@ PyObject *py_tdb_hnd_lock_bystring(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i", &s, &timeout))
return NULL;
- result = tdb_lock_bystring(obj->tdb, s, timeout);
+ result = tdb_lock_bystring_with_timeout(obj->tdb, s, timeout);
return PyInt_FromLong(result != -1);
}
diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c
index 07b876cc22c..1da7a47ea61 100644
--- a/source/rpc_client/cli_samr.c
+++ b/source/rpc_client/cli_samr.c
@@ -1102,15 +1102,57 @@ NTSTATUS rpccli_samr_query_dom_info(struct rpc_pipe_client *cli,
/* Marshall data and send request */
- init_samr_q_query_dom_info(&q, domain_pol, switch_value);
+ init_samr_q_query_domain_info(&q, domain_pol, switch_value);
r.ctr = ctr;
CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DOMAIN_INFO,
q, r,
qbuf, rbuf,
- samr_io_q_query_dom_info,
- samr_io_r_query_dom_info,
+ samr_io_q_query_domain_info,
+ samr_io_r_query_domain_info,
+ NT_STATUS_UNSUCCESSFUL);
+
+ /* Return output parameters */
+
+ if (!NT_STATUS_IS_OK(result = r.status)) {
+ goto done;
+ }
+
+ done:
+
+ return result;
+}
+
+/* Query domain info2 */
+
+NTSTATUS rpccli_samr_query_dom_info2(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_QUERY_DOMAIN_INFO2 q;
+ SAMR_R_QUERY_DOMAIN_INFO2 r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DEBUG(10,("cli_samr_query_dom_info2\n"));
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Marshall data and send request */
+
+ init_samr_q_query_domain_info2(&q, domain_pol, switch_value);
+
+ r.ctr = ctr;
+
+ CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DOMAIN_INFO2,
+ q, r,
+ qbuf, rbuf,
+ samr_io_q_query_domain_info2,
+ samr_io_r_query_domain_info2,
NT_STATUS_UNSUCCESSFUL);
/* Return output parameters */
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 05c75fe98a4..027d5fba857 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -461,10 +461,10 @@ BOOL samr_io_q_query_sec_obj(const char *desc, SAMR_Q_QUERY_SEC_OBJ * q_u,
reads or writes a structure.
********************************************************************/
-void init_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u,
- POLICY_HND *domain_pol, uint16 switch_value)
+void init_samr_q_query_domain_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u,
+ POLICY_HND *domain_pol, uint16 switch_value)
{
- DEBUG(5, ("samr_init_samr_q_query_dom_info\n"));
+ DEBUG(5, ("samr_init_samr_q_query_domain_info\n"));
q_u->domain_pol = *domain_pol;
q_u->switch_value = switch_value;
@@ -474,13 +474,13 @@ void init_samr_q_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO * q_u,
reads or writes a structure.
********************************************************************/
-BOOL samr_io_q_query_dom_info(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u,
- prs_struct *ps, int depth)
+BOOL samr_io_q_query_domain_info(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u,
+ prs_struct *ps, int depth)
{
if (q_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_q_query_dom_info");
+ prs_debug(ps, depth, desc, "samr_io_q_query_domain_info");
depth++;
if(!prs_align(ps))
@@ -495,31 +495,53 @@ BOOL samr_io_q_query_dom_info(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO * q_u,
return True;
}
-
/*******************************************************************
inits a structure.
********************************************************************/
-void init_unk_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout)
+void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist,
+ uint32 password_properties, NTTIME nt_expire, NTTIME nt_min_age)
{
- u_3->logout.low = nt_logout.low;
- u_3->logout.high = nt_logout.high;
+ u_1->min_length_password = min_pass_len;
+ u_1->password_history = pass_hist;
+
+ if (lp_check_password_script() && *lp_check_password_script()) {
+ password_properties |= DOMAIN_PASSWORD_COMPLEX;
+ }
+ u_1->password_properties = password_properties;
+
+ /* password never expire */
+ u_1->expire.high = nt_expire.high;
+ u_1->expire.low = nt_expire.low;
+
+ /* can change the password now */
+ u_1->min_passwordage.high = nt_min_age.high;
+ u_1->min_passwordage.low = nt_min_age.low;
+
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info3(const char *desc, SAM_UNK_INFO_3 * u_3,
+static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
prs_struct *ps, int depth)
{
- if (u_3 == NULL)
- return False;
+ if (u_1 == NULL)
+ return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info3");
+ prs_debug(ps, depth, desc, "sam_io_unk_info1");
depth++;
- if(!smb_io_time("logout", &u_3->logout, ps, depth))
+ if(!prs_uint16("min_length_password", ps, depth, &u_1->min_length_password))
+ return False;
+ if(!prs_uint16("password_history", ps, depth, &u_1->password_history))
+ return False;
+ if(!prs_uint32("password_properties", ps, depth, &u_1->password_properties))
+ return False;
+ if(!smb_io_time("expire", &u_1->expire, ps, depth))
+ return False;
+ if(!smb_io_time("min_passwordage", &u_1->min_passwordage, ps, depth))
return False;
return True;
@@ -529,31 +551,79 @@ static BOOL sam_io_unk_info3(const char *desc, SAM_UNK_INFO_3 * u_3,
inits a structure.
********************************************************************/
-void init_unk_info6(SAM_UNK_INFO_6 * u_6)
+void init_unk_info2(SAM_UNK_INFO_2 * u_2,
+ const char *comment, const char *domain, const char *server,
+ uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias, NTTIME nt_logout, uint32 server_role)
{
- u_6->unknown_0 = 0x00000000;
- u_6->ptr_0 = 1;
- memset(u_6->padding, 0, sizeof(u_6->padding)); /* 12 bytes zeros */
+ u_2->logout.low = nt_logout.low;
+ u_2->logout.high = nt_logout.high;
+
+ u_2->seq_num.low = seq_num;
+ u_2->seq_num.high = 0x00000000;
+
+
+ u_2->unknown_4 = 0x00000001;
+ u_2->server_role = server_role;
+ u_2->unknown_6 = 0x00000001;
+ u_2->num_domain_usrs = num_users;
+ u_2->num_domain_grps = num_groups;
+ u_2->num_local_grps = num_alias;
+
+ init_unistr2(&u_2->uni_comment, comment, UNI_FLAGS_NONE);
+ init_uni_hdr(&u_2->hdr_comment, &u_2->uni_comment);
+ init_unistr2(&u_2->uni_domain, domain, UNI_FLAGS_NONE);
+ init_uni_hdr(&u_2->hdr_domain, &u_2->uni_domain);
+ init_unistr2(&u_2->uni_server, server, UNI_FLAGS_NONE);
+ init_uni_hdr(&u_2->hdr_server, &u_2->uni_server);
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
+static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
prs_struct *ps, int depth)
{
- if (u_6 == NULL)
+ if (u_2 == NULL)
return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info6");
+ prs_debug(ps, depth, desc, "sam_io_unk_info2");
depth++;
- if(!prs_uint32("unknown_0", ps, depth, &u_6->unknown_0)) /* 0x0000 0000 */
+ if(!smb_io_time("logout", &u_2->logout, ps, depth))
+ return False;
+ if(!smb_io_unihdr("hdr_comment", &u_2->hdr_comment, ps, depth))
+ return False;
+ if(!smb_io_unihdr("hdr_domain", &u_2->hdr_domain, ps, depth))
+ return False;
+ if(!smb_io_unihdr("hdr_server", &u_2->hdr_server, ps, depth))
+ return False;
+
+ /* put all the data in here, at the moment, including what the above
+ pointer is referring to
+ */
+
+ if(!prs_uint64("seq_num ", ps, depth, &u_2->seq_num))
+ return False;
+
+ if(!prs_uint32("unknown_4 ", ps, depth, &u_2->unknown_4)) /* 0x0000 0001 */
return False;
- if(!prs_uint32("ptr_0", ps, depth, &u_6->ptr_0)) /* pointer to unknown structure */
+ if(!prs_uint32("server_role ", ps, depth, &u_2->server_role))
return False;
- if(!prs_uint8s(False, "padding", ps, depth, u_6->padding, sizeof(u_6->padding))) /* 12 bytes zeros */
+ if(!prs_uint32("unknown_6 ", ps, depth, &u_2->unknown_6)) /* 0x0000 0001 */
+ return False;
+ if(!prs_uint32("num_domain_usrs ", ps, depth, &u_2->num_domain_usrs))
+ return False;
+ if(!prs_uint32("num_domain_grps", ps, depth, &u_2->num_domain_grps))
+ return False;
+ if(!prs_uint32("num_local_grps", ps, depth, &u_2->num_local_grps))
+ return False;
+
+ if(!smb_io_unistr2("uni_comment", &u_2->uni_comment, u_2->hdr_comment.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_domain", &u_2->uni_domain, u_2->hdr_domain.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_server", &u_2->uni_server, u_2->hdr_server.buffer, ps, depth))
return False;
return True;
@@ -563,25 +633,26 @@ static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
inits a structure.
********************************************************************/
-void init_unk_info7(SAM_UNK_INFO_7 * u_7, uint32 server_role)
+void init_unk_info3(SAM_UNK_INFO_3 *u_3, NTTIME nt_logout)
{
- u_7->server_role = server_role;
+ u_3->logout.low = nt_logout.low;
+ u_3->logout.high = nt_logout.high;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
+static BOOL sam_io_unk_info3(const char *desc, SAM_UNK_INFO_3 * u_3,
prs_struct *ps, int depth)
{
- if (u_7 == NULL)
+ if (u_3 == NULL)
return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info7");
+ prs_debug(ps, depth, desc, "sam_io_unk_info3");
depth++;
- if(!prs_uint16("server_role", ps, depth, &u_7->server_role))
+ if(!smb_io_time("logout", &u_3->logout, ps, depth))
return False;
return True;
@@ -591,68 +662,61 @@ static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
inits a structure.
********************************************************************/
-void init_unk_info8(SAM_UNK_INFO_8 * u_8, uint32 seq_num)
+void init_unk_info4(SAM_UNK_INFO_4 * u_4,const char *comment)
{
- unix_to_nt_time(&u_8->domain_create_time, 0);
- u_8->seq_num.low = seq_num;
- u_8->seq_num.high = 0x0000;
+ init_unistr2(&u_4->uni_comment, comment, UNI_FLAGS_NONE);
+ init_uni_hdr(&u_4->hdr_comment, &u_4->uni_comment);
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info8(const char *desc, SAM_UNK_INFO_8 * u_8,
+static BOOL sam_io_unk_info4(const char *desc, SAM_UNK_INFO_4 * u_4,
prs_struct *ps, int depth)
{
- if (u_8 == NULL)
+ if (u_4 == NULL)
return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info8");
+ prs_debug(ps, depth, desc, "sam_io_unk_info4");
depth++;
- if (!prs_uint64("seq_num", ps, depth, &u_8->seq_num))
+ if(!smb_io_unihdr("hdr_comment", &u_4->hdr_comment, ps, depth))
return False;
- if(!smb_io_time("domain_create_time", &u_8->domain_create_time, ps, depth))
+ if(!smb_io_unistr2("uni_comment", &u_4->uni_comment, u_4->hdr_comment.buffer, ps, depth))
return False;
return True;
}
-
/*******************************************************************
inits a structure.
********************************************************************/
-void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout)
+void init_unk_info5(SAM_UNK_INFO_5 * u_5,const char *domain)
{
- u_12->duration.low = nt_lock_duration.low;
- u_12->duration.high = nt_lock_duration.high;
- u_12->reset_count.low = nt_reset_time.low;
- u_12->reset_count.high = nt_reset_time.high;
-
- u_12->bad_attempt_lockout = lockout;
+ init_unistr2(&u_5->uni_domain, domain, UNI_FLAGS_NONE);
+ init_uni_hdr(&u_5->hdr_domain, &u_5->uni_domain);
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12,
- prs_struct *ps, int depth)
+static BOOL sam_io_unk_info5(const char *desc, SAM_UNK_INFO_5 * u_5,
+ prs_struct *ps, int depth)
{
- if (u_12 == NULL)
+ if (u_5 == NULL)
return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info12");
+ prs_debug(ps, depth, desc, "sam_io_unk_info5");
depth++;
- if(!smb_io_time("duration", &u_12->duration, ps, depth))
+ if(!smb_io_unihdr("hdr_domain", &u_5->hdr_domain, ps, depth))
return False;
- if(!smb_io_time("reset_count", &u_12->reset_count, ps, depth))
- return False;
- if(!prs_uint16("bad_attempt_lockout", ps, depth, &u_12->bad_attempt_lockout))
+
+ if(!smb_io_unistr2("uni_domain", &u_5->uni_domain, u_5->hdr_domain.buffer, ps, depth))
return False;
return True;
@@ -662,29 +726,29 @@ static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12,
inits a structure.
********************************************************************/
-void init_unk_info5(SAM_UNK_INFO_5 * u_5,const char *server)
+void init_unk_info6(SAM_UNK_INFO_6 * u_6, const char *server)
{
- init_unistr2(&u_5->uni_server, server, UNI_FLAGS_NONE);
- init_uni_hdr(&u_5->hdr_server, &u_5->uni_server);
+ init_unistr2(&u_6->uni_server, server, UNI_FLAGS_NONE);
+ init_uni_hdr(&u_6->hdr_server, &u_6->uni_server);
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info5(const char *desc, SAM_UNK_INFO_5 * u_5,
+static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
prs_struct *ps, int depth)
{
- if (u_5 == NULL)
+ if (u_6 == NULL)
return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info5");
+ prs_debug(ps, depth, desc, "sam_io_unk_info6");
depth++;
- if(!smb_io_unihdr("hdr_server", &u_5->hdr_server, ps, depth))
+ if(!smb_io_unihdr("hdr_server", &u_6->hdr_server, ps, depth))
return False;
- if(!smb_io_unistr2("uni_server", &u_5->uni_server, u_5->hdr_server.buffer, ps, depth))
+ if(!smb_io_unistr2("uni_server", &u_6->uni_server, u_6->hdr_server.buffer, ps, depth))
return False;
return True;
@@ -694,81 +758,123 @@ static BOOL sam_io_unk_info5(const char *desc, SAM_UNK_INFO_5 * u_5,
inits a structure.
********************************************************************/
-void init_unk_info2(SAM_UNK_INFO_2 * u_2,
- const char *comment, const char *domain, const char *server,
- uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias, NTTIME nt_logout, uint32 server_role)
+void init_unk_info7(SAM_UNK_INFO_7 * u_7, uint32 server_role)
{
- u_2->logout.low = nt_logout.low;
- u_2->logout.high = nt_logout.high;
+ u_7->server_role = server_role;
+}
- u_2->seq_num.low = seq_num;
- u_2->seq_num.high = 0x00000000;
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
+ prs_struct *ps, int depth)
+{
+ if (u_7 == NULL)
+ return False;
- u_2->unknown_4 = 0x00000001;
- u_2->server_role = server_role;
- u_2->unknown_6 = 0x00000001;
- u_2->num_domain_usrs = num_users;
- u_2->num_domain_grps = num_groups;
- u_2->num_local_grps = num_alias;
+ prs_debug(ps, depth, desc, "sam_io_unk_info7");
+ depth++;
- memset(u_2->padding, 0, sizeof(u_2->padding)); /* 12 bytes zeros */
+ if(!prs_uint16("server_role", ps, depth, &u_7->server_role))
+ return False;
- init_unistr2(&u_2->uni_comment, comment, UNI_FLAGS_NONE);
- init_uni_hdr(&u_2->hdr_comment, &u_2->uni_comment);
- init_unistr2(&u_2->uni_domain, domain, UNI_FLAGS_NONE);
- init_uni_hdr(&u_2->hdr_domain, &u_2->uni_domain);
- init_unistr2(&u_2->uni_server, server, UNI_FLAGS_NONE);
- init_uni_hdr(&u_2->hdr_server, &u_2->uni_server);
+ return True;
+}
+
+/*******************************************************************
+inits a structure.
+********************************************************************/
+
+void init_unk_info8(SAM_UNK_INFO_8 * u_8, uint32 seq_num)
+{
+ unix_to_nt_time(&u_8->domain_create_time, 0);
+ u_8->seq_num.low = seq_num;
+ u_8->seq_num.high = 0x0000;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
+static BOOL sam_io_unk_info8(const char *desc, SAM_UNK_INFO_8 * u_8,
prs_struct *ps, int depth)
{
- if (u_2 == NULL)
+ if (u_8 == NULL)
return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info2");
+ prs_debug(ps, depth, desc, "sam_io_unk_info8");
depth++;
- if(!smb_io_time("logout", &u_2->logout, ps, depth))
- return False;
- if(!smb_io_unihdr("hdr_comment", &u_2->hdr_comment, ps, depth))
- return False;
- if(!smb_io_unihdr("hdr_domain", &u_2->hdr_domain, ps, depth))
+ if (!prs_uint64("seq_num", ps, depth, &u_8->seq_num))
return False;
- if(!smb_io_unihdr("hdr_server", &u_2->hdr_server, ps, depth))
+
+ if(!smb_io_time("domain_create_time", &u_8->domain_create_time, ps, depth))
return False;
- /* put all the data in here, at the moment, including what the above
- pointer is referring to
- */
+ return True;
+}
- if(!prs_uint64("seq_num ", ps, depth, &u_2->seq_num))
- return False;
+/*******************************************************************
+inits a structure.
+********************************************************************/
- if(!prs_uint32("unknown_4 ", ps, depth, &u_2->unknown_4)) /* 0x0000 0001 */
- return False;
- if(!prs_uint32("server_role ", ps, depth, &u_2->server_role))
- return False;
- if(!prs_uint32("unknown_6 ", ps, depth, &u_2->unknown_6)) /* 0x0000 0001 */
- return False;
- if(!prs_uint32("num_domain_usrs ", ps, depth, &u_2->num_domain_usrs))
+void init_unk_info9(SAM_UNK_INFO_9 * u_9, uint32 unknown)
+{
+ u_9->unknown = unknown;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_unk_info9(const char *desc, SAM_UNK_INFO_9 * u_9,
+ prs_struct *ps, int depth)
+{
+ if (u_9 == NULL)
return False;
- if(!prs_uint32("num_domain_grps", ps, depth, &u_2->num_domain_grps))
+
+ prs_debug(ps, depth, desc, "sam_io_unk_info9");
+ depth++;
+
+ if (!prs_uint32("unknown", ps, depth, &u_9->unknown))
return False;
- if(!prs_uint32("num_local_grps", ps, depth, &u_2->num_local_grps))
+
+ return True;
+}
+
+/*******************************************************************
+inits a structure.
+********************************************************************/
+
+void init_unk_info12(SAM_UNK_INFO_12 * u_12, NTTIME nt_lock_duration, NTTIME nt_reset_time, uint16 lockout)
+{
+ u_12->duration.low = nt_lock_duration.low;
+ u_12->duration.high = nt_lock_duration.high;
+ u_12->reset_count.low = nt_reset_time.low;
+ u_12->reset_count.high = nt_reset_time.high;
+
+ u_12->bad_attempt_lockout = lockout;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12,
+ prs_struct *ps, int depth)
+{
+ if (u_12 == NULL)
return False;
- if(!smb_io_unistr2("uni_comment", &u_2->uni_comment, u_2->hdr_comment.buffer, ps, depth))
+ prs_debug(ps, depth, desc, "sam_io_unk_info12");
+ depth++;
+
+ if(!smb_io_time("duration", &u_12->duration, ps, depth))
return False;
- if(!smb_io_unistr2("uni_domain", &u_2->uni_domain, u_2->hdr_domain.buffer, ps, depth))
+ if(!smb_io_time("reset_count", &u_12->reset_count, ps, depth))
return False;
- if(!smb_io_unistr2("uni_server", &u_2->uni_server, u_2->hdr_server.buffer, ps, depth))
+ if(!prs_uint16("bad_attempt_lockout", ps, depth, &u_12->bad_attempt_lockout))
return False;
return True;
@@ -778,45 +884,37 @@ static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
inits a structure.
********************************************************************/
-void init_unk_info1(SAM_UNK_INFO_1 *u_1, uint16 min_pass_len, uint16 pass_hist,
- uint32 password_properties, NTTIME nt_expire, NTTIME nt_min_age)
+void init_unk_info13(SAM_UNK_INFO_13 * u_13, uint32 seq_num)
{
- u_1->min_length_password = min_pass_len;
- u_1->password_history = pass_hist;
- u_1->password_properties = password_properties;
-
- /* password never expire */
- u_1->expire.high = nt_expire.high;
- u_1->expire.low = nt_expire.low;
-
- /* can change the password now */
- u_1->min_passwordage.high = nt_min_age.high;
- u_1->min_passwordage.low = nt_min_age.low;
-
+ unix_to_nt_time(&u_13->domain_create_time, 0);
+ u_13->seq_num.low = seq_num;
+ u_13->seq_num.high = 0x0000;
+ u_13->unknown1 = 0;
+ u_13->unknown2 = 0;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
-static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
+static BOOL sam_io_unk_info13(const char *desc, SAM_UNK_INFO_13 * u_13,
prs_struct *ps, int depth)
{
- if (u_1 == NULL)
- return False;
+ if (u_13 == NULL)
+ return False;
- prs_debug(ps, depth, desc, "sam_io_unk_info1");
+ prs_debug(ps, depth, desc, "sam_io_unk_info13");
depth++;
- if(!prs_uint16("min_length_password", ps, depth, &u_1->min_length_password))
+ if (!prs_uint64("seq_num", ps, depth, &u_13->seq_num))
return False;
- if(!prs_uint16("password_history", ps, depth, &u_1->password_history))
- return False;
- if(!prs_uint32("password_properties", ps, depth, &u_1->password_properties))
+
+ if(!smb_io_time("domain_create_time", &u_13->domain_create_time, ps, depth))
return False;
- if(!smb_io_time("expire", &u_1->expire, ps, depth))
+
+ if (!prs_uint32("unknown1", ps, depth, &u_13->unknown1))
return False;
- if(!smb_io_time("min_passwordage", &u_1->min_passwordage, ps, depth))
+ if (!prs_uint32("unknown2", ps, depth, &u_13->unknown2))
return False;
return True;
@@ -826,11 +924,11 @@ static BOOL sam_io_unk_info1(const char *desc, SAM_UNK_INFO_1 * u_1,
inits a SAMR_R_QUERY_DOMAIN_INFO structure.
********************************************************************/
-void init_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO * r_u,
- uint16 switch_value, SAM_UNK_CTR * ctr,
- NTSTATUS status)
+void init_samr_r_query_domain_info(SAMR_R_QUERY_DOMAIN_INFO * r_u,
+ uint16 switch_value, SAM_UNK_CTR * ctr,
+ NTSTATUS status)
{
- DEBUG(5, ("init_samr_r_query_dom_info\n"));
+ DEBUG(5, ("init_samr_r_query_domain_info\n"));
r_u->ptr_0 = 0;
r_u->switch_value = 0;
@@ -847,13 +945,13 @@ void init_samr_r_query_dom_info(SAMR_R_QUERY_DOMAIN_INFO * r_u,
reads or writes a structure.
********************************************************************/
-BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
- prs_struct *ps, int depth)
+BOOL samr_io_r_query_domain_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
+ prs_struct *ps, int depth)
{
if (r_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_r_query_dom_info");
+ prs_debug(ps, depth, desc, "samr_io_r_query_domain_info");
depth++;
if(!prs_align(ps))
@@ -869,10 +967,18 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
return False;
switch (r_u->switch_value) {
+ case 0x0d:
+ if(!sam_io_unk_info13("unk_inf13", &r_u->ctr->info.inf13, ps, depth))
+ return False;
+ break;
case 0x0c:
if(!sam_io_unk_info12("unk_inf12", &r_u->ctr->info.inf12, ps, depth))
return False;
break;
+ case 0x09:
+ if(!sam_io_unk_info9("unk_inf9",&r_u->ctr->info.inf9, ps,depth))
+ return False;
+ break;
case 0x08:
if(!sam_io_unk_info8("unk_inf8",&r_u->ctr->info.inf8, ps,depth))
return False;
@@ -889,6 +995,10 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
if(!sam_io_unk_info5("unk_inf5",&r_u->ctr->info.inf5, ps,depth))
return False;
break;
+ case 0x04:
+ if(!sam_io_unk_info4("unk_inf4",&r_u->ctr->info.inf4, ps,depth))
+ return False;
+ break;
case 0x03:
if(!sam_io_unk_info3("unk_inf3",&r_u->ctr->info.inf3, ps,depth))
return False;
@@ -902,7 +1012,7 @@ BOOL samr_io_r_query_dom_info(const char *desc, SAMR_R_QUERY_DOMAIN_INFO * r_u,
return False;
break;
default:
- DEBUG(0, ("samr_io_r_query_dom_info: unknown switch level 0x%x\n",
+ DEBUG(0, ("samr_io_r_query_domain_info: unknown switch level 0x%x\n",
r_u->switch_value));
r_u->status = NT_STATUS_INVALID_INFO_CLASS;
return False;
@@ -7659,11 +7769,11 @@ BOOL samr_io_q_query_domain_info2(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO2 *q
inits a SAMR_R_QUERY_DOMAIN_INFO structure.
********************************************************************/
-void init_samr_r_samr_query_domain_info2(SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
- uint16 switch_value, SAM_UNK_CTR * ctr,
- NTSTATUS status)
+void init_samr_r_query_domain_info2(SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
+ uint16 switch_value, SAM_UNK_CTR * ctr,
+ NTSTATUS status)
{
- DEBUG(5, ("init_samr_r_samr_query_domain_info2\n"));
+ DEBUG(5, ("init_samr_r_query_domain_info2\n"));
r_u->ptr_0 = 0;
r_u->switch_value = 0;
@@ -7680,13 +7790,13 @@ void init_samr_r_samr_query_domain_info2(SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
reads or writes a structure.
********************************************************************/
-BOOL samr_io_r_samr_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
- prs_struct *ps, int depth)
+BOOL samr_io_r_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
+ prs_struct *ps, int depth)
{
if (r_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_r_samr_query_domain_info2");
+ prs_debug(ps, depth, desc, "samr_io_r_query_domain_info2");
depth++;
if(!prs_align(ps))
@@ -7702,10 +7812,22 @@ BOOL samr_io_r_samr_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INF
return False;
switch (r_u->switch_value) {
+ case 0x0d:
+ if(!sam_io_unk_info13("unk_inf13", &r_u->ctr->info.inf13, ps, depth))
+ return False;
+ break;
case 0x0c:
if(!sam_io_unk_info12("unk_inf12", &r_u->ctr->info.inf12, ps, depth))
return False;
break;
+ case 0x09:
+ if(!sam_io_unk_info9("unk_inf9",&r_u->ctr->info.inf9, ps,depth))
+ return False;
+ break;
+ case 0x08:
+ if(!sam_io_unk_info8("unk_inf8",&r_u->ctr->info.inf8, ps,depth))
+ return False;
+ break;
case 0x07:
if(!sam_io_unk_info7("unk_inf7",&r_u->ctr->info.inf7, ps,depth))
return False;
@@ -7718,6 +7840,10 @@ BOOL samr_io_r_samr_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INF
if(!sam_io_unk_info5("unk_inf5",&r_u->ctr->info.inf5, ps,depth))
return False;
break;
+ case 0x04:
+ if(!sam_io_unk_info4("unk_inf4",&r_u->ctr->info.inf4, ps,depth))
+ return False;
+ break;
case 0x03:
if(!sam_io_unk_info3("unk_inf3",&r_u->ctr->info.inf3, ps,depth))
return False;
@@ -7731,7 +7857,7 @@ BOOL samr_io_r_samr_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INF
return False;
break;
default:
- DEBUG(0, ("samr_io_r_samr_query_domain_info2: unknown switch level 0x%x\n",
+ DEBUG(0, ("samr_io_r_query_domain_info2: unknown switch level 0x%x\n",
r_u->switch_value));
r_u->status = NT_STATUS_INVALID_INFO_CLASS;
return False;
diff --git a/source/rpc_server/srv_eventlog_lib.c b/source/rpc_server/srv_eventlog_lib.c
index acae1c94e9a..e04aefa7e1b 100644
--- a/source/rpc_server/srv_eventlog_lib.c
+++ b/source/rpc_server/srv_eventlog_lib.c
@@ -39,7 +39,7 @@ TDB_CONTEXT *elog_init_tdb( char *tdbfilename )
tdbfilename));
tdb = tdb_open_log( tdbfilename, 0, TDB_DEFAULT,
- O_RDWR|O_CREAT|O_TRUNC, 0600 );
+ O_RDWR|O_CREAT|O_TRUNC, 0660 );
if ( !tdb ) {
DEBUG( 0, ( "Can't open tdb for [%s]\n", tdbfilename ) );
diff --git a/source/rpc_server/srv_reg_nt.c b/source/rpc_server/srv_reg_nt.c
index 5ac6738b991..8fd0e55c547 100644
--- a/source/rpc_server/srv_reg_nt.c
+++ b/source/rpc_server/srv_reg_nt.c
@@ -1199,7 +1199,7 @@ WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r
WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u)
{
REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
- REGISTRY_KEY *newparentinfo;
+ REGISTRY_KEY *newparentinfo = NULL;
POLICY_HND newparent_handle;
REGSUBKEY_CTR *subkeys;
BOOL write_result;
diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c
index 8e4955a81c2..6ce4f882619 100644
--- a/source/rpc_server/srv_samr.c
+++ b/source/rpc_server/srv_samr.c
@@ -525,10 +525,10 @@ static BOOL api_samr_query_usergroups(pipes_struct *p)
}
/*******************************************************************
- api_samr_query_dom_info
+ api_samr_query_domain_info
********************************************************************/
-static BOOL api_samr_query_dom_info(pipes_struct *p)
+static BOOL api_samr_query_domain_info(pipes_struct *p)
{
SAMR_Q_QUERY_DOMAIN_INFO q_u;
SAMR_R_QUERY_DOMAIN_INFO r_u;
@@ -538,16 +538,16 @@ static BOOL api_samr_query_dom_info(pipes_struct *p)
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!samr_io_q_query_dom_info("", &q_u, data, 0)) {
- DEBUG(0,("api_samr_query_dom_info: unable to unmarshall SAMR_Q_QUERY_DOMAIN_INFO.\n"));
+ if(!samr_io_q_query_domain_info("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_query_domain_info: unable to unmarshall SAMR_Q_QUERY_DOMAIN_INFO.\n"));
return False;
}
- r_u.status = _samr_query_dom_info(p, &q_u, &r_u);
+ r_u.status = _samr_query_domain_info(p, &q_u, &r_u);
/* store the response in the SMB stream */
- if(!samr_io_r_query_dom_info("", &r_u, rdata, 0)) {
- DEBUG(0,("api_samr_query_dom_info: unable to marshall SAMR_R_QUERY_DOMAIN_INFO.\n"));
+ if(!samr_io_r_query_domain_info("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_query_domain_info: unable to marshall SAMR_R_QUERY_DOMAIN_INFO.\n"));
return False;
}
@@ -1449,7 +1449,6 @@ static BOOL api_samr_query_domain_info2(pipes_struct *p)
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- /* grab the samr unknown 8 command */
if(!samr_io_q_query_domain_info2("", &q_u, data, 0)) {
DEBUG(0,("api_samr_query_domain_info2: unable to unmarshall SAMR_Q_QUERY_DOMAIN_INFO2.\n"));
return False;
@@ -1458,7 +1457,7 @@ static BOOL api_samr_query_domain_info2(pipes_struct *p)
r_u.status = _samr_query_domain_info2(p, &q_u, &r_u);
/* store the response in the SMB stream */
- if(!samr_io_r_samr_query_domain_info2("", &r_u, rdata, 0)) {
+ if(!samr_io_r_query_domain_info2("", &r_u, rdata, 0)) {
DEBUG(0,("api_samr_query_domain_info2: unable to marshall SAMR_R_QUERY_DOMAIN_INFO2.\n"));
return False;
}
@@ -1529,7 +1528,7 @@ static struct api_struct api_samr_cmds [] =
{"SAMR_SET_USERINFO" , SAMR_SET_USERINFO , api_samr_set_userinfo },
{"SAMR_SET_USERINFO2" , SAMR_SET_USERINFO2 , api_samr_set_userinfo2 },
- {"SAMR_QUERY_DOMAIN_INFO" , SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info },
+ {"SAMR_QUERY_DOMAIN_INFO" , SAMR_QUERY_DOMAIN_INFO, api_samr_query_domain_info},
{"SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
{"SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo },
{"SAMR_QUERY_DISPINFO3" , SAMR_QUERY_DISPINFO3 , api_samr_query_dispinfo },
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index c4b3d3512c0..c9e6b552c8d 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -2180,10 +2180,12 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
}
/*******************************************************************
- _samr_query_dom_info
+ _samr_query_domain_info
********************************************************************/
-NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SAMR_R_QUERY_DOMAIN_INFO *r_u)
+NTSTATUS _samr_query_domain_info(pipes_struct *p,
+ SAMR_Q_QUERY_DOMAIN_INFO *q_u,
+ SAMR_R_QUERY_DOMAIN_INFO *r_u)
{
struct samr_info *info = NULL;
SAM_UNK_CTR *ctr;
@@ -2212,7 +2214,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
r_u->status = NT_STATUS_OK;
- DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__));
+ DEBUG(5,("_samr_query_domain_info: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info)) {
@@ -2300,11 +2302,17 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
init_unk_info3(&ctr->info.inf3, nt_logout);
break;
+ case 0x04:
+ init_unk_info4(&ctr->info.inf4, lp_serverstring());
+ break;
case 0x05:
- init_unk_info5(&ctr->info.inf5, global_myname());
+ init_unk_info5(&ctr->info.inf5, get_global_sam_name());
break;
case 0x06:
- init_unk_info6(&ctr->info.inf6);
+ /* NT returns its own name when a PDC. win2k and later
+ * only the name of the PDC if itself is a BDC (samba4
+ * idl) */
+ init_unk_info6(&ctr->info.inf6, global_myname());
break;
case 0x07:
server_role = ROLE_DOMAIN_PDC;
@@ -2361,9 +2369,9 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
}
- init_samr_r_query_dom_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
+ init_samr_r_query_domain_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
- DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__));
+ DEBUG(5,("_samr_query_domain_info: %d\n", __LINE__));
return r_u->status;
}
@@ -4712,144 +4720,31 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
********************************************************************/
NTSTATUS _samr_query_domain_info2(pipes_struct *p,
- SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
- SAMR_R_QUERY_DOMAIN_INFO2 *r_u)
+ SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
+ SAMR_R_QUERY_DOMAIN_INFO2 *r_u)
{
- struct samr_info *info = NULL;
- SAM_UNK_CTR *ctr;
- uint32 min_pass_len,pass_hist,password_properties;
- time_t u_expire, u_min_age;
- NTTIME nt_expire, nt_min_age;
-
- time_t u_lock_duration, u_reset_time;
- NTTIME nt_lock_duration, nt_reset_time;
- uint32 lockout;
-
- time_t u_logout;
- NTTIME nt_logout;
-
- uint32 num_users=0, num_groups=0, num_aliases=0;
+ SAMR_Q_QUERY_DOMAIN_INFO q;
+ SAMR_R_QUERY_DOMAIN_INFO r;
- uint32 account_policy_temp;
-
- time_t seq_num;
- uint32 server_role;
-
- if ((ctr = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_CTR)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- ZERO_STRUCTP(ctr);
-
- r_u->status = NT_STATUS_OK;
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
DEBUG(5,("_samr_query_domain_info2: %d\n", __LINE__));
- /* find the policy handle. open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)(void *)&info))
- return NT_STATUS_INVALID_HANDLE;
-
- switch (q_u->switch_value) {
- case 0x01:
- 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;
-
- unix_to_nt_time_abs(&nt_expire, u_expire);
- unix_to_nt_time_abs(&nt_min_age, u_min_age);
+ q.domain_pol = q_u->domain_pol;
+ q.switch_value = q_u->switch_value;
- init_unk_info1(&ctr->info.inf1, (uint16)min_pass_len, (uint16)pass_hist,
- password_properties, nt_expire, nt_min_age);
- break;
- case 0x02:
- become_root();
- num_users = count_sam_users(info->disp_info, ACB_NORMAL);
- num_groups = count_sam_groups(info->disp_info);
- num_aliases = count_sam_aliases(info->disp_info);
- unbecome_root();
+ r_u->status = _samr_query_domain_info(p, &q, &r);
- pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
- u_logout = account_policy_temp;
-
- unix_to_nt_time_abs(&nt_logout, u_logout);
-
- if (!pdb_get_seq_num(&seq_num))
- seq_num = time(NULL);
-
- server_role = ROLE_DOMAIN_PDC;
- if (lp_server_role() == ROLE_DOMAIN_BDC)
- server_role = ROLE_DOMAIN_BDC;
-
- init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), seq_num,
- num_users, num_groups, num_aliases, nt_logout, server_role);
- break;
- case 0x03:
- pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
- u_logout = account_policy_temp;
-
- unix_to_nt_time_abs(&nt_logout, u_logout);
-
- init_unk_info3(&ctr->info.inf3, nt_logout);
- break;
- case 0x05:
- init_unk_info5(&ctr->info.inf5, global_myname());
- break;
- case 0x06:
- init_unk_info6(&ctr->info.inf6);
- break;
- case 0x07:
- server_role = ROLE_DOMAIN_PDC;
- if (lp_server_role() == ROLE_DOMAIN_BDC)
- server_role = ROLE_DOMAIN_BDC;
-
- init_unk_info7(&ctr->info.inf7, server_role);
- break;
- case 0x08:
- if (!pdb_get_seq_num(&seq_num))
- seq_num = time(NULL);
-
- init_unk_info8(&ctr->info.inf8, (uint32) seq_num);
- break;
- case 0x0c:
- pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
- u_lock_duration = account_policy_temp;
- if (u_lock_duration != -1)
- u_lock_duration *= 60;
-
- pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp);
- u_reset_time = account_policy_temp * 60;
-
- pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
- lockout = account_policy_temp;
-
- unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
- unix_to_nt_time_abs(&nt_reset_time, u_reset_time);
-
- init_unk_info12(&ctr->info.inf12, nt_lock_duration, nt_reset_time, (uint16)lockout);
- break;
- default:
- return NT_STATUS_INVALID_INFO_CLASS;
- }
-
- init_samr_r_samr_query_domain_info2(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
-
- DEBUG(5,("_samr_query_domain_info2: %d\n", __LINE__));
+ r_u->ptr_0 = r.ptr_0;
+ r_u->switch_value = r.switch_value;
+ r_u->ctr = r.ctr;
return r_u->status;
}
/*******************************************************************
- _samr_
+ _samr_set_dom_info
********************************************************************/
NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R_SET_DOMAIN_INFO *r_u)
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index aede762ed43..2e224896c4d 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -40,23 +40,6 @@ extern userdom_struct current_user_info;
#define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
#define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
-
-/* Table to map the driver version */
-/* to OS */
-static const char * drv_ver_to_os[] = {
- "WIN9X", /* driver version/cversion 0 */
- "", /* unused ? */
- "WINNT", /* driver version/cversion 2 */
- "WIN2K", /* driver version/cversion 3 */
-};
-
-static const char *get_drv_ver_to_os(int ver)
-{
- if (ver < 0 || ver > 3)
- return "";
- return drv_ver_to_os[ver];
-}
-
struct table_node {
const char *long_archi;
const char *short_archi;
@@ -7657,21 +7640,6 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
goto done;
}
- /* BEGIN_ADMIN_LOG */
- switch(level) {
- 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.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.ut.uid));
- break;
- }
- /* END_ADMIN_LOG */
-
/*
* I think this is where he DrvUpgradePrinter() hook would be
* be called in a driver's interface DLL on a Windows NT 4.0/2k
diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c
index 0e22b982873..97a707c020a 100644
--- a/source/rpcclient/cmd_lsarpc.c
+++ b/source/rpcclient/cmd_lsarpc.c
@@ -859,10 +859,7 @@ static void display_trust_dom_info_4(TRUSTED_DOMAIN_INFO_PASSWORD *p, const char
DATA_BLOB data_old = data_blob(NULL, p->old_password.length);
memcpy(data.data, p->password.data, p->password.length);
- data.length = p->password.length;
-
memcpy(data_old.data, p->old_password.data, p->old_password.length);
- data_old.length = p->old_password.length;
pwd = decrypt_trustdom_secret(password, &data);
pwd_old = decrypt_trustdom_secret(password, &data_old);
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index ca0b6e96245..cbf638e7e62 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -208,6 +208,35 @@ static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
printf("Unknown 6:\t0x%x\n", info2->unknown_6);
}
+static void display_sam_unk_info_3(SAM_UNK_INFO_3 *info3)
+{
+ printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info3->logout));
+}
+
+static void display_sam_unk_info_4(SAM_UNK_INFO_4 *info4)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &info4->uni_comment, sizeof(name) - 1);
+ printf("Comment:\t%s\n", name);
+}
+
+static void display_sam_unk_info_5(SAM_UNK_INFO_5 *info5)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &info5->uni_domain, sizeof(name) - 1);
+ printf("Domain:\t\t%s\n", name);
+}
+
+static void display_sam_unk_info_6(SAM_UNK_INFO_6 *info6)
+{
+ fstring name;
+
+ unistr2_to_ascii(name, &info6->uni_server, sizeof(name) - 1);
+ printf("Server:\t\t%s\n", name);
+}
+
static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
{
printf("Server Role:\t%s\n", server_role_str(info7->server_role));
@@ -218,7 +247,11 @@ static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
printf("Sequence No:\t%d\n", info8->seq_num.low);
printf("Domain Create Time:\t%s\n",
http_timestring(nt_time_to_unix(&info8->domain_create_time)));
+}
+static void display_sam_unk_info_9(SAM_UNK_INFO_9 *info9)
+{
+ printf("unknown:\t%d (0x%08x)\n", info9->unknown, info9->unknown);
}
static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
@@ -228,6 +261,16 @@ static void display_sam_unk_info_12(SAM_UNK_INFO_12 *info12)
printf("Lockout after bad attempts: %d\n", info12->bad_attempt_lockout);
}
+static void display_sam_unk_info_13(SAM_UNK_INFO_13 *info13)
+{
+ printf("Sequence No:\t%d\n", info13->seq_num.low);
+ printf("Domain Create Time:\t%s\n",
+ http_timestring(nt_time_to_unix(&info13->domain_create_time)));
+ printf("Unknown1:\t%d\n", info13->unknown1);
+ printf("Unknown2:\t%d\n", info13->unknown2);
+
+}
+
static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1)
{
fstring tmp;
@@ -1367,15 +1410,34 @@ static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli,
case 2:
display_sam_unk_info_2(&ctr.info.inf2);
break;
+ case 3:
+ display_sam_unk_info_3(&ctr.info.inf3);
+ break;
+ case 4:
+ display_sam_unk_info_4(&ctr.info.inf4);
+ break;
+ case 5:
+ display_sam_unk_info_5(&ctr.info.inf5);
+ break;
+ case 6:
+ display_sam_unk_info_6(&ctr.info.inf6);
+ break;
case 7:
display_sam_unk_info_7(&ctr.info.inf7);
break;
case 8:
display_sam_unk_info_8(&ctr.info.inf8);
break;
+ case 9:
+ display_sam_unk_info_9(&ctr.info.inf9);
+ break;
case 12:
display_sam_unk_info_12(&ctr.info.inf12);
break;
+ case 13:
+ display_sam_unk_info_13(&ctr.info.inf13);
+ break;
+
default:
printf("cannot display domain info for switch value %d\n",
switch_level);
diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c
index 50ddbd405ba..d5425aa43d1 100644
--- a/source/rpcclient/rpcclient.c
+++ b/source/rpcclient/rpcclient.c
@@ -787,6 +787,11 @@ out_free:
}
}
+ if ((server[0] == '/' && server[1] == '/') ||
+ (server[0] == '\\' && server[1] == '\\')) {
+ server += 2;
+ }
+
nt_status = cli_full_connection(&cli, global_myname(), server,
opt_ipaddr ? &server_ip : NULL, opt_port,
"IPC$", "IPC",
diff --git a/source/sam/idmap.c b/source/sam/idmap.c
index aac8b70013a..aa5b923d3dd 100644
--- a/source/sam/idmap.c
+++ b/source/sam/idmap.c
@@ -25,6 +25,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_IDMAP
+static_decl_idmap;
+
struct idmap_function_entry {
const char *name;
struct idmap_methods *methods;
diff --git a/source/sam/idmap_ad.c b/source/sam/idmap_ad.c
index f9a959e7ec0..5edfad487d7 100644
--- a/source/sam/idmap_ad.c
+++ b/source/sam/idmap_ad.c
@@ -30,14 +30,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_IDMAP
-#ifndef ATTR_UIDNUMBER
-#define ATTR_UIDNUMBER ADS_ATTR_SFU_UIDNUMBER_OID
-#endif
-
-#ifndef ATTR_GIDNUMBER
-#define ATTR_GIDNUMBER ADS_ATTR_SFU_GIDNUMBER_OID
-#endif
-
#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
NTSTATUS init_module(void);
@@ -48,28 +40,42 @@ static char *ad_idmap_uri = NULL;
static char *attr_uidnumber = NULL;
static char *attr_gidnumber = NULL;
-static BOOL ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
+static ADS_STATUS ad_idmap_check_attr_mapping(ADS_STRUCT *ads)
{
+ ADS_STATUS status;
+ enum wb_posix_mapping map_type;
+
if (attr_uidnumber != NULL && attr_gidnumber != NULL) {
- return True;
+ return ADS_ERROR(LDAP_SUCCESS);
}
- if (use_nss_info("sfu")) {
-
- if (!ads_check_sfu_mapping(ads)) {
- DEBUG(0,("ad_idmap_check_attr_mapping: failed to check for SFU schema\n"));
- return False;
- }
+ SMB_ASSERT(ads->server.workgroup);
- attr_uidnumber = SMB_STRDUP(ads->schema.sfu_uidnumber_attr);
- attr_gidnumber = SMB_STRDUP(ads->schema.sfu_gidnumber_attr);
+ map_type = get_nss_info(ads->server.workgroup);
- } else {
- attr_uidnumber = SMB_STRDUP("uidNumber");
- attr_gidnumber = SMB_STRDUP("gidNumber");
+ if ((map_type == WB_POSIX_MAP_SFU) ||
+ (map_type == WB_POSIX_MAP_RFC2307)) {
+
+ status = ads_check_posix_schema_mapping(ads, map_type);
+ if (ADS_ERR_OK(status)) {
+ attr_uidnumber = SMB_STRDUP(ads->schema.posix_uidnumber_attr);
+ attr_gidnumber = SMB_STRDUP(ads->schema.posix_gidnumber_attr);
+ ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
+ ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
+ return ADS_ERROR(LDAP_SUCCESS);
+ } else {
+ DEBUG(0,("ads_check_posix_schema_mapping failed: %s\n", ads_errstr(status)));
+ /* return status; */
+ }
}
+
+ /* fallback to XAD defaults */
+ attr_uidnumber = SMB_STRDUP("uidNumber");
+ attr_gidnumber = SMB_STRDUP("gidNumber");
+ ADS_ERROR_HAVE_NO_MEMORY(attr_uidnumber);
+ ADS_ERROR_HAVE_NO_MEMORY(attr_gidnumber);
- return True;
+ return ADS_ERROR(LDAP_SUCCESS);
}
static ADS_STRUCT *ad_idmap_cached_connection(void)
@@ -78,10 +84,6 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
ADS_STATUS status;
BOOL local = False;
-#ifdef ADS_AUTH_EXTERNAL_BIND
- local = ((strncmp(ad_idmap_uri, "ldapi://", sizeof("ldapi://") - 1)) == 0);
-#endif /* ADS_AUTH_EXTERNAL_BIND */
-
if (ad_idmap_ads != NULL) {
ads = ad_idmap_ads;
@@ -105,40 +107,18 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
}
- ads = ads_init(NULL, NULL, NULL);
+ ads = ads_init(lp_realm(), lp_workgroup(), NULL);
if (!ads) {
DEBUG(1,("ads_init failed\n"));
return NULL;
}
- /* if ad_imap_uri is not empty we try to connect to
- * the given URI in smb.conf. Else try to connect to
- * one of the DCs
- */
- if (*ad_idmap_uri != '\0') {
- ads->server.ldap_uri = SMB_STRDUP(ad_idmap_uri);
- if (ads->server.ldap_uri == NULL) {
- return NULL;
- }
- }
- else {
- ads->server.ldap_uri = NULL;
- ads->server.ldap_server = NULL;
- }
+ /* the machine acct password might have change - fetch it every time */
+ SAFE_FREE(ads->auth.password);
+ ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-#ifdef ADS_AUTH_EXTERNAL_BIND
- if (local)
- ads->auth.flags |= ADS_AUTH_EXTERNAL_BIND;
- else
-#endif
- {
- /* the machine acct password might have change - fetch it every time */
- SAFE_FREE(ads->auth.password);
- ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
-
- SAFE_FREE(ads->auth.realm);
- ads->auth.realm = SMB_STRDUP(lp_realm());
- }
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = SMB_STRDUP(lp_realm());
status = ads_connect(ads);
if (!ADS_ERR_OK(status)) {
@@ -149,7 +129,8 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
ads->is_mine = False;
- if (!ad_idmap_check_attr_mapping(ads)) {
+ status = ad_idmap_check_attr_mapping(ads);
+ if (!ADS_ERR_OK(status)) {
DEBUG(1, ("ad_idmap_init: failed to check attribute mapping\n"));
return NULL;
}
@@ -194,14 +175,14 @@ static NTSTATUS ad_idmap_get_sid_from_id(DOM_SID *sid, unid_t unid, int id_type)
case ID_USERID:
if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
- ATTR_UIDNUMBER, (int)unid.uid) == -1) {
+ ads->schema.posix_uidnumber_attr, (int)unid.uid) == -1) {
return NT_STATUS_NO_MEMORY;
}
break;
case ID_GROUPID:
if (asprintf(&expr, "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(%s=%d))",
ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP,
- ATTR_GIDNUMBER, (int)unid.gid) == -1) {
+ ads->schema.posix_gidnumber_attr, (int)unid.gid) == -1) {
return NT_STATUS_NO_MEMORY;
}
break;
@@ -254,7 +235,11 @@ static NTSTATUS ad_idmap_get_id_from_sid(unid_t *unid, int *id_type, const DOM_S
{
ADS_STATUS rc;
NTSTATUS status = NT_STATUS_NONE_MAPPED;
- const char *attrs[] = { "sAMAccountType", ATTR_UIDNUMBER, ATTR_GIDNUMBER, NULL };
+ const char *attrs[] = { "sAMAccountType", ADS_ATTR_SFU_UIDNUMBER_OID,
+ ADS_ATTR_SFU_GIDNUMBER_OID,
+ ADS_ATTR_RFC2307_UIDNUMBER_OID,
+ ADS_ATTR_RFC2307_GIDNUMBER_OID,
+ NULL };
void *res = NULL;
void *msg = NULL;
char *expr = NULL;
diff --git a/source/sam/idmap_util.c b/source/sam/idmap_util.c
index 7233cb48cd1..f78d3bdc233 100644
--- a/source/sam/idmap_util.c
+++ b/source/sam/idmap_util.c
@@ -110,17 +110,3 @@ NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags)
return ret;
}
-
-/* placeholder for checking lp_winbind_nss_info() */
-BOOL use_nss_info(const char *info)
-{
- int i;
- const char **list = lp_winbind_nss_info();
-
- for (i=0; list[i]; i++) {
- if (strequal(list[i], info))
- return True;
- }
-
- return False;
-}
diff --git a/source/sam/nss_info.c b/source/sam/nss_info.c
new file mode 100644
index 00000000000..3d0e658a358
--- /dev/null
+++ b/source/sam/nss_info.c
@@ -0,0 +1,111 @@
+/*
+ Unix SMB/CIFS implementation.
+ nss info helpers
+ Copyright (C) Guenther Deschner 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/* winbind nss info = rfc2307 SO36:sfu FHAIN:rfc2307 PANKOW:template
+ *
+ * syntax is:
+ * 1st param: default setting
+ * following ":" separated list elements:
+ * DOMAIN:setting
+ * setting can be one of "sfu", "rfc2307", "template", "unixinfo"
+ */
+
+enum wb_posix_mapping get_nss_info(const char *domain_name)
+{
+ const char **list = lp_winbind_nss_info();
+ enum wb_posix_mapping map_templ = WB_POSIX_MAP_TEMPLATE;
+ int i;
+
+ DEBUG(11,("get_nss_info for %s\n", domain_name));
+
+ if (!lp_winbind_nss_info() || !*lp_winbind_nss_info()) {
+ return WB_POSIX_MAP_TEMPLATE;
+ }
+
+ if ((map_templ = wb_posix_map_type(list[0])) == -1) {
+ DEBUG(0,("get_nss_info: invalid setting: %s\n", list[0]));
+ return WB_POSIX_MAP_TEMPLATE;
+ }
+
+ DEBUG(11,("get_nss_info: using \"%s\" by default\n", list[0]));
+
+ for (i=0; list[i]; i++) {
+
+ const char *p = list[i];
+ fstring tok;
+
+ if (!next_token(&p, tok, ":", sizeof(tok))) {
+ DEBUG(0,("get_nss_info: no \":\" delimitier found\n"));
+ continue;
+ }
+
+ if (strequal(tok, domain_name)) {
+
+ enum wb_posix_mapping type;
+
+ if ((type = wb_posix_map_type(p)) == -1) {
+ DEBUG(0,("get_nss_info: invalid setting: %s\n", p));
+ /* return WB_POSIX_MAP_TEMPLATE; */
+ continue;
+ }
+
+ DEBUG(11,("get_nss_info: using \"%s\" for domain: %s\n", p, tok));
+
+ return type;
+ }
+ }
+
+ return map_templ;
+}
+
+const char *wb_posix_map_str(enum wb_posix_mapping mtype)
+{
+ switch (mtype) {
+ case WB_POSIX_MAP_TEMPLATE:
+ return "template";
+ case WB_POSIX_MAP_SFU:
+ return "sfu";
+ case WB_POSIX_MAP_RFC2307:
+ return "rfc2307";
+ case WB_POSIX_MAP_UNIXINFO:
+ return "unixinfo";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+enum wb_posix_mapping wb_posix_map_type(const char *map_str)
+{
+ if (strequal(map_str, "template"))
+ return WB_POSIX_MAP_TEMPLATE;
+ else if (strequal(map_str, "sfu"))
+ return WB_POSIX_MAP_SFU;
+ else if (strequal(map_str, "rfc2307"))
+ return WB_POSIX_MAP_RFC2307;
+ else if (strequal(map_str, "unixinfo"))
+ return WB_POSIX_MAP_UNIXINFO;
+
+ return -1;
+}
diff --git a/source/script/installswat.sh b/source/script/installswat.sh
index 427e1773620..f4220b3c632 100755
--- a/source/script/installswat.sh
+++ b/source/script/installswat.sh
@@ -43,7 +43,7 @@ fi
for ln in $LANGS; do
# images
- for f in $SRCDIR../swat/$ln/images/*.png; do
+ for f in $SRCDIR../swat/$ln/images/*.gif; do
if [ ! -f $f ] ; then
continue
fi
@@ -121,29 +121,6 @@ for ln in $LANGS; do
fi
done
- # javascripts
- for f in $SRCDIR../swat/$ln/js/*.js; do
- if [ ! -f $f ] ; then
- continue
- fi
- FNAME="$DESTDIR/$SWATDIR/$ln/js/`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
-
done
# Install/ remove html documentation (if html documentation tree is here)
diff --git a/source/script/mkbuildoptions.awk b/source/script/mkbuildoptions.awk
index 9c226623109..1e7b74b8d9c 100644
--- a/source/script/mkbuildoptions.awk
+++ b/source/script/mkbuildoptions.awk
@@ -242,14 +242,21 @@ END {
# add code to display the various type sizes
print " /* Output the sizes of the various types */";
print " output(screen, \"\\nType sizes:\\n\");";
- print " output(screen, \" sizeof(char): %lu\\n\",(unsigned long)sizeof(char));";
- print " output(screen, \" sizeof(int): %lu\\n\",(unsigned long)sizeof(int));";
- print " output(screen, \" sizeof(long): %lu\\n\",(unsigned long)sizeof(long));";
- print " output(screen, \" sizeof(uint8): %lu\\n\",(unsigned long)sizeof(uint8));";
- print " output(screen, \" sizeof(uint16): %lu\\n\",(unsigned long)sizeof(uint16));";
- print " output(screen, \" sizeof(uint32): %lu\\n\",(unsigned long)sizeof(uint32));";
- print " output(screen, \" sizeof(short): %lu\\n\",(unsigned long)sizeof(short));";
- print " output(screen, \" sizeof(void*): %lu\\n\",(unsigned long)sizeof(void*));";
+ print " output(screen, \" sizeof(char): %lu\\n\",(unsigned long)sizeof(char));";
+ print " output(screen, \" sizeof(int): %lu\\n\",(unsigned long)sizeof(int));";
+ print " output(screen, \" sizeof(long): %lu\\n\",(unsigned long)sizeof(long));";
+ print "#if HAVE_LONGLONG"
+ print " output(screen, \" sizeof(long long): %lu\\n\",(unsigned long)sizeof(long long));";
+ print "#endif"
+ print " output(screen, \" sizeof(uint8): %lu\\n\",(unsigned long)sizeof(uint8));";
+ print " output(screen, \" sizeof(uint16): %lu\\n\",(unsigned long)sizeof(uint16));";
+ print " output(screen, \" sizeof(uint32): %lu\\n\",(unsigned long)sizeof(uint32));";
+ print " output(screen, \" sizeof(short): %lu\\n\",(unsigned long)sizeof(short));";
+ print " output(screen, \" sizeof(void*): %lu\\n\",(unsigned long)sizeof(void*));";
+ print " output(screen, \" sizeof(size_t): %lu\\n\",(unsigned long)sizeof(size_t));";
+ print " output(screen, \" sizeof(off_t): %lu\\n\",(unsigned long)sizeof(off_t));";
+ print " output(screen, \" sizeof(ino_t): %lu\\n\",(unsigned long)sizeof(ino_t));";
+ print " output(screen, \" sizeof(dev_t): %lu\\n\",(unsigned long)sizeof(dev_t));";
##################################################
# add code to give information about modules
diff --git a/source/script/tests/selftest.sh b/source/script/tests/selftest.sh
index e7b29f76c7a..cdf5b36bfa0 100755
--- a/source/script/tests/selftest.sh
+++ b/source/script/tests/selftest.sh
@@ -15,7 +15,7 @@ PREFIX=`echo $1 | sed s+//+/+`
mkdir -p $PREFIX || exit $?
OLD_PWD=`pwd`
cd $PREFIX || exit $?
-export PREFIX_ABS=`pwd`
+PREFIX_ABS=`pwd`
cd $OLD_PWD
if [ -z "$TORTURE_MAXTIME" ]; then
@@ -29,7 +29,7 @@ export TORTURE_MAXTIME
SERVER=localhost2
SERVER_IP=127.0.0.2
-USERNAME=`whoami`
+USERNAME=`PATH=/usr/ucb:$PATH whoami`
PASSWORD=test
SRCDIR=`pwd`
@@ -46,7 +46,7 @@ LOGDIR=$PREFIX_ABS/logs
SOCKET_WRAPPER_DIR=$PREFIX/sw
CONFIGURATION="-s $CONFFILE"
-export PREFIX_ABS CONFIGURATION CONFFILE PATH SOCKET_WRAPPER_DIR DOMAIN
+export PREFIX PREFIX_ABS CONFIGURATION CONFFILE PATH SOCKET_WRAPPER_DIR DOMAIN
export PRIVATEDIR LIBDIR PIDDIR LOCKDIR LOGDIR SERVERCONFFILE
export SRCDIR SCRIPTDIR
export USERNAME PASSWORD
@@ -157,9 +157,11 @@ TORTURE4_OPTIONS="--maximum-runtime=$TORTURE_MAXTIME --option=interfaces=$TORTUR
export TORTURE4_OPTIONS
if [ x"$RUN_FROM_BUILD_FARM" = x"yes" ];then
- TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=\"torture:progress=no\""
+ TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=torture:progress=no"
fi
+TORTURE4_OPTIONS="$TORTURE4_OPTIONS --option=target:samba3=yes"
+
##
## ready to go...now loop through the tests
##
diff --git a/source/script/tests/test_posix_s3.sh b/source/script/tests/test_posix_s3.sh
index 2f5f92ee807..1e60ec76668 100755
--- a/source/script/tests/test_posix_s3.sh
+++ b/source/script/tests/test_posix_s3.sh
@@ -32,9 +32,13 @@ 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"
+tests="$base $raw"
-skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE BASE-DENY1 BASE-OPENATTR BASE-TCONDEV"
+skipped="BASE-CHARSET BASE-DEFER_OPEN BASE-DELAYWRITE BASE-DELETE BASE-OPENATTR BASE-TCONDEV"
+skipped="$skipped RAW-ACLS RAW-CLOSE RAW-COMPOSITE RAW-CONTEXT RAW-EAS"
+skipped="$skipped RAW-IOCTL RAW-MKDIR RAW-MUX RAW-NOTIFY RAW-OPEN RAW-OPLOCK"
+skipped="$skipped RAW-QFILEINFO RAW-QFSINFO RAW-RENAME RAW-SEARCH"
+skipped="$skipped RAW-SFILEINFO RAW-STREAMS RAW-UNLINK RAW-WRITE"
echo "WARNING: Skipping tests $skipped"
diff --git a/source/smbd/close.c b/source/smbd/close.c
index bc1182032d7..8a63d3b227b 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -143,54 +143,15 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
}
/****************************************************************************
- Close a file.
-
- 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.
+ Deal with removing a share mode on last close.
****************************************************************************/
-static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
+static int close_remove_share_mode(files_struct *fsp, enum file_close_type close_type)
{
- BOOL delete_file = False;
connection_struct *conn = fsp->conn;
- int saved_errno = 0;
- int err = 0;
- int err1 = 0;
+ BOOL delete_file = False;
struct share_mode_lock *lck;
- remove_pending_lock_requests_by_fid(fsp);
-
- if (fsp->aio_write_behind) {
- /*
- * If we're finishing write behind on a close we can get a write
- * error here, we must remember this.
- */
- int ret = wait_for_aio_completion(fsp);
- if (ret) {
- saved_errno = ret;
- err1 = -1;
- }
- } else {
- cancel_aio_by_fsp(fsp);
- }
-
- /*
- * If we're flushing on a close we can get a write
- * error here, we must remember this.
- */
-
- if (close_filestruct(fsp) == -1) {
- saved_errno = errno;
- err1 = -1;
- }
-
- if (fsp->print_file) {
- print_fsp_end(fsp, close_type);
- file_free(fsp);
- return 0;
- }
-
/*
* Lock the share entries, and determine if we should delete
* on close. If so delete whilst the lock is still in effect.
@@ -200,12 +161,12 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
- DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name));
+ DEBUG(0, ("close_remove_share_mode: Could not get share mode lock for file %s\n", fsp->fsp_name));
return EINVAL;
}
if (!del_share_mode(lck, fsp)) {
- DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name));
+ DEBUG(0, ("close_remove_share_mode: Could not delete share entry for file %s\n", fsp->fsp_name));
}
delete_file = (lck->delete_on_close | lck->initial_delete_on_close);
@@ -236,13 +197,13 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
lck->delete_token) {
SMB_STRUCT_STAT sbuf;
- DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
+ DEBUG(5,("close_remove_share_mode: 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");
+ smb_panic("close_remove_share_mode: file %s. failed to push sec_ctx.\n");
}
set_sec_ctx(lck->delete_token->uid,
@@ -253,17 +214,17 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
/* We can only delete the file if the name we have
is still valid and hasn't been renamed. */
-
+
if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
- DEBUG(5,("close_file: file %s. Delete on close was set "
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
"and stat failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
} else {
if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
- DEBUG(5,("close_file: file %s. Delete on close was set and "
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set and "
"dev and/or inode does not match\n",
fsp->fsp_name ));
- DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f "
+ DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, inode = %.0f "
"stat dev = %x, inode = %.0f\n",
fsp->fsp_name,
(unsigned int)fsp->dev, (double)fsp->inode,
@@ -277,21 +238,80 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
* we log this but not at debug level zero.
*/
- DEBUG(5,("close_file: file %s. Delete on close was set "
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
"and unlink failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
}
}
/* unbecome user. */
pop_sec_ctx();
-
+
process_pending_change_notify_queue((time_t)0);
}
TALLOC_FREE(lck);
+ return 0;
+}
+
+/****************************************************************************
+ Close a file.
+
+ 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, enum file_close_type close_type)
+{
+ connection_struct *conn = fsp->conn;
+ int saved_errno = 0;
+ int err = 0;
+ int err1 = 0;
- if(fsp->oplock_type)
+ remove_pending_lock_requests_by_fid(fsp);
+
+ if (fsp->aio_write_behind) {
+ /*
+ * If we're finishing write behind on a close we can get a write
+ * error here, we must remember this.
+ */
+ int ret = wait_for_aio_completion(fsp);
+ if (ret) {
+ saved_errno = ret;
+ err1 = -1;
+ }
+ } else {
+ cancel_aio_by_fsp(fsp);
+ }
+
+ /*
+ * If we're flushing on a close we can get a write
+ * error here, we must remember this.
+ */
+
+ if (close_filestruct(fsp) == -1) {
+ saved_errno = errno;
+ err1 = -1;
+ }
+
+ if (fsp->print_file) {
+ print_fsp_end(fsp, close_type);
+ file_free(fsp);
+ return 0;
+ }
+
+ /* If this is an old DOS or FCB open and we have multiple opens on
+ the same handle we only have one share mode. Ensure we only remove
+ the share mode on the last close. */
+
+ if (fsp->fh->ref_count == 1) {
+ /* Should we return on error here... ? */
+ close_remove_share_mode(fsp, close_type);
+ }
+
+ if(fsp->oplock_type) {
release_file_oplock(fsp);
+ }
locking_close_file(fsp);
@@ -323,9 +343,6 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
conn->num_files_open,
(err == -1 || err1 == -1) ? strerror(saved_errno) : ""));
- if (fsp->fsp_name)
- string_free(&fsp->fsp_name);
-
file_free(fsp);
if (err == -1 || err1 == -1) {
@@ -410,11 +427,6 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
* Do the code common to files and directories.
*/
close_filestruct(fsp);
-
- if (fsp->fsp_name) {
- string_free(&fsp->fsp_name);
- }
-
file_free(fsp);
return 0;
}
@@ -429,10 +441,6 @@ static int close_stat(files_struct *fsp)
* Do the code common to files and directories.
*/
close_filestruct(fsp);
-
- if (fsp->fsp_name)
- string_free(&fsp->fsp_name);
-
file_free(fsp);
return 0;
}
@@ -447,6 +455,8 @@ int close_file(files_struct *fsp, enum file_close_type close_type)
return close_directory(fsp, close_type);
else if (fsp->is_stat)
return close_stat(fsp);
+ else if (fsp->fake_file_handle != NULL)
+ return close_fake_file(fsp);
else
return close_normal_file(fsp, close_type);
}
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index cd6c1b0bda3..27a4182c220 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -719,7 +719,7 @@ struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
}
/****************************************************************************
- Check a filetype for being valid.
+ Check that a file matches a particular file type.
****************************************************************************/
BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index 1356baf1a81..b4f1f02b724 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -156,3 +156,9 @@ void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
talloc_destroy((*fh)->mem_ctx);
(*fh) = NULL;
}
+
+int close_fake_file(files_struct *fsp)
+{
+ file_free(fsp);
+ return 0;
+}
diff --git a/source/smbd/files.c b/source/smbd/files.c
index ba4baa93b10..e020d8e13a6 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -32,8 +32,6 @@ static files_struct *Files;
/* a fsp to use when chaining */
static files_struct *chain_fsp = NULL;
-/* a fsp to use to save when breaking an oplock. */
-static files_struct *oplock_save_chain_fsp = NULL;
static int files_used;
@@ -109,7 +107,7 @@ files_struct *file_new(connection_struct *conn)
fsp->fh->fd = -1;
fsp->conn = conn;
- fsp->file_id = get_gen_count();
+ fsp->fh->file_id = get_gen_count();
GetTimeOfDay(&fsp->open_time);
first_file = (i+1) % real_max_open_files;
@@ -238,7 +236,7 @@ void file_dump_open_table(void)
for (fsp=Files;fsp;fsp=fsp->next,count++) {
DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
- count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->file_id,
+ count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->file_id,
(unsigned int)fsp->dev, (double)fsp->inode ));
}
}
@@ -277,7 +275,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i
/* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
if (fsp->dev == dev &&
fsp->inode == inode &&
- fsp->file_id == file_id ) {
+ fsp->fh->file_id == file_id ) {
if (count > 10) {
DLIST_PROMOTE(Files, fsp);
}
@@ -287,7 +285,7 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i
(fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, (unsigned int)fsp->file_id,
+ (double)fsp->inode, (unsigned int)fsp->fh->file_id,
(unsigned int)fsp->oplock_type ));
smb_panic("file_find_dif\n");
}
@@ -503,24 +501,6 @@ void file_chain_reset(void)
}
/****************************************************************************
- Save the chained fsp - done when about to do an oplock break.
-****************************************************************************/
-
-void file_chain_save(void)
-{
- oplock_save_chain_fsp = chain_fsp;
-}
-
-/****************************************************************************
- Restore the chained fsp - done after an oplock break.
-****************************************************************************/
-
-void file_chain_restore(void)
-{
- chain_fsp = oplock_save_chain_fsp;
-}
-
-/****************************************************************************
Duplicate the file handle part for a DOS or FCB open.
****************************************************************************/
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index 1b5a5f39c72..7f9505606cc 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -433,8 +433,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
START_PROFILE(SMBtrans);
- if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
- SVAL(inbuf, smb_mid)))) {
+ result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
+ if (!NT_STATUS_IS_OK(result)) {
DEBUG(2, ("Got invalid trans request: %s\n",
nt_errstr(result)));
END_PROFILE(SMBtrans);
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index 4606441c3a9..700aa2ae81c 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -419,7 +419,10 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_
return False;
}
- if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) {
+ if ( !( strequal(dp.servicename, lp_servicename(SNUM(conn)))
+ || ( strequal(dp.servicename, HOMES_NAME)
+ && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) )
+ {
return False;
}
diff --git a/source/smbd/notify.c b/source/smbd/notify.c
index b2d0fc33262..829ca3a736d 100644
--- a/source/smbd/notify.c
+++ b/source/smbd/notify.c
@@ -135,7 +135,19 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT
}
/****************************************************************************
- Return true if there are pending change notifies.
+ Set the current change notify timeout to the lowest value across all service
+ values.
+****************************************************************************/
+
+void set_change_notify_timeout(int val)
+{
+ if (val > 0) {
+ cnotify->select_time = MIN(cnotify->select_time, val);
+ }
+}
+
+/****************************************************************************
+ Longest time to sleep for before doing a change notify scan.
****************************************************************************/
int change_notify_timeout(void)
diff --git a/source/smbd/notify_hash.c b/source/smbd/notify_hash.c
index a98a028fae0..0787a3eec5e 100644
--- a/source/smbd/notify_hash.c
+++ b/source/smbd/notify_hash.c
@@ -81,6 +81,11 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
return True;
}
+ if (lp_change_notify_timeout(SNUM(conn)) <= 0) {
+ /* It change notify timeout has been disabled, never scan the directory. */
+ return True;
+ }
+
/*
* If we are to watch for changes that are only stored
* in inodes of files, not in the directory inode, we must
@@ -179,9 +184,17 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,
{
struct change_data *data = (struct change_data *)datap;
struct change_data data2;
+ int cnto = lp_change_notify_timeout(SNUM(conn));
+
+ if (t && cnto <= 0) {
+ /* Change notify turned off on this share.
+ * Only scan when (t==0) - we think something changed. */
+ return False;
+ }
- if (t && t < data->last_check_time + lp_change_notify_timeout())
+ if (t && t < data->last_check_time + cnto) {
return False;
+ }
if (!change_to_user(conn,vuid))
return True;
@@ -201,8 +214,9 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,
return True;
}
- if (t)
+ if (t) {
data->last_check_time = t;
+ }
change_to_root_user();
@@ -229,7 +243,7 @@ struct cnotify_fns *hash_notify_init(void)
cnotify.register_notify = hash_register_notify;
cnotify.check_notify = hash_check_notify;
cnotify.remove_notify = hash_remove_notify;
- cnotify.select_time = lp_change_notify_timeout();
+ cnotify.select_time = 60; /* Start with 1 minute default. */
cnotify.notification_fd = -1;
return &cnotify;
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 839eb7bb279..3cdc4997b23 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -2719,6 +2719,7 @@ static int handle_nttrans(connection_struct *conn,
/* 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,
@@ -2728,7 +2729,10 @@ static int handle_nttrans(connection_struct *conn,
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,
@@ -2737,7 +2741,10 @@ static int handle_nttrans(connection_struct *conn,
&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,
@@ -2746,7 +2753,10 @@ static int handle_nttrans(connection_struct *conn,
&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,
@@ -2755,7 +2765,10 @@ static int handle_nttrans(connection_struct *conn,
&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,
@@ -2764,8 +2777,10 @@ static int handle_nttrans(connection_struct *conn,
&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,
@@ -2774,8 +2789,11 @@ static int handle_nttrans(connection_struct *conn,
&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,
@@ -2784,7 +2802,10 @@ static int handle_nttrans(connection_struct *conn,
&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,
@@ -2793,7 +2814,9 @@ static int handle_nttrans(connection_struct *conn,
&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",
@@ -2827,8 +2850,8 @@ int reply_nttrans(connection_struct *conn,
return ERROR_DOS(ERRSRV,ERRaccess);
}
- if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
- SVAL(inbuf, smb_mid)))) {
+ result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
+ if (!NT_STATUS_IS_OK(result)) {
DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
END_PROFILE(SMBnttrans);
return ERROR_NT(result);
@@ -2881,7 +2904,7 @@ int reply_nttrans(connection_struct *conn,
DEBUG(0,("reply_nttrans: data malloc fail for %u "
"bytes !\n", state->total_data));
TALLOC_FREE(state);
- END_PROFILE(SMBtrans);
+ END_PROFILE(SMBnttrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
@@ -2901,7 +2924,7 @@ int reply_nttrans(connection_struct *conn,
"bytes !\n", state->total_param));
SAFE_FREE(state->data);
TALLOC_FREE(state);
- END_PROFILE(SMBtrans);
+ END_PROFILE(SMBnttrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
diff --git a/source/smbd/open.c b/source/smbd/open.c
index edc5bc98b6e..3d537b2f394 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -1308,7 +1308,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
*/
#if defined(O_SYNC)
- if (create_options & FILE_WRITE_THROUGH) {
+ if ((create_options & FILE_WRITE_THROUGH) && lp_strict_sync(SNUM(conn))) {
flags2 |= O_SYNC;
}
#endif /* O_SYNC */
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index 70e5bf4d727..42c64a28435 100644
--- a/source/smbd/oplock.c
+++ b/source/smbd/oplock.c
@@ -20,6 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define DBGC_CLASS DBGC_LOCKING
#include "includes.h"
/* Current number of oplocks we have outstanding. */
@@ -88,7 +89,7 @@ void process_kernel_oplocks(fd_set *pfds)
/* Put the kernel break info into the message. */
SDEV_T_VAL(msg,0,fsp->dev);
SINO_T_VAL(msg,8,fsp->inode);
- SIVAL(msg,16,fsp->file_id);
+ SIVAL(msg,16,fsp->fh->file_id);
/* Don't need to be root here as we're only ever
sending to ourselves. */
@@ -118,10 +119,11 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type)
exclusive_oplocks_open++;
}
- DEBUG(5,("set_file_oplock: granted oplock on file %s, dev = %x, inode = %.0f, file_id = %lu, \
-tv_sec = %x, tv_usec = %x\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id,
- (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec ));
+ DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, "
+ "tv_sec = %x, tv_usec = %x\n",
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id, (int)fsp->open_time.tv_sec,
+ (int)fsp->open_time.tv_usec ));
return True;
}
@@ -191,7 +193,7 @@ BOOL remove_oplock(files_struct *fsp)
ret = remove_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("remove_oplock: failed to remove share oplock for "
- "file %s fnum %d, dev = %x, inode = %.0f\n",
+ "file %s fnum %d, 0x%x/%.0f\n",
fsp->fsp_name, fsp->fnum, (unsigned int)dev,
(double)inode));
}
@@ -292,8 +294,8 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un
files_struct *fsp = NULL;
if( DEBUGLVL( 3 ) ) {
- dbgtext( "initial_break_processing: called for dev = 0x%x, inode = %.0f file_id = %lu\n",
- (unsigned int)dev, (double)inode, file_id);
+ dbgtext( "initial_break_processing: called for 0x%x/%.0f/%u\n",
+ (unsigned int)dev, (double)inode, (int)file_id);
dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n",
exclusive_oplocks_open, level_II_oplocks_open );
}
@@ -331,7 +333,7 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un
if( DEBUGLVL( 3 ) ) {
dbgtext( "initial_break_processing: file %s ", fsp->fsp_name );
dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n",
- (unsigned int)dev, (double)inode, fsp->file_id );
+ (unsigned int)dev, (double)inode, fsp->fh->file_id );
dbgtext( "Allowing break to succeed regardless.\n" );
}
return NULL;
@@ -403,9 +405,9 @@ static void process_oplock_async_level2_break_message(int msg_type, struct proce
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, buf);
- DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%d\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
- (int)msg.share_file_id));
+ DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id));
fsp = initial_break_processing(msg.dev, msg.inode,
msg.share_file_id);
@@ -490,9 +492,9 @@ static void process_oplock_break_message(int msg_type, struct process_id src,
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, buf);
- DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%d\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
- (int)msg.share_file_id));
+ DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id));
fsp = initial_break_processing(msg.dev, msg.inode,
msg.share_file_id);
@@ -693,9 +695,10 @@ static void process_oplock_break_response(int msg_type, struct process_id src,
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, buf);
- DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%u mid %u\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
- (unsigned int)msg.share_file_id, (unsigned int)msg.op_mid));
+ DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id,
+ (unsigned int)msg.op_mid));
/* Here's the hack from open.c, store the mid in the 'port' field */
schedule_deferred_open_smb_message(msg.op_mid);
@@ -719,8 +722,9 @@ static void process_open_retry_message(int msg_type, struct process_id src,
/* De-linearize incoming message. */
message_to_share_mode_entry(&msg, buf);
- DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f mid %u\n",
- (int)procid_to_pid(&src), (unsigned int)msg.dev, (double)msg.inode,
+ DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id,
(unsigned int)msg.op_mid));
schedule_deferred_open_smb_message(msg.op_mid);
diff --git a/source/smbd/oplock_irix.c b/source/smbd/oplock_irix.c
index 83883444a7b..248d9020283 100644
--- a/source/smbd/oplock_irix.c
+++ b/source/smbd/oplock_irix.c
@@ -18,6 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define DBGC_CLASS DBGC_LOCKING
#include "includes.h"
#if HAVE_KERNEL_OPLOCKS_IRIX
@@ -144,7 +145,7 @@ static files_struct *irix_oplock_receive_message(fd_set *fds)
DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
"received for dev = %x, inode = %.0f\n, file_id = %ul",
- (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
+ (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id ));
return fsp;
}
@@ -159,18 +160,18 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type)
if(errno != EAGAIN) {
DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \
inode = %.0f, file_id = %ul. Error was %s\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id,
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id,
strerror(errno) ));
} else {
DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
inode = %.0f, file_id = %ul. Another process had the file open.\n",
- fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
+ fsp->fsp_name, fsp->fh->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id ));
}
return False;
}
DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id));
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id));
return True;
}
@@ -189,7 +190,7 @@ static void irix_release_kernel_oplock(files_struct *fsp)
int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \
oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, fsp->file_id, state );
+ (double)fsp->inode, fsp->fh->file_id, state );
}
/*
@@ -200,7 +201,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " );
dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, fsp->file_id, strerror(errno) );
+ (double)fsp->inode, fsp->fh->file_id, strerror(errno) );
}
}
}
diff --git a/source/smbd/oplock_linux.c b/source/smbd/oplock_linux.c
index ab0c08f7fcc..f186c13ebdd 100644
--- a/source/smbd/oplock_linux.c
+++ b/source/smbd/oplock_linux.c
@@ -18,6 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define DBGC_CLASS DBGC_LOCKING
#include "includes.h"
#if HAVE_KERNEL_OPLOCKS_LINUX
@@ -163,7 +164,7 @@ inode = %.0f. (%s)\n",
}
DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n",
- fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id));
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->fh->file_id));
return True;
}
@@ -182,7 +183,7 @@ static void linux_release_kernel_oplock(files_struct *fsp)
int state = fcntl(fsp->fh->fd, F_GETLEASE, 0);
dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \
oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, fsp->file_id, state );
+ (double)fsp->inode, fsp->fh->file_id, state );
}
/*
@@ -193,7 +194,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " );
dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->dev,
- (double)fsp->inode, fsp->file_id, strerror(errno) );
+ (double)fsp->inode, fsp->fh->file_id, strerror(errno) );
}
}
}
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 8d33c1deed1..73b0ebb4b32 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -155,10 +155,9 @@ int register_vuid(auth_serversupplied_info *server_info,
{
user_struct *vuser = NULL;
- /* Ensure no vuid gets registered in share level security. */
+ /* Paranoia check. */
if(lp_security() == SEC_SHARE) {
- data_blob_free(&session_key);
- return UID_FIELD_INVALID;
+ smb_panic("Tried to register uid in security=share\n");
}
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
@@ -189,6 +188,11 @@ int register_vuid(auth_serversupplied_info *server_info,
vuser->vuid = next_vuid;
if (!server_info) {
+ /*
+ * This happens in an unfinished NTLMSSP session setup. We
+ * need to allocate a vuid between the first and second calls
+ * to NTLMSSP.
+ */
next_vuid++;
num_validated_vuids++;
diff --git a/source/smbd/process.c b/source/smbd/process.c
index aaf98203a25..440d0ac0a50 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -43,7 +43,6 @@ int max_send = BUFFER_SIZE;
int max_recv = BUFFER_SIZE;
extern int last_message;
-extern userdom_struct current_user_info;
extern int smb_read_error;
SIG_ATOMIC_T reload_after_sighup = 0;
SIG_ATOMIC_T got_sig_term = 0;
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 0524078310f..387ed4a47f4 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -1085,12 +1085,13 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
BOOL mask_contains_wcard = False;
BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
+ START_PROFILE(SMBsearch);
+
if (lp_posix_pathnames()) {
+ END_PROFILE(SMBsearch);
return reply_unknown(inbuf, outbuf);
}
- START_PROFILE(SMBsearch);
-
*mask = *directory = *fname = 0;
/* If we were called as SMBffirst then we must expect close. */
@@ -1284,12 +1285,13 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
NTSTATUS err;
BOOL path_contains_wcard = False;
+ START_PROFILE(SMBfclose);
+
if (lp_posix_pathnames()) {
+ END_PROFILE(SMBfclose);
return reply_unknown(inbuf, outbuf);
}
- START_PROFILE(SMBfclose);
-
outsize = set_message(outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
@@ -1517,13 +1519,13 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
close_file(fsp,ERROR_CLOSE);
- END_PROFILE(SMBntcreateX);
+ END_PROFILE(SMBopenX);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
if (retval < 0) {
close_file(fsp,ERROR_CLOSE);
- END_PROFILE(SMBwrite);
+ END_PROFILE(SMBopenX);
return ERROR_NT(NT_STATUS_DISK_FULL);
}
size = get_allocation_size(conn,fsp,&sbuf);
@@ -2629,7 +2631,6 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
nread = read_file(fsp,data,startpos,smb_maxcnt);
if (nread < 0) {
- END_PROFILE(SMBreadX);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
diff --git a/source/smbd/server.c b/source/smbd/server.c
index b76ade957c2..d16579f24a8 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -22,6 +22,8 @@
#include "includes.h"
+static_decl_rpc;
+
static int am_parent = 1;
/* the last message the was processed */
diff --git a/source/smbd/service.c b/source/smbd/service.c
index ba87d0743da..cb9bfcc27ae 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -523,8 +523,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
return NULL;
}
+ conn->nt_user_token = NULL;
+
if (lp_guest_only(snum)) {
const char *guestname = lp_guestaccount();
+ NTSTATUS status2;
+ char *found_username;
guest = True;
pass = getpwnam_alloc(NULL, guestname);
if (!pass) {
@@ -534,11 +538,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
*status = NT_STATUS_NO_SUCH_USER;
return NULL;
}
- fstrcpy(user,pass->pw_name);
+ status2 = create_token_from_username(NULL, pass->pw_name, True,
+ &conn->uid, &conn->gid,
+ &found_username,
+ &conn->nt_user_token);
+ if (!NT_STATUS_IS_OK(status2)) {
+ conn_free(conn);
+ *status = status2;
+ return NULL;
+ }
+ fstrcpy(user, found_username);
+ string_set(&conn->user,user);
conn->force_user = True;
- conn->uid = pass->pw_uid;
- conn->gid = pass->pw_gid;
- string_set(&conn->user,pass->pw_name);
TALLOC_FREE(pass);
DEBUG(3,("Guest only user %s\n",user));
} else if (vuser) {
@@ -570,6 +581,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
fstrcpy(user,vuser->user.unix_name);
guest = vuser->guest;
} else if (lp_security() == SEC_SHARE) {
+ NTSTATUS status2;
+ char *found_username;
/* add it as a possible user name if we
are in share mode security */
add_session_user(lp_servicename(snum));
@@ -582,12 +595,18 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
return NULL;
}
pass = Get_Pwnam(user);
+ status2 = create_token_from_username(NULL, pass->pw_name, True,
+ &conn->uid, &conn->gid,
+ &found_username,
+ &conn->nt_user_token);
+ if (!NT_STATUS_IS_OK(status2)) {
+ conn_free(conn);
+ *status = status2;
+ return NULL;
+ }
+ fstrcpy(user, found_username);
+ string_set(&conn->user,user);
conn->force_user = True;
- conn->uid = pass->pw_uid;
- conn->gid = pass->pw_gid;
- string_set(&conn->user, pass->pw_name);
- fstrcpy(user, pass->pw_name);
-
} else {
DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
conn_free(conn);
@@ -626,7 +645,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->aio_write_behind_list = NULL;
string_set(&conn->dirpath,"");
string_set(&conn->user,user);
- conn->nt_user_token = NULL;
conn->read_only = lp_readonly(conn->service);
conn->admin_user = False;
@@ -930,6 +948,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
dbgtext( "(pid %d)\n", (int)sys_getpid() );
}
+ /* Setup the minimum value for a change notify wait time (seconds). */
+ set_change_notify_timeout(lp_change_notify_timeout(snum));
+
/* we've finished with the user stuff - go back to root */
change_to_root_user();
return(conn);
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 7c90263a5b0..46acb20bdad 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -96,7 +96,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
char *p;
if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- ERROR_NT(nt_status);
+ ERROR_NT(nt_status_squash(nt_status));
} else {
set_message(outbuf,4,0,True);
@@ -176,6 +176,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
DATA_BLOB nullblob = data_blob(NULL, 0);
fstring real_username;
BOOL map_domainuser_to_guest = False;
+ BOOL username_was_mapped;
PAC_LOGON_INFO *logon_info = NULL;
ZERO_STRUCT(ticket);
@@ -186,21 +187,21 @@ static int reply_spnego_kerberos(connection_struct *conn,
mem_ctx = talloc_init("reply_spnego_kerberos");
if (mem_ctx == NULL)
- return ERROR_NT(NT_STATUS_NO_MEMORY);
+ return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
talloc_destroy(mem_ctx);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
- ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
+ ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
data_blob_free(&ticket);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(1,("Failed to verify incoming ticket!\n"));
talloc_destroy(mem_ctx);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
DEBUG(3,("Ticket name is [%s]\n", client));
@@ -212,7 +213,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&session_key);
SAFE_FREE(client);
talloc_destroy(mem_ctx);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
*p = 0;
@@ -233,7 +234,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&session_key);
SAFE_FREE(client);
talloc_destroy(mem_ctx);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
}
@@ -288,7 +289,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
/* lookup the passwd struct, create a new user if necessary */
- map_username( user );
+ username_was_mapped = map_username( user );
pw = smb_getpwnam( mem_ctx, user, real_username, True );
if (!pw) {
@@ -311,7 +312,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
talloc_destroy(mem_ctx);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
}
@@ -322,7 +323,7 @@ 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_info3(mem_ctx, real_username, real_username, domain,
+ ret = make_server_info_info3(mem_ctx, real_username, domain,
&server_info, &logon_info->info3);
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(1,("make_server_info_info3 failed: %s!\n",
@@ -331,7 +332,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
talloc_destroy(mem_ctx);
- return ERROR_NT(ret);
+ return ERROR_NT(nt_status_squash(ret));
}
} else {
@@ -344,7 +345,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
talloc_destroy(mem_ctx);
- return ERROR_NT(ret);
+ return ERROR_NT(nt_status_squash(ret));
}
/* make_server_info_pw does not set the domain. Without this
@@ -355,6 +356,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
pdb_set_domain(server_info->sam_account, domain, PDB_SET);
}
}
+
+ server_info->was_mapped |= username_was_mapped;
/* we need to build the token for the user. make_server_info_guest()
already does this */
@@ -367,7 +370,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&session_key);
TALLOC_FREE( mem_ctx );
TALLOC_FREE( server_info );
- return ERROR_NT(ret);
+ return ERROR_NT(nt_status_squash(ret));
}
}
@@ -520,7 +523,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
/* only look at the first OID for determining the mechToken --
@@ -567,7 +570,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(nt_status);
+ return ERROR_NT(nt_status_squash(nt_status));
}
nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -604,7 +607,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
if (!*auth_ntlmssp_state) {
@@ -612,7 +615,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
invalidate_vuid(vuid);
/* auth before negotiatiate? */
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -664,7 +667,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
if (data_blob_len == 0) {
/* an invalid request */
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
bufrem = smb_bufrem(inbuf, p);
@@ -696,14 +699,14 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
if (!vuser) {
vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
if (vuid == UID_FIELD_INVALID ) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
vuser = get_partial_auth_user_struct(vuid);
}
if (!vuser) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
SSVAL(outbuf,smb_uid,vuid);
@@ -733,7 +736,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(nt_status);
+ return ERROR_NT(nt_status_squash(nt_status));
}
}
@@ -754,7 +757,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
data_blob_free(&blob1);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
/****************************************************************************
@@ -846,7 +849,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
(SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
if (!global_spnego_negotiated) {
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
if (SVAL(inbuf,smb_vwv4) == 0) {
@@ -864,7 +867,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
if (doencrypt) {
@@ -925,11 +928,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* check for nasty tricks */
if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
}
/* Save the lanman2 password and the NT md4 password. */
@@ -1007,7 +1010,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
fstrcpy(sub_user, user);
} else {
@@ -1038,7 +1041,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
} else if (doencrypt) {
if (!negprot_global_auth_context) {
DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
lm_resp, nt_resp);
@@ -1087,7 +1090,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* Ensure we can't possible take a code path leading to a null defref. */
if (!server_info) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
nt_status = create_local_token(server_info);
@@ -1124,20 +1127,30 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* register the name and uid as being validated, so further connections
to a uid can get through without a password, on the same VC */
- /* register_vuid keeps the server info */
- sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
- data_blob_free(&nt_resp);
- data_blob_free(&lm_resp);
-
- if (sess_vuid == UID_FIELD_INVALID) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
+ if (lp_security() == SEC_SHARE) {
+ sess_vuid = UID_FIELD_INVALID;
+ data_blob_free(&session_key);
+ TALLOC_FREE(server_info);
+ } else {
+ /* register_vuid keeps the server info */
+ sess_vuid = register_vuid(server_info, session_key,
+ nt_resp.data ? nt_resp : lm_resp,
+ sub_user);
+ if (sess_vuid == UID_FIELD_INVALID) {
+ data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
+ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ }
- /* current_user_info is changed on new vuid */
- reload_services( True );
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
- sessionsetup_start_signing_engine(server_info, inbuf);
+ sessionsetup_start_signing_engine(server_info, inbuf);
+ }
+ data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
+
SSVAL(outbuf,smb_uid,sess_vuid);
SSVAL(inbuf,smb_uid,sess_vuid);
diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c
index df5f445587f..468f61560b9 100644
--- a/source/smbd/share_access.c
+++ b/source/smbd/share_access.c
@@ -204,7 +204,8 @@ BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum)
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));
+ DEBUG(10, ("User %s not in 'valid users'\n",
+ username));
return False;
}
}
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index b229807bfdc..fc14772c57c 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -5011,6 +5011,7 @@ int handle_trans2(connection_struct *conn,
/* Now we must call the relevant TRANS2 function */
switch(state->call) {
case TRANSACT2_OPEN:
+ {
START_PROFILE_NESTED(Trans2_open);
outsize = call_trans2open(
conn, inbuf, outbuf, bufsize,
@@ -5019,8 +5020,10 @@ int handle_trans2(connection_struct *conn,
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,
@@ -5029,8 +5032,10 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_findfirst);
break;
+ }
case TRANSACT2_FINDNEXT:
+ {
START_PROFILE_NESTED(Trans2_findnext);
outsize = call_trans2findnext(
conn, inbuf, outbuf, size, bufsize,
@@ -5039,8 +5044,10 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_findnext);
break;
+ }
case TRANSACT2_QFSINFO:
+ {
START_PROFILE_NESTED(Trans2_qfsinfo);
outsize = call_trans2qfsinfo(
conn, inbuf, outbuf, size, bufsize,
@@ -5049,8 +5056,10 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_qfsinfo);
break;
+ }
case TRANSACT2_SETFSINFO:
+ {
START_PROFILE_NESTED(Trans2_setfsinfo);
outsize = call_trans2setfsinfo(
conn, inbuf, outbuf, size, bufsize,
@@ -5059,9 +5068,11 @@ int handle_trans2(connection_struct *conn,
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, size, bufsize, state->call,
@@ -5070,8 +5081,11 @@ int handle_trans2(connection_struct *conn,
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, size, bufsize, state->call,
@@ -5080,8 +5094,10 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_setpathinfo);
break;
+ }
case TRANSACT2_FINDNOTIFYFIRST:
+ {
START_PROFILE_NESTED(Trans2_findnotifyfirst);
outsize = call_trans2findnotifyfirst(
conn, inbuf, outbuf, size, bufsize,
@@ -5090,8 +5106,10 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_findnotifyfirst);
break;
+ }
case TRANSACT2_FINDNOTIFYNEXT:
+ {
START_PROFILE_NESTED(Trans2_findnotifynext);
outsize = call_trans2findnotifynext(
conn, inbuf, outbuf, size, bufsize,
@@ -5100,7 +5118,10 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_findnotifynext);
break;
+ }
+
case TRANSACT2_MKDIR:
+ {
START_PROFILE_NESTED(Trans2_mkdir);
outsize = call_trans2mkdir(
conn, inbuf, outbuf, size, bufsize,
@@ -5109,8 +5130,10 @@ int handle_trans2(connection_struct *conn,
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, size, bufsize,
@@ -5119,7 +5142,10 @@ int handle_trans2(connection_struct *conn,
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, size, bufsize,
@@ -5128,11 +5154,14 @@ int handle_trans2(connection_struct *conn,
state->max_data_return);
END_PROFILE_NESTED(Trans2_ioctl);
break;
+ }
+
default:
/* Error in request */
DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
outsize = ERROR_DOS(ERRSRV,ERRerror);
}
+
return outsize;
}
@@ -5154,8 +5183,8 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
START_PROFILE(SMBtrans2);
- if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
- SVAL(inbuf, smb_mid)))) {
+ result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
+ if (!NT_STATUS_IS_OK(result)) {
DEBUG(2, ("Got invalid trans2 request: %s\n",
nt_errstr(result)));
END_PROFILE(SMBtrans2);
@@ -5246,7 +5275,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
"bytes !\n", state->total_param));
SAFE_FREE(state->data);
TALLOC_FREE(state);
- END_PROFILE(SMBtrans);
+ END_PROFILE(SMBtrans2);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
@@ -5269,7 +5298,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
SAFE_FREE(state->data);
SAFE_FREE(state->param);
TALLOC_FREE(state);
- END_PROFILE(SMBtrans);
+ END_PROFILE(SMBtrans2);
return outsize;
}
@@ -5379,7 +5408,7 @@ int reply_transs2(connection_struct *conn,
if ((state->received_param < state->total_param) ||
(state->received_data < state->total_data)) {
- END_PROFILE(SMBtranss);
+ END_PROFILE(SMBtranss2);
return -1;
}
@@ -5396,7 +5425,7 @@ int reply_transs2(connection_struct *conn,
TALLOC_FREE(state);
if (outsize == 0) {
- END_PROFILE(SMBtranss);
+ END_PROFILE(SMBtranss2);
return(ERROR_DOS(ERRSRV,ERRnosupport));
}
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c
index 55bf146c20f..ee251c17d8d 100644
--- a/source/smbd/vfs-wrap.c
+++ b/source/smbd/vfs-wrap.c
@@ -549,7 +549,7 @@ int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t
{
int saved_errno = errno; /* We might get ENOSYS */
if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
- END_PROFILE(syscall_chmod);
+ END_PROFILE(syscall_fchmod);
return result;
}
/* Error - return the old errno. */
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 9a6327b33b5..2c9403a0790 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -27,6 +27,8 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
+static_decl_vfs;
+
struct vfs_init_function_entry {
char *name;
vfs_op_tuple *vfs_op_tuples;
diff --git a/source/tdb/spinlock.c b/source/tdb/spinlock.c
index a487ee2a103..e42a6901c71 100644
--- a/source/tdb/spinlock.c
+++ b/source/tdb/spinlock.c
@@ -266,15 +266,6 @@ static void yield_cpu(void)
#endif
}
-static int this_is_smp(void)
-{
-#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN)
- return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
-#else
- return 0;
-#endif
-}
-
/*
* GENERIC
*/
diff --git a/source/torture/msgtest.c b/source/torture/msgtest.c
index f7c47ddbbf8..035214b3a96 100644
--- a/source/torture/msgtest.c
+++ b/source/torture/msgtest.c
@@ -25,6 +25,24 @@
static int pong_count;
+
+/* samba4 timeval functions */
+
+double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
+{
+ return (tv2->tv_sec - tv1->tv_sec) +
+ (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
+}
+
+/**
+ return the number of seconds elapsed since a given time
+*/
+double timeval_elapsed(const struct timeval *tv)
+{
+ struct timeval tv2 = timeval_current();
+ return timeval_elapsed2(tv, &tv2);
+}
+
/****************************************************************************
a useful function for testing the message system
****************************************************************************/
@@ -39,6 +57,8 @@ void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
int i, n;
char buf[12];
+ load_case_tables();
+
setup_logging(argv[0],True);
lp_load(dyn_CONFIGFILE,False,False,False,True);
@@ -83,7 +103,42 @@ void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
if (pong_count != 2) {
fprintf(stderr, "Duplicate filter failed (%d).\n", pong_count);
- exit(1);
+ }
+
+ /* Speed testing */
+
+ pong_count = 0;
+
+ {
+ struct timeval tv = timeval_current();
+ size_t timelimit = n;
+ size_t ping_count = 0;
+
+ printf("Sending pings for %d seconds\n", timelimit);
+ while (timeval_elapsed(&tv) < timelimit) {
+ if(message_send_pid(pid_to_procid(pid), MSG_PING,
+ buf, 11, False)) ping_count++;
+ if(message_send_pid(pid_to_procid(pid), MSG_PING,
+ NULL, 0, False)) ping_count++;
+
+ while (ping_count > pong_count + 20) {
+ message_dispatch();
+ }
+ }
+
+ printf("waiting for %d remaining replies (done %d)\n",
+ ping_count - pong_count, pong_count);
+ while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
+ message_dispatch();
+ }
+
+ if (ping_count != pong_count) {
+ fprintf(stderr, "ping test failed! received %d, sent %d\n",
+ pong_count, ping_count);
+ }
+
+ printf("ping rate of %.0f messages/sec\n",
+ (ping_count+pong_count)/timeval_elapsed(&tv));
}
return (0);
diff --git a/source/utils/net.c b/source/utils/net.c
index 1389885ba17..27b64aa96e5 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -233,6 +233,29 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
}
}
+/****************************************************************************
+connect to \\server\ipc$ using KRB5
+****************************************************************************/
+NTSTATUS connect_to_ipc_krb5(struct cli_state **c,
+ struct in_addr *server_ip, const char *server_name)
+{
+ NTSTATUS nt_status;
+
+ nt_status = cli_full_connection(c, NULL, server_name,
+ server_ip, opt_port,
+ "IPC$", "IPC",
+ opt_user_name, opt_workgroup,
+ opt_password, CLI_FULL_CONNECTION_USE_KERBEROS,
+ Undefined, NULL);
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ } else {
+ DEBUG(1,("Cannot connect to server using kerberos. Error was %s\n", nt_errstr(nt_status)));
+ return nt_status;
+ }
+}
+
/**
* Connect a server and open a given pipe
*
@@ -304,8 +327,9 @@ int net_use_machine_password(void)
return 0;
}
-BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name)
+BOOL net_find_server(const char *domain, unsigned flags, struct in_addr *server_ip, char **server_name)
{
+ const char *d = domain ? domain : opt_target_workgroup;
if (opt_host) {
*server_name = SMB_STRDUP(opt_host);
@@ -325,23 +349,22 @@ BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_na
} else if (flags & NET_FLAGS_PDC) {
struct in_addr pdc_ip;
- if (get_pdc_ip(opt_target_workgroup, &pdc_ip)) {
+ if (get_pdc_ip(d, &pdc_ip)) {
fstring dc_name;
if (is_zero_ip(pdc_ip))
return False;
- if ( !name_status_find(opt_target_workgroup, 0x1b, 0x20, pdc_ip, dc_name) )
+ if ( !name_status_find(d, 0x1b, 0x20, pdc_ip, dc_name) )
return False;
*server_name = SMB_STRDUP(dc_name);
*server_ip = pdc_ip;
}
-
} else if (flags & NET_FLAGS_DMB) {
struct in_addr msbrow_ip;
/* if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
- if (!resolve_name(opt_target_workgroup, &msbrow_ip, 0x1B)) {
+ if (!resolve_name(d, &msbrow_ip, 0x1B)) {
DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
return False;
} else {
@@ -350,7 +373,7 @@ BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_na
*server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip));
} else if (flags & NET_FLAGS_MASTER) {
struct in_addr brow_ips;
- if (!resolve_name(opt_target_workgroup, &brow_ips, 0x1D)) {
+ if (!resolve_name(d, &brow_ips, 0x1D)) {
/* go looking for workgroups */
DEBUG(1,("Unable to resolve master browser via name lookup\n"));
return False;
@@ -387,17 +410,27 @@ BOOL net_find_pdc(struct in_addr *server_ip, fstring server_name, const char *do
return False;
}
+struct cli_state *net_make_ipc_connection( unsigned flags )
+{
+ return net_make_ipc_connection_ex( NULL, NULL, NULL, flags );
+}
-struct cli_state *net_make_ipc_connection(unsigned flags)
+struct cli_state *net_make_ipc_connection_ex( const char *domain, const char *server,
+ struct in_addr *ip, unsigned flags)
{
char *server_name = NULL;
struct in_addr server_ip;
struct cli_state *cli = NULL;
NTSTATUS nt_status;
- if (!net_find_server(flags, &server_ip, &server_name)) {
- d_fprintf(stderr, "\nUnable to find a suitable server\n");
- return NULL;
+ if ( !server || !ip ) {
+ if (!net_find_server(domain, flags, &server_ip, &server_name)) {
+ d_fprintf(stderr, "Unable to find a suitable server\n");
+ return NULL;
+ }
+ } else {
+ server_name = SMB_STRDUP( server );
+ server_ip = *ip;
}
if (flags & NET_FLAGS_ANONYMOUS) {
@@ -563,6 +596,26 @@ static int net_setlocalsid(int argc, const char **argv)
return 0;
}
+static int net_setdomainsid(int argc, const char **argv)
+{
+ DOM_SID sid;
+
+ if ( (argc != 1)
+ || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
+ || (!string_to_sid(&sid, argv[0]))
+ || (sid.num_auths != 4)) {
+ d_printf("usage: net setdomainsid S-1-5-21-x-y-z\n");
+ return 1;
+ }
+
+ if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
+ DEBUG(0,("Can't store domain SID.\n"));
+ return 1;
+ }
+
+ return 0;
+}
+
static int net_getdomainsid(int argc, const char **argv)
{
DOM_SID domain_sid;
@@ -760,6 +813,7 @@ static struct functable net_func[] = {
{"CACHE", net_cache},
{"GETLOCALSID", net_getlocalsid},
{"SETLOCALSID", net_setlocalsid},
+ {"SETDOMAINSID", net_setdomainsid},
{"GETDOMAINSID", net_getdomainsid},
{"MAXRID", net_maxrid},
{"IDMAP", net_idmap},
diff --git a/source/utils/net.h b/source/utils/net.h
index fc3167012d6..d037871f82e 100644
--- a/source/utils/net.h
+++ b/source/utils/net.h
@@ -62,30 +62,23 @@ struct rpc_sh_cmd {
const char *help;
};
+enum netdom_domain_t { ND_TYPE_NT4, ND_TYPE_AD };
+
/* INCLUDE FILES */
#include "utils/net_proto.h"
/* MACROS & DEFINES */
-#define NET_FLAGS_MASTER 1
-#define NET_FLAGS_DMB 2
-
-/* Would it be insane to set 'localhost' as the default
- remote host for this operation?
-
- For example, localhost is insane for a 'join' operation.
-*/
-#define NET_FLAGS_LOCALHOST_DEFAULT_INSANE 4
-
-/* We want to find the PDC only */
-#define NET_FLAGS_PDC 8
-
-/* We want an anonymous connection */
-#define NET_FLAGS_ANONYMOUS 16
-
-/* don't open an RPC pipe */
-#define NET_FLAGS_NO_PIPE 32
+#define NET_FLAGS_MASTER 0x00000001
+#define NET_FLAGS_DMB 0x00000002
+#define NET_FLAGS_LOCALHOST_DEFAULT_INSANE 0x00000004 /* Would it be insane to set 'localhost'
+ as the default remote host for this
+ operation? For example, localhost
+ is insane for a 'join' operation. */
+#define NET_FLAGS_PDC 0x00000008 /* PDC only */
+#define NET_FLAGS_ANONYMOUS 0x00000010 /* use an anonymous connection */
+#define NET_FLAGS_NO_PIPE 0x00000020 /* don't open an RPC pipe */
/* net share operation modes */
#define NET_MODE_SHARE_MIGRATE 1
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 11e7ae02826..e701803d17e 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -4,6 +4,7 @@
Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+ Copyright (C) 2006 Gerald (Jerry) Carter (jerry@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
@@ -23,6 +24,22 @@
#include "includes.h"
#include "utils/net.h"
+/* Macro for checking RPC error codes to make things more readable */
+
+#if 0
+#define CHECK_RPC_ERR(rpc, msg) \
+ if (!NT_STATUS_IS_OK(result = rpc)) { \
+ DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
+ goto done; \
+ }
+
+#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
+ if (!NT_STATUS_IS_OK(result = rpc)) { \
+ DEBUG(0, debug_args); \
+ goto done; \
+ }
+
+#endif
#ifdef HAVE_ADS
int net_ads_usage(int argc, const char **argv)
@@ -55,6 +72,8 @@ int net_ads_usage(int argc, const char **argv)
"\n\tperform a raw LDAP search and dump the results\n"
"\nnet ads dn"\
"\n\tperform a raw LDAP search and dump attributes of a particular DN\n"
+"\nnet ads sid"\
+"\n\tperform a raw LDAP search and dump attributes of a particular SID\n"
"\nnet ads keytab"\
"\n\tcreates and updates the kerberos system keytab file\n"
);
@@ -63,6 +82,78 @@ int net_ads_usage(int argc, const char **argv)
/*
+ do a cldap netlogon query
+*/
+static int net_ads_cldap_netlogon(ADS_STRUCT *ads)
+{
+ struct cldap_netlogon_reply reply;
+
+ if ( !ads_cldap_netlogon( inet_ntoa(ads->ldap_ip), ads->server.realm, &reply ) ) {
+ d_fprintf(stderr, "CLDAP query failed!\n");
+ return -1;
+ }
+
+ d_printf("Information for Domain Controller: %s\n\n",
+ inet_ntoa(ads->ldap_ip));
+
+ d_printf("Response Type: ");
+ switch (reply.type) {
+ case SAMLOGON_AD_UNK_R:
+ d_printf("SAMLOGON\n");
+ break;
+ case SAMLOGON_AD_R:
+ d_printf("SAMLOGON_USER\n");
+ break;
+ default:
+ d_printf("0x%x\n", reply.type);
+ break;
+ }
+ d_printf("GUID: %s\n",
+ smb_uuid_string_static(smb_uuid_unpack_static(reply.guid)));
+ d_printf("Flags:\n"
+ "\tIs a PDC: %s\n"
+ "\tIs a GC of the forest: %s\n"
+ "\tIs an LDAP server: %s\n"
+ "\tSupports DS: %s\n"
+ "\tIs running a KDC: %s\n"
+ "\tIs running time services: %s\n"
+ "\tIs the closest DC: %s\n"
+ "\tIs writable: %s\n"
+ "\tHas a hardware clock: %s\n"
+ "\tIs a non-domain NC serviced by LDAP server: %s\n",
+ (reply.flags & ADS_PDC) ? "yes" : "no",
+ (reply.flags & ADS_GC) ? "yes" : "no",
+ (reply.flags & ADS_LDAP) ? "yes" : "no",
+ (reply.flags & ADS_DS) ? "yes" : "no",
+ (reply.flags & ADS_KDC) ? "yes" : "no",
+ (reply.flags & ADS_TIMESERV) ? "yes" : "no",
+ (reply.flags & ADS_CLOSEST) ? "yes" : "no",
+ (reply.flags & ADS_WRITABLE) ? "yes" : "no",
+ (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no",
+ (reply.flags & ADS_NDNC) ? "yes" : "no");
+
+ printf("Forest:\t\t\t%s\n", reply.forest);
+ printf("Domain:\t\t\t%s\n", reply.domain);
+ printf("Domain Controller:\t%s\n", reply.hostname);
+
+ printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain);
+ printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname);
+
+ if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk);
+ if (*reply.user_name) printf("User name:\t%s\n", reply.user_name);
+
+ printf("Site Name:\t\t%s\n", reply.site_name);
+ printf("Site Name (2):\t\t%s\n", reply.site_name_2);
+
+ d_printf("NT Version: %d\n", reply.version);
+ d_printf("LMNT Token: %.2x\n", reply.lmnt_token);
+ d_printf("LM20 Token: %.2x\n", reply.lm20_token);
+
+ return 0;
+}
+
+
+/*
this implements the CLDAP based netlogon lookup requests
for finding the domain controller of a ADS domain
*/
@@ -70,8 +161,12 @@ static int net_ads_lookup(int argc, const char **argv)
{
ADS_STRUCT *ads;
ADS_STATUS status;
+ const char *realm = NULL;
+
+ if ( strequal(lp_workgroup(), opt_target_workgroup ) )
+ realm = lp_realm();
- ads = ads_init(NULL, opt_target_workgroup, opt_host);
+ ads = ads_init(realm, opt_target_workgroup, opt_host);
if (ads) {
ads->auth.flags |= ADS_AUTH_NO_BIND;
}
@@ -87,7 +182,7 @@ static int net_ads_lookup(int argc, const char **argv)
ads->ldap_port = 389;
}
- return ads_cldap_netlogon(ads);
+ return net_ads_cldap_netlogon(ads);
}
@@ -96,14 +191,7 @@ static int net_ads_info(int argc, const char **argv)
{
ADS_STRUCT *ads;
- /* if netbios is disabled we have to default to the realm from smb.conf */
-
- if ( lp_disable_netbios() && *lp_realm() )
- ads = ads_init(lp_realm(), opt_target_workgroup, opt_host);
- else
- ads = ads_init(NULL, opt_target_workgroup, opt_host);
-
- if (ads) {
+ if ( (ads = ads_init(lp_realm(), opt_target_workgroup, opt_host)) != NULL ) {
ads->auth.flags |= ADS_AUTH_NO_BIND;
}
@@ -114,6 +202,13 @@ static int net_ads_info(int argc, const char **argv)
return -1;
}
+ /* Try to set the server's current time since we didn't do a full
+ TCP LDAP session initially */
+
+ if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
+ d_fprintf( stderr, "Failed to get server's current time!\n");
+ }
+
d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
d_printf("Realm: %s\n", ads->config.realm);
@@ -206,10 +301,19 @@ retry:
int net_ads_check(void)
{
ADS_STRUCT *ads;
+ ADS_STATUS status;
- ads = ads_startup();
- if (!ads)
+ if ( (ads = ads_init( lp_realm(), lp_workgroup(), NULL )) == NULL ) {
return -1;
+ }
+
+ ads->auth.flags |= ADS_AUTH_NO_BIND;
+
+ status = ads_connect(ads);
+ if ( !ADS_ERR_OK(status) ) {
+ return -1;
+ }
+
ads_destroy(&ads);
return 0;
}
@@ -220,28 +324,38 @@ int net_ads_check(void)
static int net_ads_workgroup(int argc, const char **argv)
{
ADS_STRUCT *ads;
- TALLOC_CTX *ctx;
- const char *workgroup;
+ ADS_STATUS status;
+ const char *realm = NULL;
+ struct cldap_netlogon_reply reply;
- if (!(ads = ads_startup())) return -1;
+ if ( strequal(lp_workgroup(), opt_target_workgroup ) )
+ realm = lp_realm();
- if (!(ctx = talloc_init("net_ads_workgroup"))) {
- ads_destroy(&ads);
- return -1;
+ ads = ads_init(realm, opt_target_workgroup, opt_host);
+ if (ads) {
+ ads->auth.flags |= ADS_AUTH_NO_BIND;
}
- if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
- d_fprintf(stderr, "Failed to find workgroup for realm '%s'\n",
- ads->config.realm);
- talloc_destroy(ctx);
- ads_destroy(&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) {
+ ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
+ ads->ldap_port = 389;
+ }
+
+ if ( !ads_cldap_netlogon( inet_ntoa(ads->ldap_ip), ads->server.realm, &reply ) ) {
+ d_fprintf(stderr, "CLDAP query failed!\n");
return -1;
}
- d_printf("Workgroup: %s\n", workgroup);
+ d_printf("Workgroup: %s\n", reply.netbios_domain);
- talloc_destroy(ctx);
ads_destroy(&ads);
+
return 0;
}
@@ -471,7 +585,7 @@ int net_ads_user(int argc, const char **argv)
rc = ads_do_search_all_fn(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
- "(objectclass=user)",
+ "(objectCategory=user)",
opt_long_list_entries ? longattrs :
shortattrs, usergrp_display,
disp_fields);
@@ -595,7 +709,7 @@ int net_ads_group(int argc, const char **argv)
"\n-----------------------------\n");
rc = ads_do_search_all_fn(ads, ads->config.bind_path,
LDAP_SCOPE_SUBTREE,
- "(objectclass=group)",
+ "(objectCategory=group)",
opt_long_list_entries ? longattrs :
shortattrs, usergrp_display,
disp_fields);
@@ -634,35 +748,70 @@ static int net_ads_status(int argc, const char **argv)
return 0;
}
+/*******************************************************************
+ Leave an AD domain. Windows XP disables the machine account.
+ We'll try the same. The old code would do an LDAP delete.
+ That only worked using the machine creds because added the machine
+ with full control to the computer object's ACL.
+*******************************************************************/
static int net_ads_leave(int argc, const char **argv)
{
ADS_STRUCT *ads = NULL;
- ADS_STATUS rc;
+ int ret = -1;
+ struct cli_state *cli = NULL;
+ TALLOC_CTX *ctx;
+ DOM_SID *dom_sid = NULL;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
return -1;
}
- if (!opt_password) {
- net_use_machine_password();
+ if (!(ctx = talloc_init("net_ads_leave"))) {
+ DEBUG(0, ("Could not initialise talloc context\n"));
+ return -1;
}
+ /* The finds a DC and takes care of getting the
+ user creds if necessary */
+
if (!(ads = ads_startup())) {
return -1;
}
- rc = ads_leave_realm(ads, global_myname());
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, "Failed to delete host '%s' from the '%s' realm.\n",
+ /* make RPC calls here */
+
+ if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, &ads->ldap_ip,
+ ads->config.ldap_server_name)) )
+ {
+ goto done;
+ }
+
+ saf_store( cli->server_domain, cli->desthost );
+
+ if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, &dom_sid )) ) {
+ goto done;
+ }
+
+ if ( !NT_STATUS_IS_OK(netdom_leave_domain( ctx, cli, dom_sid )) ) {
+ d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n",
global_myname(), ads->config.realm);
- ads_destroy(&ads);
- return -1;
+ goto done;
}
+
+ d_printf("Disabled account for '%s' in realm '%s'\n",
+ global_myname(), ads->config.realm);
+
+ ret = 0;
+
+done:
+ if ( cli )
+ cli_shutdown(cli);
- d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
ads_destroy(&ads);
- return 0;
+ TALLOC_FREE( ctx );
+
+ return ret;
}
static int net_ads_join_ok(void)
@@ -701,125 +850,252 @@ int net_ads_testjoin(int argc, const char **argv)
return 0;
}
-/*
- join a domain using ADS
- */
-int net_ads_join(int argc, const char **argv)
-{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- char *password;
- char *machine_account = NULL;
- char *tmp_password;
- const char *org_unit = NULL;
- char *dn;
- void *res;
- DOM_SID dom_sid;
- char *ou_str;
- uint32 sec_channel_type = SEC_CHAN_WKSTA;
- uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
- const char *short_domain_name = NULL;
- TALLOC_CTX *ctx = NULL;
+/*******************************************************************
+ Simple configu checks before beginning the join
+ ********************************************************************/
- 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");
+static int check_ads_config( void )
+{
+ if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
+ d_printf("Host is not configured as a member server.\n");
return -1;
}
if (strlen(global_myname()) > 15) {
- d_printf("Our netbios name can only be 15 chars long, \"%s\""
- " is %d chars long\n",
+ d_printf("Our netbios name can be at most 15 chars long, "
+ "\"%s\" is %d chars long\n",
global_myname(), strlen(global_myname()));
return -1;
}
- if (argc > 0) {
- org_unit = argv[0];
+ if ( lp_security() == SEC_ADS && !*lp_realm()) {
+ d_fprintf(stderr, "realm must be set in in smb.conf for ADS "
+ "join to succeed.\n");
+ return -1;
}
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
return -1;
}
+
+ return 0;
+}
- tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
- password = SMB_STRDUP(tmp_password);
+/*******************************************************************
+ Do the domain join
+ ********************************************************************/
- if (!(ads = ads_startup())) {
- return -1;
+static int net_join_domain( TALLOC_CTX *ctx, const char *servername,
+ struct in_addr *ip, DOM_SID **dom_sid, const char *password )
+{
+ int ret = -1;
+ struct cli_state *cli = NULL;
+
+ if ( !NT_STATUS_IS_OK(connect_to_ipc_krb5(&cli, ip, servername)) )
+ goto done;
+
+ saf_store( cli->server_domain, cli->desthost );
+
+ if ( !NT_STATUS_IS_OK(netdom_get_domain_sid( ctx, cli, dom_sid )) )
+ goto done;
+
+ if ( !NT_STATUS_IS_OK(netdom_join_domain( ctx, cli, *dom_sid,
+ password, ND_TYPE_AD )) )
+ {
+ goto done;
}
+
+ ret = 0;
- if (!*lp_realm()) {
- d_fprintf(stderr, "realm must be set in in smb.conf for ADS join to succeed.\n");
- ads_destroy(&ads);
- return -1;
+done:
+ if ( cli )
+ cli_shutdown(cli);
+
+ return ret;
+}
+
+/*******************************************************************
+ Set a machines dNSHostName and servicePrincipalName attributes
+ ********************************************************************/
+
+static ADS_STATUS net_set_machine_spn(TALLOC_CTX *ctx, ADS_STRUCT *ads_s )
+{
+ ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *host_upn, *new_dn;
+ ADS_MODLIST mods;
+ const char *servicePrincipalName[3] = {NULL, NULL, NULL};
+ char *psp;
+ fstring my_fqdn;
+ LDAPMessage *res = NULL;
+ char *dn_string = NULL;
+ const char *machine_name = global_myname();
+ int count;
+
+ if ( !machine_name ) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ /* Find our DN */
+
+ status = ads_find_machine_acct(ads_s, (void **)(void *)&res, machine_name);
+ if (!ADS_ERR_OK(status))
+ return status;
+
+ if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
+ DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
+
+ if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
+ DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
+ goto done;
+ }
+
+ new_dn = talloc_strdup(ctx, dn_string);
+ ads_memfree(ads_s, dn_string);
+ if (!new_dn) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
}
- if (strcmp(ads->config.realm, lp_realm()) != 0) {
- d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf (%s) DO NOT match. Aborting join\n", ads->config.realm, lp_realm());
- ads_destroy(&ads);
- return -1;
+ /* Windows only creates HOST/shortname & HOST/fqdn. We create
+ the UPN as well so that 'kinit -k' will work. You can only
+ request a TGT for entries with a UPN in AD. */
+
+ if ( !(psp = talloc_asprintf(ctx, "HOST/%s", machine_name)) )
+ goto done;
+ strupper_m(psp);
+ servicePrincipalName[0] = psp;
+
+ name_to_fqdn(my_fqdn, machine_name);
+ strlower_m(my_fqdn);
+ if ( !(psp = talloc_asprintf(ctx, "HOST/%s", my_fqdn)) )
+ goto done;
+ servicePrincipalName[1] = psp;
+
+ if (!(host_upn = talloc_asprintf(ctx, "%s@%s", servicePrincipalName[0], ads_s->config.realm)))
+ goto done;
+
+ /* now do the mods */
+
+ if (!(mods = ads_init_mods(ctx))) {
+ goto done;
}
+
+ /* fields of primary importance */
+
+ ads_mod_str(ctx, &mods, "dNSHostName", my_fqdn);
+ ads_mod_strlist(ctx, &mods, "servicePrincipalName", servicePrincipalName);
+
+ status = ads_gen_mod(ads_s, new_dn, mods);
+
+done:
+ ads_msgfree(ads_s, res);
+
+ return status;
+}
+
+
+/*******************************************************************
+ join a domain using ADS (LDAP mods)
+ ********************************************************************/
+
+static ADS_STATUS net_precreate_machine_acct( ADS_STRUCT *ads, const char *ou )
+{
+ ADS_STATUS rc = ADS_ERROR(LDAP_SERVER_DOWN);
+ char *dn, *ou_str;
+ LDAPMessage *res = NULL;
- ou_str = ads_ou_string(ads,org_unit);
+ ou_str = ads_ou_string(ads, ou);
asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
free(ou_str);
- rc = ads_search_dn(ads, &res, dn, NULL);
+ rc = ads_search_dn(ads, (void**)&res, dn, NULL);
ads_msgfree(ads, res);
- if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
- d_fprintf(stderr, "ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
- org_unit, dn);
- ads_destroy(&ads);
- return -1;
+ if (ADS_ERR_OK(rc)) {
+ /* Attempt to create the machine account and bail if this fails.
+ Assume that the admin wants exactly what they requested */
+
+ rc = ads_create_machine_acct( ads, global_myname(), dn );
+ if ( rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_ALREADY_EXISTS ) {
+ rc = ADS_SUCCESS;
+ }
}
- free(dn);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
- ads_destroy(&ads);
- return -1;
- }
+ SAFE_FREE( dn );
- rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
- ads_destroy(&ads);
+ return rc;
+}
+
+/*******************************************************************
+ join a domain using ADS (LDAP mods)
+ ********************************************************************/
+
+int net_ads_join(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
+ char *machine_account = NULL;
+ const char *short_domain_name = NULL;
+ char *tmp_password, *password;
+ struct cldap_netlogon_reply cldap_reply;
+ TALLOC_CTX *ctx;
+ DOM_SID *domain_sid = NULL;
+
+ if ( check_ads_config() != 0 ) {
+ d_fprintf(stderr, "Invalid configuration. Exiting....\n");
return -1;
}
- rc = ads_domain_sid(ads, &dom_sid);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, "ads_domain_sid: %s\n", ads_errstr(rc));
- ads_destroy(&ads);
+ if ( (ads = ads_startup()) == NULL ) {
return -1;
}
- if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
- d_fprintf(stderr, "asprintf failed\n");
+ if (strcmp(ads->config.realm, lp_realm()) != 0) {
+ d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf "
+ "(%s) DO NOT match. Aborting join\n", ads->config.realm,
+ lp_realm());
ads_destroy(&ads);
return -1;
}
- rc = ads_set_machine_password(ads, machine_account, password);
- if (!ADS_ERR_OK(rc)) {
- d_fprintf(stderr, "ads_set_machine_password: %s\n", ads_errstr(rc));
- ads_destroy(&ads);
+ if (!(ctx = talloc_init("net_ads_join"))) {
+ DEBUG(0, ("Could not initialise talloc context\n"));
return -1;
}
+
+ /* If we were given an OU, try to create the machine in the OU account
+ first and then do the normal RPC join */
+
+ if ( argc > 0 ) {
+ status = net_precreate_machine_acct( ads, argv[0] );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf( stderr, "Failed to pre-create the machine object "
+ "in OU %s.\n", argv[0]);
+ ads_destroy( &ads );
+ return -1;
+ }
+ }
+
+ /* Do the domain join here */
+
+ tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+ password = talloc_strdup(ctx, tmp_password);
- /* make sure we get the right workgroup */
-
- if ( !(ctx = talloc_init("net ads join")) ) {
- d_fprintf(stderr, "talloc_init() failed!\n");
- ads_destroy(&ads);
+ if ( net_join_domain( ctx, ads->config.ldap_server_name, &ads->ldap_ip, &domain_sid, password ) != 0 ) {
+ d_fprintf(stderr, "Failed to join domain!\n");
return -1;
}
- rc = ads_workgroup_name(ads, ctx, &short_domain_name);
- if ( ADS_ERR_OK(rc) ) {
+ /* Check the short name of the domain */
+
+ ZERO_STRUCT( cldap_reply );
+
+ if ( ads_cldap_netlogon( ads->config.ldap_server_name,
+ ads->server.realm, &cldap_reply ) )
+ {
+ short_domain_name = talloc_strdup( ctx, cldap_reply.netbios_domain );
if ( !strequal(lp_workgroup(), short_domain_name) ) {
d_printf("The workgroup in smb.conf does not match the short\n");
d_printf("domain name obtained from the server.\n");
@@ -831,46 +1107,52 @@ int net_ads_join(int argc, const char **argv)
}
d_printf("Using short domain name -- %s\n", short_domain_name);
-
- /* HACK ALRET! Store the sid and password under bother the lp_workgroup()
+
+ /* HACK ALERT! Store the sid and password under both the lp_workgroup()
value from smb.conf and the string returned from the server. The former is
neede to bootstrap winbindd's first connection to the DC to get the real
short domain name --jerry */
-
- if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
- DEBUG(1,("Failed to save domain sid\n"));
+
+ if ( (netdom_store_machine_account( lp_workgroup(), domain_sid, password ) == -1)
+ || (netdom_store_machine_account( short_domain_name, domain_sid, password ) == -1) )
+ {
ads_destroy(&ads);
return -1;
}
- if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
- DEBUG(1,("Failed to save machine password\n"));
- ads_destroy(&ads);
- return -1;
- }
+ /* Verify that everything is ok */
-#ifdef HAVE_KRB5
- if (!kerberos_derive_salting_principal(machine_account)) {
- DEBUG(1,("Failed to determine salting principal\n"));
- ads_destroy(&ads);
+ if ( net_rpc_join_ok(short_domain_name, ads->config.ldap_server_name, &ads->ldap_ip) != 0 ) {
+ d_fprintf(stderr, "Failed to verify membership in domain!\n");
return -1;
+ }
+
+ /* create the dNSHostName & servicePrincipalName values */
+
+ status = net_set_machine_spn( ctx, ads );
+ if ( !ADS_ERR_OK(status) ) {
+ d_fprintf(stderr, "Failed to set servicePrincipalNames. Only NTLM authentication will be possible.\n");
+ d_fprintf(stderr, "Please ensure that the DNS domain of this server matches the AD domain,\n");
+ d_fprintf(stderr, "Or rejoin with using Domain Admin credentials.\n");
+
+ /* don't fail */
}
- if (!kerberos_derive_cifs_salting_principals()) {
- DEBUG(1,("Failed to determine salting principals\n"));
+#if defined(HAVE_KRB5)
+ if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
+ d_fprintf(stderr, "asprintf failed\n");
ads_destroy(&ads);
return -1;
}
-#endif
- if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
- DEBUG(1,("Failed to save domain sid\n"));
+ if (!kerberos_derive_salting_principal(machine_account)) {
+ DEBUG(1,("Failed to determine salting principal\n"));
ads_destroy(&ads);
return -1;
}
- if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
- DEBUG(1,("Failed to save machine password\n"));
+ if (!kerberos_derive_cifs_salting_principals()) {
+ DEBUG(1,("Failed to determine salting principals\n"));
ads_destroy(&ads);
return -1;
}
@@ -879,18 +1161,20 @@ int net_ads_join(int argc, const char **argv)
if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
DEBUG(1,("Error creating host keytab!\n"));
}
+#endif
d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
- SAFE_FREE(password);
SAFE_FREE(machine_account);
- if ( ctx ) {
- talloc_destroy(ctx);
- }
+ TALLOC_FREE( ctx );
ads_destroy(&ads);
+
return 0;
}
+/*******************************************************************
+ ********************************************************************/
+
int net_ads_printer_usage(int argc, const char **argv)
{
d_printf(
@@ -908,6 +1192,9 @@ int net_ads_printer_usage(int argc, const char **argv)
return -1;
}
+/*******************************************************************
+ ********************************************************************/
+
static int net_ads_printer_search(int argc, const char **argv)
{
ADS_STRUCT *ads;
@@ -1388,6 +1675,71 @@ static int net_ads_dn(int argc, const char **argv)
return 0;
}
+/*
+ help for net ads sid search
+*/
+static int net_ads_sid_usage(int argc, const char **argv)
+{
+ d_printf(
+ "\nnet ads sid <sid> <attributes...>\n"\
+ "\nperform a raw LDAP search on a ADS server and dump the results\n"\
+ "The SID is in string format, and the attributes are a list of LDAP fields \n"\
+ "to show in the results\n\n"\
+ "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
+ );
+ net_common_flags_usage(argc, argv);
+ return -1;
+}
+
+
+/*
+ general ADS search function. Useful in diagnosing problems in ADS
+*/
+static int net_ads_sid(int argc, const char **argv)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ const char *sid_string;
+ const char **attrs;
+ void *res = NULL;
+ DOM_SID sid;
+
+ if (argc < 1) {
+ return net_ads_sid_usage(argc, argv);
+ }
+
+ if (!(ads = ads_startup())) {
+ return -1;
+ }
+
+ sid_string = argv[0];
+ attrs = (argv + 1);
+
+ if (!string_to_sid(&sid, sid_string)) {
+ d_fprintf(stderr, "could not convert sid\n");
+ ads_destroy(&ads);
+ return -1;
+ }
+
+ rc = ads_search_retry_sid(ads, &res, &sid, attrs);
+ if (!ADS_ERR_OK(rc)) {
+ d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
+ ads_destroy(&ads);
+ return -1;
+ }
+
+ d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
+
+ /* dump the results */
+ ads_dump(ads, res);
+
+ ads_msgfree(ads, res);
+ ads_destroy(&ads);
+
+ return 0;
+}
+
+
static int net_ads_keytab_usage(int argc, const char **argv)
{
d_printf(
@@ -1479,6 +1831,7 @@ int net_ads_help(int argc, const char **argv)
#if 0
{"INFO", net_ads_info},
{"JOIN", net_ads_join},
+ {"JOIN2", net_ads_join2},
{"LEAVE", net_ads_leave},
{"STATUS", net_ads_status},
{"PASSWORD", net_ads_password},
@@ -1505,6 +1858,7 @@ int net_ads(int argc, const char **argv)
{"PRINTER", net_ads_printer},
{"SEARCH", net_ads_search},
{"DN", net_ads_dn},
+ {"SID", net_ads_sid},
{"WORKGROUP", net_ads_workgroup},
{"LOOKUP", net_ads_lookup},
{"KEYTAB", net_ads_keytab},
diff --git a/source/utils/net_domain.c b/source/utils/net_domain.c
new file mode 100644
index 00000000000..ae8d6b6c552
--- /dev/null
+++ b/source/utils/net_domain.c
@@ -0,0 +1,338 @@
+/*
+ Samba Unix/Linux SMB client library
+ net ads commands
+ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
+ Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
+ Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+ Copyright (C) 2006 Gerald (Jerry) Carter (jerry@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"
+
+/* Macro for checking RPC error codes to make things more readable */
+
+#define CHECK_RPC_ERR(rpc, msg) \
+ if (!NT_STATUS_IS_OK(result = rpc)) { \
+ DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
+ goto done; \
+ }
+
+#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
+ if (!NT_STATUS_IS_OK(result = rpc)) { \
+ DEBUG(0, debug_args); \
+ goto done; \
+ }
+
+/*******************************************************************
+ Leave an AD domain. Windows XP disables the machine account.
+ We'll try the same. The old code would do an LDAP delete.
+ That only worked using the machine creds because added the machine
+ with full control to the computer object's ACL.
+*******************************************************************/
+
+NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
+ DOM_SID *dom_sid )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND sam_pol, domain_pol, user_pol;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ char *acct_name;
+ uint32 flags = 0x3e8;
+ const char *const_acct_name;
+ uint32 user_rid;
+ uint32 num_rids, *name_types, *user_rids;
+ SAM_USERINFO_CTR ctr, *qctr = NULL;
+ SAM_USER_INFO_16 p16;
+
+ /* Open the domain */
+
+ if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
+ DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
+ nt_errstr(status) ));
+ return status;
+ }
+
+ status = rpccli_samr_connect(pipe_hnd, mem_ctx,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+
+ status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+ /* Create domain user */
+
+ acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
+ strlower_m(acct_name);
+ const_acct_name = acct_name;
+
+ status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
+ &domain_pol, flags, 1, &const_acct_name,
+ &num_rids, &user_rids, &name_types);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+ if ( name_types[0] != SID_NAME_USER) {
+ DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
+ return NT_STATUS_INVALID_WORKSTATION;
+ }
+
+ user_rid = user_rids[0];
+
+ /* Open handle on user */
+
+ status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
+ if ( !NT_STATUS_IS_OK(status) ) {
+ goto done;
+ }
+
+ /* Get user info */
+
+ status = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, 16, &qctr);
+ if ( !NT_STATUS_IS_OK(status) ) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+ goto done;
+ }
+
+ /* now disable and setuser info */
+
+ ZERO_STRUCT(ctr);
+ ctr.switch_value = 16;
+ ctr.info.id16 = &p16;
+
+ p16.acb_info = qctr->info.id16->acb_info | ACB_DISABLED;
+
+ status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16,
+ &cli->user_session_key, &ctr);
+
+ rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+
+done:
+ rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+ rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
+
+ cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
+
+ return status;
+}
+
+/*******************************************************************
+ Store the machine password and domain SID
+ ********************************************************************/
+
+int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char *pw )
+{
+ if (!secrets_store_domain_sid(domain, sid)) {
+ DEBUG(1,("Failed to save domain sid\n"));
+ return -1;
+ }
+
+ if (!secrets_store_machine_password(pw, domain, SEC_CHAN_WKSTA)) {
+ DEBUG(1,("Failed to save machine password\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, DOM_SID **sid )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND lsa_pol;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ char *domain = NULL;
+
+ if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status)) == NULL ) {
+ DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
+ nt_errstr(status) ));
+ return status;
+ }
+
+ status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+ status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx,
+ &lsa_pol, 5, &domain, sid);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+ 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"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Do the domain join
+ ********************************************************************/
+
+NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
+ DOM_SID *dom_sid, const char *clear_pw,
+ enum netdom_domain_t dom_type )
+{
+ struct rpc_pipe_client *pipe_hnd = NULL;
+ POLICY_HND sam_pol, domain_pol, user_pol;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ char *acct_name;
+ const char *const_acct_name;
+ uint32 user_rid;
+ uint32 num_rids, *name_types, *user_rids;
+ uint32 flags = 0x3e8;
+ uint32 acb_info = ACB_WSTRUST;
+ uchar pwbuf[516];
+ SAM_USERINFO_CTR ctr;
+ SAM_USER_INFO_24 p24;
+ SAM_USER_INFO_16 p16;
+ uchar md4_trust_password[16];
+
+ /* Open the domain */
+
+ if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
+ DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
+ nt_errstr(status) ));
+ return status;
+ }
+
+ status = rpccli_samr_connect(pipe_hnd, mem_ctx,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+
+ status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+ /* Create domain user */
+
+ acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
+ strlower_m(acct_name);
+ const_acct_name = acct_name;
+
+ /* Don't try to set any acb_info flags other than ACB_WSTRUST */
+
+ status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
+ acct_name, acb_info, 0xe005000b, &user_pol, &user_rid);
+
+ if ( !NT_STATUS_IS_OK(status)
+ && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS))
+ {
+ d_fprintf(stderr, "Creation of workstation account failed\n");
+
+ /* If NT_STATUS_ACCESS_DENIED then we have a valid
+ username/password combo but the user does not have
+ administrator access. */
+
+ if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
+ d_fprintf(stderr, "User specified does not have administrator privileges\n");
+
+ return status;
+ }
+
+ /* We *must* do this.... don't ask... */
+
+ if (NT_STATUS_IS_OK(status)) {
+ rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+ }
+
+ status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
+ &domain_pol, flags, 1, &const_acct_name,
+ &num_rids, &user_rids, &name_types);
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
+
+ if ( name_types[0] != SID_NAME_USER) {
+ DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
+ return NT_STATUS_INVALID_WORKSTATION;
+ }
+
+ user_rid = user_rids[0];
+
+ /* Open handle on user */
+
+ status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
+
+ /* Create a random machine account password */
+
+ E_md4hash( clear_pw, md4_trust_password);
+ encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
+
+ /* Set password on machine account */
+
+ ZERO_STRUCT(ctr);
+ ZERO_STRUCT(p24);
+
+ init_sam_user_info24(&p24, (char *)pwbuf,24);
+
+ ctr.switch_value = 24;
+ ctr.info.id24 = &p24;
+
+ status = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
+ 24, &cli->user_session_key, &ctr);
+
+ /* Why do we have to try to (re-)set the ACB to be the same as what
+ we passed in the samr_create_dom_user() call? When a NT
+ workstation is joined to a domain by an administrator the
+ acb_info is set to 0x80. For a normal user with "Add
+ workstations to the domain" rights the acb_info is 0x84. I'm
+ not sure whether it is supposed to make a difference or not. NT
+ seems to cope with either value so don't bomb out if the set
+ userinfo2 level 0x10 fails. -tpot */
+
+ ZERO_STRUCT(ctr);
+ ctr.switch_value = 16;
+ ctr.info.id16 = &p16;
+
+ /* Fill in the additional account flags now */
+
+ acb_info |= ACB_PWNOEXP;
+ if ( dom_type == ND_TYPE_AD ) {
+#if !defined(ENCTYPE_ARCFOUR_HMAC)
+ acb_info |= ACB_USE_DES_KEY_ONLY;
+#endif
+ ;;
+ }
+
+ init_sam_user_info16(&p16, acb_info);
+
+ status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16,
+ &cli->user_session_key, &ctr);
+
+ rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+ cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
+
+ return status;
+}
+
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index 79062345ab6..40892ab0911 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 LOOKUP SAM\n");
+" SETDOMAINSID CHANGESCRETPW LOOKUP SAM\n");
return -1;
}
@@ -230,6 +230,7 @@ static int net_usage(int argc, const char **argv)
" net cache\t\tto operate on cache tdb file\n"\
" net getlocalsid [NAME]\tto get the SID for local name\n"\
" net setlocalsid SID\tto set the local domain SID\n"\
+ " net setdomainsid SID\tto set the domain SID on member servers\n"\
" net changesecretpw\tto change the machine password in the local secrets database only\n"\
" \tthis requires the -f flag as a safety barrier\n"\
" net status\t\tShow server status\n"\
diff --git a/source/utils/net_lookup.c b/source/utils/net_lookup.c
index dd2d666d5a0..68097aa9f7f 100644
--- a/source/utils/net_lookup.c
+++ b/source/utils/net_lookup.c
@@ -62,71 +62,85 @@ static int net_lookup_host(int argc, const char **argv)
return 0;
}
-#ifdef HAVE_LDAP
-static void print_ldap_srvlist(char *srvlist)
+#ifdef HAVE_ADS
+static void print_ldap_srvlist(struct dns_rr_srv *dclist, int numdcs )
{
- char *cur, *next;
struct in_addr ip;
- BOOL printit;
-
- cur = srvlist;
- do {
- next = strchr(cur,':');
- if (next) *next++='\0';
- printit = resolve_name(cur, &ip, 0x20);
- cur=next;
- next=cur ? strchr(cur,' ') :NULL;
- if (next)
- *next++='\0';
- if (printit)
- d_printf("%s:%s\n", inet_ntoa(ip), cur?cur:"");
- cur = next;
- } while (next);
+ int i;
+
+ for ( i=0; i<numdcs; i++ ) {
+ if ( resolve_name(dclist[i].hostname, &ip, 0x20) ) {
+ d_printf("%s:%d\n", inet_ntoa(ip), dclist[i].port);
+ }
+ }
}
#endif
static int net_lookup_ldap(int argc, const char **argv)
{
#ifdef HAVE_ADS
- char *srvlist;
const char *domain;
- int rc;
struct in_addr addr;
struct hostent *hostent;
+ struct dns_rr_srv *dcs = NULL;
+ int numdcs = 0;
+ TALLOC_CTX *ctx;
+ NTSTATUS status;
if (argc > 0)
domain = argv[0];
else
domain = opt_target_workgroup;
+ if ( (ctx = talloc_init("net_lookup_ldap")) == NULL ) {
+ d_fprintf(stderr, "net_lookup_ldap: talloc_inti() failed!\n");
+ return -1;
+ }
+
DEBUG(9, ("Lookup up ldap for domain %s\n", domain));
- rc = ldap_domain2hostlist(domain, &srvlist);
- if ((rc == LDAP_SUCCESS) && srvlist) {
- print_ldap_srvlist(srvlist);
+
+ status = ads_dns_query_dcs( ctx, domain, &dcs, &numdcs );
+ if ( NT_STATUS_IS_OK(status) && numdcs ) {
+ print_ldap_srvlist(dcs, numdcs);
+ TALLOC_FREE( ctx );
+
return 0;
}
DEBUG(9, ("Looking up DC for domain %s\n", domain));
- if (!get_pdc_ip(domain, &addr))
+ if (!get_pdc_ip(domain, &addr)) {
+ TALLOC_FREE( ctx );
return -1;
+ }
hostent = gethostbyaddr((char *) &addr.s_addr, sizeof(addr.s_addr),
AF_INET);
- if (!hostent)
+ if (!hostent) {
+ TALLOC_FREE( ctx );
return -1;
+ }
DEBUG(9, ("Found DC with DNS name %s\n", hostent->h_name));
domain = strchr(hostent->h_name, '.');
- if (!domain)
+ if (!domain) {
+ TALLOC_FREE( ctx );
return -1;
+ }
domain++;
DEBUG(9, ("Looking up ldap for domain %s\n", domain));
- rc = ldap_domain2hostlist(domain, &srvlist);
- if ((rc == LDAP_SUCCESS) && srvlist) {
- print_ldap_srvlist(srvlist);
+
+ status = ads_dns_query_dcs( ctx, domain, &dcs, &numdcs );
+ if ( NT_STATUS_IS_OK(status) && numdcs ) {
+ print_ldap_srvlist(dcs, numdcs);
+ TALLOC_FREE( ctx );
+
return 0;
}
+
+ TALLOC_FREE( ctx );
+
+
return -1;
#endif
DEBUG(1,("No ADS support\n"));
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 0060a39c310..0844d407dbb 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -389,15 +389,14 @@ 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");
+ if (lp_server_role() == ROLE_STANDALONE) {
+ d_printf("cannot join as standalone machine\n");
return -1;
}
if (strlen(global_myname()) > 15) {
- d_printf("Our netbios name can only be 15 chars long, \"%s\""
- " is %d chars long\n",
+ d_printf("Our netbios name can be at most 15 chars long, "
+ "\"%s\" is %d chars long\n",
global_myname(), strlen(global_myname()));
return -1;
}
@@ -1607,7 +1606,7 @@ struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
};
return cmds;
-};
+}
/****************************************************************************/
@@ -4794,7 +4793,7 @@ struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
};
return cmds;
-};
+}
/****************************************************************************/
@@ -6198,7 +6197,7 @@ BOOL net_rpc_check(unsigned flags)
char *server_name = NULL;
/* flags (i.e. server type) may depend on command */
- if (!net_find_server(flags, &server_ip, &server_name))
+ if (!net_find_server(NULL, flags, &server_ip, &server_name))
return False;
ZERO_STRUCT(cli);
@@ -6611,6 +6610,7 @@ int net_rpc_usage(int argc, const char **argv)
d_printf(" net rpc rights\t\tto manage privileges assigned to SIDs\n");
d_printf(" net rpc registry\t\tto manage registry hives\n");
d_printf(" net rpc service\t\tto start, stop and query services\n");
+ d_printf(" net rpc audit\t\t\tto modify global auditing settings\n");
d_printf("\n");
d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
diff --git a/source/utils/net_rpc_join.c b/source/utils/net_rpc_join.c
index d611940e656..2c55b0e9462 100644
--- a/source/utils/net_rpc_join.c
+++ b/source/utils/net_rpc_join.c
@@ -41,7 +41,7 @@
* @return A shell status integer (0 for success)
*
**/
-static int net_rpc_join_ok(const char *domain)
+int net_rpc_join_ok(const char *domain, const char *server, struct in_addr *ip )
{
uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
struct cli_state *cli = NULL;
@@ -50,7 +50,7 @@ static int net_rpc_join_ok(const char *domain)
NTSTATUS ntret = NT_STATUS_UNSUCCESSFUL;
/* Connect to remote machine */
- if (!(cli = net_make_ipc_connection(NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC))) {
+ if (!(cli = net_make_ipc_connection_ex(domain, server, ip, (NET_FLAGS_ANONYMOUS|NET_FLAGS_PDC)))) {
return -1;
}
@@ -402,7 +402,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
}
/* double-check, connection from scratch */
- retval = net_rpc_join_ok(domain);
+ retval = net_rpc_join_ok(domain, cli->desthost, &cli->dest_ip);
done:
@@ -434,7 +434,7 @@ int net_rpc_testjoin(int argc, const char **argv)
char *domain = smb_xstrdup(opt_target_workgroup);
/* Display success or failure */
- if (net_rpc_join_ok(domain) != 0) {
+ if (net_rpc_join_ok(domain, NULL, NULL) != 0) {
fprintf(stderr,"Join to domain '%s' is not valid\n",domain);
free(domain);
return -1;
diff --git a/source/utils/net_rpc_rights.c b/source/utils/net_rpc_rights.c
index 2f02b409483..0dd28c3ac67 100644
--- a/source/utils/net_rpc_rights.c
+++ b/source/utils/net_rpc_rights.c
@@ -609,5 +609,5 @@ struct rpc_sh_cmd *net_rpc_rights_cmds(TALLOC_CTX *mem_ctx,
};
return cmds;
-};
+}
diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c
index b1807bb79b1..ef9a0627b58 100644
--- a/source/utils/net_rpc_samsync.c
+++ b/source/utils/net_rpc_samsync.c
@@ -1042,10 +1042,13 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
fflush(add_fd);
user_suffix = lp_ldap_user_suffix();
+ if (user_suffix == NULL) {
+ SAFE_FREE(suffix_attr);
+ return NT_STATUS_NO_MEMORY;
+ }
/* If it exists and is distinct from other containers,
Write the Users entity */
- if (user_suffix && *user_suffix &&
- strcmp(user_suffix, suffix)) {
+ if (*user_suffix && strcmp(user_suffix, suffix)) {
user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ',');
fprintf(add_fd, "# %s\n", user_suffix);
fprintf(add_fd, "dn: %s\n", user_suffix);
@@ -1057,10 +1060,14 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
group_suffix = lp_ldap_group_suffix();
+ if (group_suffix == NULL) {
+ SAFE_FREE(suffix_attr);
+ SAFE_FREE(user_attr);
+ return NT_STATUS_NO_MEMORY;
+ }
/* If it exists and is distinct from other containers,
Write the Groups entity */
- if (group_suffix && *group_suffix &&
- strcmp(group_suffix, suffix)) {
+ if (*group_suffix && strcmp(group_suffix, suffix)) {
group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
fprintf(add_fd, "# %s\n", group_suffix);
fprintf(add_fd, "dn: %s\n", group_suffix);
@@ -1073,8 +1080,13 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
/* If it exists and is distinct from other containers,
Write the Computers entity */
machine_suffix = lp_ldap_machine_suffix();
- if (machine_suffix && *machine_suffix &&
- strcmp(machine_suffix, user_suffix) &&
+ if (machine_suffix == NULL) {
+ SAFE_FREE(suffix_attr);
+ SAFE_FREE(user_attr);
+ SAFE_FREE(group_attr);
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
strcmp(machine_suffix, suffix)) {
char *machine_ou = NULL;
fprintf(add_fd, "# %s\n", machine_suffix);
@@ -1092,7 +1104,13 @@ static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const ch
/* If it exists and is distinct from other containers,
Write the IdMap entity */
idmap_suffix = lp_ldap_idmap_suffix();
- if (idmap_suffix && *idmap_suffix &&
+ if (idmap_suffix == NULL) {
+ SAFE_FREE(suffix_attr);
+ SAFE_FREE(user_attr);
+ SAFE_FREE(group_attr);
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (*idmap_suffix &&
strcmp(idmap_suffix, user_suffix) &&
strcmp(idmap_suffix, suffix)) {
char *s;
diff --git a/source/utils/net_sam.c b/source/utils/net_sam.c
index 945afb3a210..0bf662c2711 100644
--- a/source/utils/net_sam.c
+++ b/source/utils/net_sam.c
@@ -462,7 +462,6 @@ 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;
@@ -478,17 +477,13 @@ static int net_sam_createbuiltingroup(int argc, const char **argv)
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)) {
+ if ( !lookup_name(tmp_talloc_ctx(), groupname, LOOKUP_NAME_ALL, NULL,
+ NULL, &sid, &type)) {
d_fprintf(stderr, "%s is not a BUILTIN group\n", argv[0]);
return -1;
}
diff --git a/source/utils/net_usershare.c b/source/utils/net_usershare.c
index 1a5c0777211..1ee156c4ee0 100644
--- a/source/utils/net_usershare.c
+++ b/source/utils/net_usershare.c
@@ -62,12 +62,13 @@ 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"
+ "net usershare add [-l|--long] <sharename> <path> [<comment>] [<acl>] [<guest_ok=[y|n]>]\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<guest_ok=y> if present sets \"guest ok = yes\" on this usershare.\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 "
@@ -110,7 +111,8 @@ static int net_usershare_list_usage(int argc, const char **argv)
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"
+ d_printf("net usershare add <sharename> <path> [<comment>] [<acl>] [<guest_ok=[y|n]>] 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"
@@ -300,6 +302,7 @@ static int info_fn(struct file_list *fl, void *priv)
int num_aces;
char sep_str[2];
enum usershare_err us_err;
+ BOOL guest_ok = False;
sep_str[0] = *lp_winbind_separator();
sep_str[1] = '\0';
@@ -346,7 +349,8 @@ static int info_fn(struct file_list *fl, void *priv)
us_err = parse_usershare_file(ctx, &sbuf, fl->pathname, -1, lines, numlines,
sharepath,
comment,
- &psd);
+ &psd,
+ &guest_ok);
file_lines_free(lines);
@@ -400,7 +404,8 @@ static int info_fn(struct file_list *fl, void *priv)
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);
+ d_printf("%s\n", acl_str);
+ d_printf("guest_ok=%c\n\n", guest_ok ? 'y' : 'n');
} else if (pi->op == US_LIST_OP) {
d_printf("%s\n", fl->pathname);
}
@@ -475,6 +480,7 @@ static int net_usershare_add(int argc, const char **argv)
const char *pacl;
size_t to_write;
uid_t myeuid = geteuid();
+ BOOL guest_ok = False;
us_comment = "";
arg_acl = "S-1-1-0:R";
@@ -499,6 +505,27 @@ static int net_usershare_add(int argc, const char **argv)
us_comment = argv[2];
arg_acl = argv[3];
break;
+ case 5:
+ sharename = strdup_lower(argv[0]);
+ us_path = argv[1];
+ us_comment = argv[2];
+ arg_acl = argv[3];
+ if (!strnequal(argv[4], "guest_ok=", 9)) {
+ return net_usershare_add_usage(argc, argv);
+ }
+ switch (argv[4][9]) {
+ case 'y':
+ case 'Y':
+ guest_ok = True;
+ break;
+ case 'n':
+ case 'N':
+ guest_ok = False;
+ break;
+ default:
+ return net_usershare_add_usage(argc, argv);
+ }
+ break;
}
if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
@@ -642,6 +669,15 @@ static int net_usershare_add(int argc, const char **argv)
/* Remove the last ',' */
us_acl[strlen(us_acl)-1] = '\0';
+ if (guest_ok && !lp_usershare_allow_guests()) {
+ d_fprintf(stderr, "net usershare add: guest_ok=y requested "
+ "but the \"usershare allow guests\" parameter is not enabled "
+ "by this server.\n");
+ talloc_destroy(ctx);
+ SAFE_FREE(sharename);
+ return -1;
+ }
+
/* Create a temporary filename for this share. */
tmpfd = smb_mkstemp(full_path_tmp);
@@ -688,9 +724,9 @@ static int net_usershare_add(int argc, const char **argv)
}
/* 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 );
+ file_img = talloc_strdup(ctx, "#VERSION 2\npath=");
+ file_img = talloc_asprintf_append(file_img, "%s\ncomment=%s\nusershare_acl=%s\nguest_ok=%c\n",
+ us_path, us_comment, us_acl, guest_ok ? 'y' : 'n');
to_write = strlen(file_img);
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index 2e879cc1132..ef24f9f1611 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -916,7 +916,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
response.negTokenTarg.responseToken = data_blob(NULL, 0);
- status = ads_verify_ticket(mem_ctx, lp_realm(),
+ status = ads_verify_ticket(mem_ctx, lp_realm(), 0,
&request.negTokenInit.mechToken,
&principal, NULL, &ap_rep,
&session_key);
diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c
index 5c798c79014..ad05f8e9483 100644
--- a/source/utils/smbcontrol.c
+++ b/source/utils/smbcontrol.c
@@ -7,6 +7,7 @@
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Martin Pool 2001-2002
Copyright (C) Simo Sorce 2002
+ Copyright (C) James Peach 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +26,18 @@
#include "includes.h"
+#if HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+
+#if HAVE_LIBUNWIND_PTRACE_H
+#include <libunwind-ptrace.h>
+#endif
+
+#if HAVE_SYS_PTRACE_H
+#include <sys/ptrace.h>
+#endif
+
/* Default timeout value when waiting for replies (in seconds) */
#define DEFAULT_TIMEOUT 10
@@ -131,7 +144,177 @@ 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 */
+#if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
+
+/* Return the name of a process given it's PID. This will only work on Linux,
+ * but that's probably moot since this whole stack tracing implementatino is
+ * Linux-specific anyway.
+ */
+static const char * procname(pid_t pid, char * buf, size_t bufsz)
+{
+ char path[64];
+ FILE * fp;
+
+ snprintf(path, sizeof(path), "/proc/%llu/cmdline",
+ (unsigned long long)pid);
+ if ((fp = fopen(path, "r")) == NULL) {
+ return NULL;
+ }
+
+ fgets(buf, bufsz, fp);
+
+ fclose(fp);
+ return buf;
+}
+
+static void print_stack_trace(pid_t pid, int * count)
+{
+ void * pinfo = NULL;
+ unw_addr_space_t aspace = NULL;
+ unw_cursor_t cursor;
+ unw_word_t ip, sp;
+
+ char nbuf[256];
+ unw_word_t off;
+
+ int ret;
+
+ if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
+ fprintf(stderr,
+ "Failed to attach to process %llu: %s\n",
+ (unsigned long long)pid, strerror(errno));
+ return;
+ }
+
+ /* Wait until the attach is complete. */
+ waitpid(pid, NULL, 0);
+
+ if (((pinfo = _UPT_create(pid)) == NULL) ||
+ ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
+ /* Probably out of memory. */
+ fprintf(stderr,
+ "Unable to initialize stack unwind for process %llu\n",
+ (unsigned long long)pid);
+ goto cleanup;
+ }
+
+ if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
+ fprintf(stderr,
+ "Unable to unwind stack for process %llu: %s\n",
+ (unsigned long long)pid, unw_strerror(ret));
+ goto cleanup;
+ }
+
+ if (*count > 0) {
+ printf("\n");
+ }
+
+ if (procname(pid, nbuf, sizeof(nbuf))) {
+ printf("Stack trace for process %llu (%s):\n",
+ (unsigned long long)pid, nbuf);
+ } else {
+ printf("Stack trace for process %llu:\n",
+ (unsigned long long)pid);
+ }
+
+ while (unw_step(&cursor) > 0) {
+ ip = sp = off = 0;
+ unw_get_reg(&cursor, UNW_REG_IP, &ip);
+ unw_get_reg(&cursor, UNW_REG_SP, &sp);
+
+ ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
+ if (ret != 0 && ret != -UNW_ENOMEM) {
+ snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
+ }
+ printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
+ nbuf, (long long)off, (long long)ip,
+ (long long)sp);
+ }
+
+ (*count)++;
+
+cleanup:
+ if (aspace) {
+ unw_destroy_addr_space(aspace);
+ }
+
+ if (pinfo) {
+ _UPT_destroy(pinfo);
+ }
+
+ ptrace(PTRACE_DETACH, pid, NULL, NULL);
+}
+
+static int stack_trace_connection(TDB_CONTEXT * tdb, TDB_DATA key,
+ TDB_DATA data, void * priv)
+{
+ struct connections_data conn;
+
+ if (data.dsize != sizeof(conn))
+ return 0;
+
+ memcpy(&conn, data.dptr, sizeof(conn));
+ print_stack_trace(procid_to_pid(&conn.pid), (int *)priv);
+
+ return 0;
+}
+
+static BOOL do_daemon_stack_trace(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ fprintf(stderr,
+ "Daemon stack tracing is not supported on this platform\n");
+ return False;
+
+ pid_t dest;
+ int count = 0;
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
+ return False;
+ }
+
+ dest = procid_to_pid(&pid);
+
+ if (dest != 0) {
+ /* It would be nice to be able to make sure that this PID is
+ * the PID of a smbd/winbind/nmbd process, not some random PID
+ * the user liked the look of. It doesn't seem like it's worth
+ * the effort at the moment, however.
+ */
+ print_stack_trace(dest, &count);
+ } else {
+ TDB_CONTEXT * tdb;
+
+ tdb = tdb_open_log(lock_path("connections.tdb"), 0,
+ TDB_DEFAULT, O_RDONLY, 0);
+ if (!tdb) {
+ fprintf(stderr,
+ "Failed to open connections database: %s\n",
+ strerror(errno));
+ return False;
+ }
+
+ tdb_traverse(tdb, stack_trace_connection, &count);
+ tdb_close(tdb);
+ }
+
+ return True;
+}
+
+#else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
+
+static BOOL do_daemon_stack_trace(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ fprintf(stderr,
+ "Daemon stack tracing is not supported on this platform\n");
+ return False;
+}
+
+#endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
+
+/* Inject a fault (fatal signal) into a running smbd */
static BOOL do_inject_fault(const struct process_id pid,
const int argc, const char **argv)
@@ -726,6 +909,36 @@ static BOOL do_winbind_offline(const struct process_id pid,
return ret;
}
+static BOOL do_winbind_onlinestatus(const struct process_id pid,
+ const int argc, const char **argv)
+{
+ struct process_id myid;
+
+ myid = pid_to_procid(sys_getpid());
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
+ return False;
+ }
+
+ message_register(MSG_WINBIND_ONLINESTATUS, print_pid_string_cb);
+
+ if (!send_message(pid, MSG_WINBIND_ONLINESTATUS, &myid, sizeof(myid), False))
+ return False;
+
+ wait_replies(procid_to_pid(&pid) == 0);
+
+ /* No replies were received within the timeout period */
+
+ if (num_replies == 0)
+ printf("No replies received\n");
+
+ message_deregister(MSG_WINBIND_ONLINESTATUS);
+
+ return num_replies;
+}
+
+
static BOOL do_reload_config(const struct process_id pid,
const int argc, const char **argv)
{
@@ -799,6 +1012,8 @@ static const struct {
{ "profile", do_profile, "" },
{ "inject", do_inject_fault,
"Inject a fatal signal into a running smbd"},
+ { "stacktrace", do_daemon_stack_trace,
+ "Display a stack trace of a daemon" },
{ "profilelevel", do_profilelevel, "" },
{ "debuglevel", do_debuglevel, "Display current debuglevels" },
{ "printnotify", do_printnotify, "Send a print notify message" },
@@ -814,6 +1029,7 @@ static const struct {
{ "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"},
+ { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
{ "noop", do_noop, "Do nothing" },
{ NULL }
};
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c
index d66001e441b..c063ad8b315 100644
--- a/source/utils/smbpasswd.c
+++ b/source/utils/smbpasswd.c
@@ -407,7 +407,7 @@ static int process_root(int local_flags)
sampass = samu_new( NULL );
ret = pdb_getsampwnam(sampass, user_name);
if((ret) &&
- (pdb_get_lanman_passwd(sampass) == NULL)) {
+ (pdb_get_nt_passwd(sampass) == NULL)) {
local_flags |= LOCAL_SET_PASSWORD;
}
TALLOC_FREE(sampass);
diff --git a/source/utils/smbtree.c b/source/utils/smbtree.c
index 853a46f379e..d9cd446f6cb 100644
--- a/source/utils/smbtree.c
+++ b/source/utils/smbtree.c
@@ -127,6 +127,60 @@ static BOOL get_servers(char *workgroup, struct user_auth_info *user_info)
return True;
}
+static BOOL get_rpc_shares(struct cli_state *cli,
+ void (*fn)(const char *, uint32, const char *, void *),
+ void *state)
+{
+ 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);
+ fn(name, info->info_1.type, comment, state);
+ }
+
+ TALLOC_FREE(mem_ctx);
+ cli_rpc_pipe_close(pipe_hnd);
+ return True;
+}
+
+
static BOOL get_shares(char *server_name, struct user_auth_info *user_info)
{
struct cli_state *cli;
@@ -134,6 +188,9 @@ static BOOL get_shares(char *server_name, struct user_auth_info *user_info)
if (!(cli = get_ipc_connect(server_name, NULL, user_info)))
return False;
+ if (get_rpc_shares(cli, add_name, &shares))
+ return True;
+
if (!cli_RNetShareEnum(cli, add_name, &shares))
return False;
diff --git a/source/utils/status.c b/source/utils/status.c
index bc26be1ec93..05075da444f 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -622,6 +622,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
POPT_TABLEEND
};
+ sec_init();
load_case_tables();
setup_logging(argv[0],True);
diff --git a/source/utils/testparm.c b/source/utils/testparm.c
index 8b9ff4710e0..fe2d26afca7 100644
--- a/source/utils/testparm.c
+++ b/source/utils/testparm.c
@@ -96,15 +96,6 @@ to a valid password server.\n", sec_setting );
/*
- * Check 'hosts equiv' and 'use rhosts' compatibility with 'hostname lookup' value.
- */
-
- if(*lp_hosts_equiv() && !lp_hostname_lookups()) {
- fprintf(stderr, "ERROR: The setting 'hosts equiv = %s' requires that 'hostname lookups = yes'.\n", lp_hosts_equiv());
- ret = 1;
- }
-
- /*
* Password chat sanity checks.
*/
diff --git a/source/web/swat.c b/source/web/swat.c
index cbf5ba89891..a0dc0f4d313 100644
--- a/source/web/swat.c
+++ b/source/web/swat.c
@@ -1375,6 +1375,8 @@ static void printers_page(void)
poptFreeContext(pc);
+ load_case_tables();
+
setup_logging(argv[0],False);
load_config(True);
load_interfaces();