summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2007-04-21 21:51:01 +0000
committerGerald Carter <jerry@samba.org>2007-04-21 21:51:01 +0000
commite58110dfc02d6f90246d9c5ed1a6d207c0ce5bd2 (patch)
tree5375fc164b815c22bbf7f764b463fc6a0dd99793
parent63277b628390c5647f8a688186d767b6d76d9c3e (diff)
downloadsamba-e58110dfc02d6f90246d9c5ed1a6d207c0ce5bd2.tar.gz
samba-e58110dfc02d6f90246d9c5ed1a6d207c0ce5bd2.tar.xz
samba-e58110dfc02d6f90246d9c5ed1a6d207c0ce5bd2.zip
r22434: sync from the 3.0.25 tree for rc2
-rw-r--r--packaging/RHEL/samba.spec.tmpl3
-rw-r--r--source/Makefile.in9
-rw-r--r--source/auth/auth_util.c42
-rw-r--r--source/client/client.c4
-rw-r--r--source/configure.in26
-rw-r--r--source/include/idmap.h10
-rw-r--r--source/include/includes.h7
-rw-r--r--source/include/smb.h8
-rw-r--r--source/include/smb_macros.h24
-rw-r--r--source/include/smb_share_modes.h8
-rw-r--r--source/lib/fault.c7
-rw-r--r--source/lib/messages.c2
-rw-r--r--source/lib/replace/Makefile.in2
-rw-r--r--source/lib/replace/README19
-rw-r--r--source/lib/replace/libreplace.m416
-rw-r--r--source/lib/replace/libreplace_macros.m49
-rw-r--r--source/lib/replace/replace.c53
-rw-r--r--source/lib/replace/replace.h83
-rw-r--r--source/lib/replace/samba.m48
-rw-r--r--source/lib/replace/system/wait.h4
-rw-r--r--source/lib/replace/test/os2_delete.c2
-rw-r--r--source/lib/replace/test/testsuite.c481
-rw-r--r--source/lib/talloc/talloc.h10
-rw-r--r--source/lib/util_sock.c3
-rw-r--r--source/libads/kerberos.c6
-rw-r--r--source/libsmb/clientgen.c20
-rw-r--r--source/libsmb/clikrb5.c29
-rw-r--r--source/libsmb/namequery_dc.c5
-rw-r--r--source/libsmb/smb_share_modes.c5
-rw-r--r--source/modules/vfs_gpfs.c3
-rw-r--r--source/modules/vfs_readahead.c4
-rw-r--r--source/nmbd/nmbd_subnetdb.c7
-rw-r--r--source/nsswitch/idmap.c367
-rw-r--r--source/nsswitch/idmap_ad.c99
-rw-r--r--source/nsswitch/idmap_cache.c120
-rw-r--r--source/nsswitch/idmap_ldap.c97
-rw-r--r--source/nsswitch/idmap_nss.c3
-rw-r--r--source/nsswitch/idmap_passdb.c3
-rw-r--r--source/nsswitch/idmap_rid.c86
-rw-r--r--source/nsswitch/idmap_tdb.c43
-rw-r--r--source/nsswitch/idmap_util.c20
-rw-r--r--source/nsswitch/pam_winbind.c6
-rw-r--r--source/nsswitch/winbind_nss_config.h12
-rw-r--r--source/nsswitch/winbindd.c7
-rw-r--r--source/nsswitch/winbindd_cache.c128
-rw-r--r--source/nsswitch/winbindd_dual.c2
-rw-r--r--source/nsswitch/winbindd_sid.c85
-rw-r--r--source/nsswitch/winbindd_util.c2
-rw-r--r--source/param/loadparm.c23
-rw-r--r--source/profile/profile.c18
-rw-r--r--source/rpc_parse/parse_prs.c32
-rw-r--r--source/smbd/connection.c8
-rw-r--r--source/smbd/process.c4
-rw-r--r--source/smbd/quotas.c2
-rw-r--r--source/smbd/reply.c17
-rw-r--r--source/smbd/server.c10
-rw-r--r--source/smbd/trans2.c4
-rw-r--r--source/tdb/common/transaction.c2
-rw-r--r--source/utils/net_status.c4
-rw-r--r--source/utils/smbpasswd.c2
-rw-r--r--source/utils/status.c2
-rw-r--r--source/web/statuspage.c2
62 files changed, 1527 insertions, 602 deletions
diff --git a/packaging/RHEL/samba.spec.tmpl b/packaging/RHEL/samba.spec.tmpl
index 210d14e6a1b..627d40eade2 100644
--- a/packaging/RHEL/samba.spec.tmpl
+++ b/packaging/RHEL/samba.spec.tmpl
@@ -149,7 +149,8 @@ CFLAGS="$RPM_OPT_FLAGS $EXTRA -D_GNU_SOURCE" ./configure \
--with-shared-modules=idmap_rid,idmap_ad \
--with-smbmount \
--with-syslog \
- --with-utmp
+ --with-utmp \
+ --with-dnsupdate
make showlayout
diff --git a/source/Makefile.in b/source/Makefile.in
index 4e2cb5d2d93..0046899b727 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -75,6 +75,7 @@ VFSLIBDIR = $(LIBDIR)/vfs
PDBLIBDIR = $(LIBDIR)/pdb
RPCLIBDIR = $(LIBDIR)/rpc
IDMAPLIBDIR = $(LIBDIR)/idmap
+NSSINFOLIBDIR = $(LIBDIR)/nss_info
CHARSETLIBDIR = $(LIBDIR)/charset
AUTHLIBDIR = $(LIBDIR)/auth
CONFIGLIBDIR = $(LIBDIR)/config
@@ -172,7 +173,7 @@ SHLIBS = @LIBSMBCLIENT@ @LIBSMBSHAREMODES@ @LIBMSRPC@ @LIBADDNS@
PAM_MODULES = @PAM_MODULES@
-NSS_MODULES = @WINBIND_WINS_NSS@ @WINBIND_NSS@
+NSS_MODULES = @NSS_MODULES@
SCRIPTS = $(srcdir)/script/smbtar $(builddir)/script/findsmb
@@ -707,7 +708,9 @@ SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ)
TALLOCTORT_OBJ = lib/talloc/testsuite.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LIBSAMBA_OBJ) $(SECRETS_OBJ)
-REPLACETORT_OBJ = lib/replace/test/testsuite.o lib/replace/test/os2_delete.o \
+REPLACETORT_OBJ = lib/replace/test/testsuite.o \
+ lib/replace/test/os2_delete.o \
+ lib/replace/test/strptime.o \
$(LIBREPLACE_OBJ)
RPCTORTURE_OBJ = torture/rpctorture.o \
@@ -1591,6 +1594,7 @@ installmodules: modules installdirs
@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(PDBLIBDIR) $(PDB_MODULES)
@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(RPCLIBDIR) $(RPC_MODULES)
@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(IDMAPLIBDIR) $(IDMAP_MODULES)
+ @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(NSSINFOLIBDIR) $(NSS_INFO_MODULES)
@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(CHARSETLIBDIR) $(CHARSET_MODULES)
@$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR) $(prefix) $(AUTHLIBDIR) $(AUTH_MODULES)
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ ldapsam_compat.@SHLIBEXT@
@@ -1598,6 +1602,7 @@ installmodules: modules installdirs
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) sam.@SHLIBEXT@ sam_ignoredomain.@SHLIBEXT@
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) domain.@SHLIBEXT@ trustdomain.@SHLIBEXT@ ntdomain.@SHLIBEXT@
@$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) builtin.@SHLIBEXT@ guest.@SHLIBEXT@ fixed_challenge.@SHLIBEXT@ name_to_ntstatus.@SHLIBEXT@
+ @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(NSSINFOLIBDIR) ../idmap/ad.@SHLIBEXT@ rfc2307.@SHLIBEXT@ sfu.@SHLIBEXT@
installscripts: installdirs
@$(SHELL) $(srcdir)/script/installscripts.sh $(INSTALLPERMS) $(DESTDIR)$(BINDIR) $(SCRIPTS)
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 1bc65dcaacc..4e9e6f85f66 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -982,9 +982,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
NTSTATUS create_local_token(auth_serversupplied_info *server_info)
{
TALLOC_CTX *mem_ctx;
- struct id_map *ids;
NTSTATUS status;
- BOOL wb = True;
size_t i;
@@ -1031,44 +1029,18 @@ NTSTATUS create_local_token(auth_serversupplied_info *server_info)
server_info->groups = NULL;
/* Start at index 1, where the groups start. */
- ids = talloc_zero_array(mem_ctx, struct id_map, server_info->ptok->num_sids);
- for (i = 0; i < server_info->ptok->num_sids-1; i++) {
- ids[i].sid = &server_info->ptok->user_sids[i + 1]; /* store the sids */
- }
- if (!winbind_sids_to_unixids(ids, server_info->ptok->num_sids-1)) {
- DEBUG(2, ("Query to map secondary SIDs failed!\n"));
- if (!winbind_ping()) {
- DEBUG(2, ("Winbindd is not running, will try to map SIDs one by one with legacy code\n"));
- wb = False;
- }
- }
+ for (i=1; i<server_info->ptok->num_sids; i++) {
+ gid_t gid;
+ DOM_SID *sid = &server_info->ptok->user_sids[i];
- for (i = 0; i < server_info->ptok->num_sids-1; i++) {
- gid_t agid;
-
- if (wb) {
- if (ids[i].status != ID_MAPPED) {
+ if (!sid_to_gid(sid, &gid)) {
DEBUG(10, ("Could not convert SID %s to gid, "
- "ignoring it\n", sid_string_static(ids[i].sid)));
+ "ignoring it\n", sid_string_static(sid)));
continue;
}
- if (ids[i].xid.type == ID_TYPE_UID) {
- DEBUG(10, ("SID %s is a User ID (%u) not a Group ID, "
- "ignoring it\n", sid_string_static(ids[i].sid), ids[i].xid.id));
- continue;
- }
- agid = (gid_t)ids[i].xid.id;
- } else {
- if (! sid_to_gid(ids[i].sid, &agid)) {
- continue;
- }
- }
- if (!add_gid_to_array_unique(server_info, agid, &server_info->groups,
- &server_info->n_groups)) {
- TALLOC_FREE(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
+ add_gid_to_array_unique(server_info, gid, &server_info->groups,
+ &server_info->n_groups);
}
debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
diff --git a/source/client/client.c b/source/client/client.c
index e1b19e495dc..f0ee12aa793 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -3976,13 +3976,13 @@ static int do_message_op(void)
/* We must use old option processing for this. Find the
* position of the -T option in the raw argv[]. */
{
- int i, optnum;
+ int i;
for (i = 1; i < argc; i++) {
if (strncmp("-T", argv[i],2)==0)
break;
}
i++;
- if (!(optnum = tar_parseargs(argc, argv, poptGetOptArg(pc), i))) {
+ if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
poptPrintUsage(pc, stderr, 0);
exit(1);
}
diff --git a/source/configure.in b/source/configure.in
index 53e394f0024..bb54635135f 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -297,6 +297,7 @@ AC_SUBST(LDAP_LIBS)
AC_SUBST(PAM_MODULES)
AC_SUBST(INSTALL_PAM_MODULES)
AC_SUBST(UNINSTALL_PAM_MODULES)
+AC_SUBST(NSS_MODULES)
AC_SUBST(EXTRA_BIN_PROGS)
AC_SUBST(SMBMOUNT_PROGS)
AC_SUBST(CIFSMOUNT_PROGS)
@@ -3525,6 +3526,7 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_crypto_destroy, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_decode_ap_req, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(free_AP_REQ, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_verify_checksum, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_c_verify_checksum, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_principal_compare_any_realm, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_parse_name_norealm, $KRB5_LIBS)
@@ -3563,6 +3565,26 @@ if test x"$with_ads_support" != x"no"; then
[Whether the krb5_ticket structure contains the kvno and enctype])
fi
+ AC_CACHE_CHECK(whether krb5_get_init_creds_opt_free takes a context argument,
+ smb_krb5_creds_opt_free_context,
+ [
+ AC_TRY_COMPILE([
+ #include <krb5.h>],
+ [
+ krb5_context ctx;
+ krb5_get_init_creds_opt *opt = NULL;
+ krb5_get_init_creds_opt_free(ctx, opt);
+ ],
+ [smb_krb5_creds_opt_free_context=yes],
+ [smb_krb5_creds_opt_free_context=no]
+ )
+ ])
+
+ if test x"$smb_krb5_creds_opt_free_context" = x"yes" ; then
+ AC_DEFINE(KRB5_CREDS_OPT_FREE_REQUIRES_CONTEXT, 1,
+ [Whether krb5_get_init_creds_opt_free takes a context argument])
+ fi
+
AC_CACHE_CHECK(whether krb5_verify_checksum takes 7 arguments, smb_krb5_verify_checksum, [
AC_TRY_COMPILE([
#include <krb5.h>],
@@ -5742,6 +5764,10 @@ AC_SUBST(WINBIND_NSS_EXTRA_OBJS)
AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
AC_SUBST(NSSSONAMEVERSIONSUFFIX)
+if test $BLDSHARED = true -a x"$HAVE_WINBIND" = x"yes"; then
+ NSS_MODULES="${WINBIND_NSS} ${WINBIND_WINS_NSS}"
+fi
+
AC_SUBST(SMB_KRB5_LOCATOR)
# Check the setting of --with-winbind
diff --git a/source/include/idmap.h b/source/include/idmap.h
index 80bd541a23f..f4926f1e5c4 100644
--- a/source/include/idmap.h
+++ b/source/include/idmap.h
@@ -42,16 +42,24 @@ struct idmap_domain {
BOOL readonly;
void *private_data;
struct idmap_methods *methods;
+ BOOL initialized;
+ const char *params;
};
/* Filled out by IDMAP backends */
struct idmap_methods {
/* Called when backend is first loaded */
- NTSTATUS (*init)(struct idmap_domain *dom, const char *compat_params);
+ NTSTATUS (*init)(struct idmap_domain *dom);
+ /* Map an array of uids/gids to SIDs. The caller specifies
+ the uid/gid and type. Gets back the SID. */
NTSTATUS (*unixids_to_sids)(struct idmap_domain *dom, struct id_map **ids);
+
+ /* Map an arry of SIDs to uids/gids. The caller sets the SID
+ and type and gets back a uid or gid. */
NTSTATUS (*sids_to_unixids)(struct idmap_domain *dom, struct id_map **ids);
+
NTSTATUS (*set_mapping)(struct idmap_domain *dom, const struct id_map *map);
NTSTATUS (*remove_mapping)(struct idmap_domain *dom, const struct id_map *map);
diff --git a/source/include/includes.h b/source/include/includes.h
index ca8f2ded8cc..14bfc2d6409 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -1191,8 +1191,11 @@ krb5_error_code nt_status_to_krb5(NTSTATUS nt_status);
void smb_krb5_free_error(krb5_context context, krb5_error *krberror);
krb5_error_code handle_krberror_packet(krb5_context context,
krb5_data *packet);
-void krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt);
-krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt);
+
+void smb_krb5_get_init_creds_opt_free(krb5_context context,
+ krb5_get_init_creds_opt *opt);
+krb5_error_code smb_krb5_get_init_creds_opt_alloc(krb5_context context,
+ krb5_get_init_creds_opt **opt);
krb5_error_code smb_krb5_mk_error(krb5_context context,
krb5_error_code error_code,
const krb5_principal server,
diff --git a/source/include/smb.h b/source/include/smb.h
index 2ad3202ef9d..29fb1e133d8 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -286,12 +286,14 @@ typedef struct dom_sid {
#define dom_sid28 dom_sid
enum id_mapping {
- ID_UNKNOWN,
+ ID_UNKNOWN = 0,
ID_MAPPED,
- ID_UNMAPPED
+ ID_UNMAPPED,
+ ID_EXPIRED
};
enum id_type {
+ ID_TYPE_NOT_SPECIFIED = 0,
ID_TYPE_UID,
ID_TYPE_GID
};
@@ -885,7 +887,7 @@ struct connections_data {
int cnum;
uid_t uid;
gid_t gid;
- char name[24];
+ char servicename[FSTRING_LEN];
char addr[24];
char machine[FSTRING_LEN];
time_t start;
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index add7dcd31c2..c433ac2dc43 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -46,25 +46,6 @@
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
#endif
-/* zero a structure */
-#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
-
-/* zero a structure given a pointer to the structure */
-#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
-
-/* zero a structure given a pointer to the structure - no zero check */
-#define ZERO_STRUCTPN(x) memset((char *)(x), 0, sizeof(*(x)))
-
-/* zero an array - note that sizeof(array) must work - ie. it must not be a
- pointer */
-#define ZERO_ARRAY(x) memset((char *)(x), 0, sizeof(x))
-
-/* pointer difference macro */
-#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
-
-/* work out how many elements there are in a static array */
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
-
/* assert macros */
#ifdef DEVELOPER
#define SMB_ASSERT(b) ( (b) ? (void)0 : \
@@ -350,11 +331,6 @@ copy an IP address from one buffer to another
#else
-#define _STRING_LINE_(s) #s
-#define _STRING_LINE2_(s) _STRING_LINE_(s)
-#define __LINESTR__ _STRING_LINE2_(__LINE__)
-#define __location__ __FILE__ ":" __LINESTR__
-
#define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem((ps),sizeof(type),(count))
#define PRS_ALLOC_MEM_VOID(ps, size) prs_alloc_mem((ps),(size),1)
diff --git a/source/include/smb_share_modes.h b/source/include/smb_share_modes.h
index 1e04ea496de..5ed43bda336 100644
--- a/source/include/smb_share_modes.h
+++ b/source/include/smb_share_modes.h
@@ -33,12 +33,8 @@ extern "C" {
# endif
#endif
-#include "tdb.h"
-
-/* Database context handle. */
-struct smbdb_ctx {
- TDB_CONTEXT *smb_tdb;
-};
+/* Opaque database context handle. */
+struct smbdb_ctx;
/* Share mode entry. */
/*
diff --git a/source/lib/fault.c b/source/lib/fault.c
index b214d9027ea..d429c197488 100644
--- a/source/lib/fault.c
+++ b/source/lib/fault.c
@@ -161,6 +161,13 @@ void dump_core_setup(const char *progname)
}
#if DUMP_CORE
+ /* If we're running as non root we might not be able to dump the core
+ * file to the corepath. There must not be an unbecome_root() before
+ * we call abort(). */
+ if (geteuid() != 0) {
+ become_root();
+ }
+
if (*corepath != '\0') {
/* The chdir might fail if we dump core before we finish
* processing the config file.
diff --git a/source/lib/messages.c b/source/lib/messages.c
index 08a94142572..8e2456d5a5a 100644
--- a/source/lib/messages.c
+++ b/source/lib/messages.c
@@ -646,7 +646,7 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void
/* If the pid was not found delete the entry from connections.tdb */
DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
- procid_str_static(&crec.pid), crec.cnum, crec.name));
+ procid_str_static(&crec.pid), crec.cnum, crec.servicename));
tdb_delete(the_tdb, kbuf);
}
msg_all->n_sent++;
diff --git a/source/lib/replace/Makefile.in b/source/lib/replace/Makefile.in
index 10ba5b9415a..f4c79749a69 100644
--- a/source/lib/replace/Makefile.in
+++ b/source/lib/replace/Makefile.in
@@ -37,7 +37,7 @@ test: all
installcheck: install test
-TEST_OBJS = test/testsuite.o test/os2_delete.o
+TEST_OBJS = test/testsuite.o test/os2_delete.o test/strptime.o
testsuite: libreplace.a $(TEST_OBJS)
$(CC) -o testsuite $(TEST_OBJS) -L. -lreplace
diff --git a/source/lib/replace/README b/source/lib/replace/README
index a313984c8ea..77558b2ca96 100644
--- a/source/lib/replace/README
+++ b/source/lib/replace/README
@@ -12,7 +12,6 @@ strlcpy
strlcat
mktime
rename
-innetgr
initgroups
memmove
strdup
@@ -21,6 +20,7 @@ setlinebuf
vsyslog
timegm
setenv
+unsetenv
strndup
strnlen
waitpid
@@ -53,6 +53,7 @@ inet_ntoa
strtoll
strtoull
socketpair
+strptime
Types:
bool
@@ -76,13 +77,27 @@ CHAR_BIT
Macros:
va_copy
__FUNCTION__
+__FILE__
+__LINE__
+__LINESTR__
+__location__
__STRING
+__STRINGSTRING
MIN
MAX
QSORT_CAST
+ZERO_STRUCT
+ZERO_STRUCTP
+ZERO_STRUCTPN
+ZERO_ARRAY
+ARRAY_SIZE
+PTR_DIFF
+
+Headers:
+stdint.h
+stdbool.h
Prerequisites:
memset (for bzero)
syslog (for vsyslog)
-setnetgrent, getnetgrent, endnetgrent (for innetgr)
mktemp (for mkstemp and mkdtemp)
diff --git a/source/lib/replace/libreplace.m4 b/source/lib/replace/libreplace.m4
index 3328dea95e8..e9b19b7cf51 100644
--- a/source/lib/replace/libreplace.m4
+++ b/source/lib/replace/libreplace.m4
@@ -61,9 +61,12 @@ AC_FUNC_MEMCMP
AC_CHECK_FUNCS(pipe strftime srandom random srand rand usleep setbuffer lstat getpgrp)
-AC_CHECK_HEADERS(stdbool.h sys/select.h)
+AC_CHECK_HEADERS(stdbool.h stdint.h sys/select.h)
AC_CHECK_HEADERS(setjmp.h)
+LIBREPLACE_PROVIDE_HEADER([stdint.h])
+LIBREPLACE_PROVIDE_HEADER([stdbool.h])
+
AC_CHECK_TYPE(bool,
[AC_DEFINE(HAVE_BOOL, 1, [Whether the bool type is available])],,
[
@@ -147,7 +150,7 @@ AC_TRY_COMPILE([
AC_CHECK_FUNCS(seteuid setresuid setegid setresgid chroot bzero strerror)
AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename)
-AC_CHECK_FUNCS(waitpid strlcpy strlcat innetgr initgroups memmove strdup)
+AC_CHECK_FUNCS(waitpid strlcpy strlcat initgroups memmove strdup)
AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp socketpair)
AC_HAVE_DECL(setresuid, [#include <unistd.h>])
AC_HAVE_DECL(setresgid, [#include <unistd.h>])
@@ -260,7 +263,10 @@ AC_CHECK_HEADERS([sys/param.h limits.h])
AC_CHECK_TYPE(comparison_fn_t,
[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])])
-AC_CHECK_FUNCS(strnlen setenv)
+AC_HAVE_DECL(setenv, [#include <stdlib.h>])
+AC_CHECK_FUNCS(setenv unsetenv)
+
+AC_CHECK_FUNCS(strnlen)
AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq)
# this test disabled as we don't actually need __VA_ARGS__ yet
@@ -323,12 +329,12 @@ m4_include(system/config.m4)
m4_include(dlfcn.m4)
m4_include(getpass.m4)
+m4_include(strptime.m4)
m4_include(win32.m4)
m4_include(timegm.m4)
m4_include(repdir.m4)
-AC_CHECK_FUNCS([syslog memset setnetgrent getnetgrent endnetgrent memcpy],,
- [AC_MSG_ERROR([Required function not found])])
+AC_CHECK_FUNCS([syslog memset memcpy],,[AC_MSG_ERROR([Required function not found])])
echo "LIBREPLACE_BROKEN_CHECKS: END"
]) dnl end AC_LIBREPLACE_BROKEN_CHECKS
diff --git a/source/lib/replace/libreplace_macros.m4 b/source/lib/replace/libreplace_macros.m4
index 0669c10c2a0..f262b9b6eb0 100644
--- a/source/lib/replace/libreplace_macros.m4
+++ b/source/lib/replace/libreplace_macros.m4
@@ -306,3 +306,12 @@ AC_DEFUN(AC_VERIFY_C_PROTOTYPE,
)
AS_IF([test $AS_TR_SH([ac_cv_c_prototype_$1]) = yes],[$3],[$4])
])
+
+AC_DEFUN(LIBREPLACE_PROVIDE_HEADER,
+[AC_CHECK_HEADER([$1],
+ [ AC_CONFIG_COMMANDS(rm-$1, [rm -f $libreplacedir/$1], [libreplacedir=$libreplacedir]) ],
+ [ AC_CONFIG_COMMANDS(mk-$1, [echo "#include \"replace.h\"" > $libreplacedir/$1], [libreplacedir=$libreplacedir]) ]
+ )
+])
+
+
diff --git a/source/lib/replace/replace.c b/source/lib/replace/replace.c
index 9e6c75bd358..db299130e51 100644
--- a/source/lib/replace/replace.c
+++ b/source/lib/replace/replace.c
@@ -154,33 +154,6 @@ time_t rep_mktime(struct tm *t)
#endif /* !HAVE_MKTIME */
-#ifndef HAVE_INNETGR
-#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
-/*
- * Search for a match in a netgroup. This replaces it on broken systems.
- */
-int rep_innetgr(const char *group, const char *host, const char *user,
- const char *dom)
-{
- char *hst, *usr, *dm;
-
- setnetgrent(group);
- while (getnetgrent(&hst, &usr, &dm)) {
- if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
- ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
- ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
- endnetgrent();
- return (1);
- }
- }
- endnetgrent();
- return (0);
-}
-#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
-#endif /* HAVE_INNETGR */
-
-
-
#ifndef HAVE_INITGROUPS
/****************************************************************************
some systems don't have an initgroups call
@@ -590,6 +563,32 @@ int rep_setenv(const char *name, const char *value, int overwrite)
}
#endif
+#ifndef HAVE_UNSETENV
+int rep_unsetenv(const char *name)
+{
+ extern char **environ;
+ size_t len = strlen(name);
+ size_t i;
+ int found = 0;
+
+ for (i=0; (environ && environ[i]); i++) {
+ if (found) {
+ environ[i-1] = environ[i];
+ continue;
+ }
+
+ if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
+ free(environ[i]);
+ environ[i] = NULL;
+ found = 1;
+ continue;
+ }
+ }
+
+ return 0;
+}
+#endif
+
#ifndef HAVE_SOCKETPAIR
int rep_socketpair(int d, int type, int protocol, int sv[2])
{
diff --git a/source/lib/replace/replace.h b/source/lib/replace/replace.h
index d75394aa1fc..b96356ac467 100644
--- a/source/lib/replace/replace.h
+++ b/source/lib/replace/replace.h
@@ -79,6 +79,29 @@
#include <stddef.h>
#endif
+/**
+ this is a warning hack. The idea is to use this everywhere that we
+ get the "discarding const" warning from gcc. That doesn't actually
+ fix the problem of course, but it means that when we do get to
+ cleaning them up we can do it by searching the code for
+ discard_const.
+
+ It also means that other error types aren't as swamped by the noise
+ of hundreds of const warnings, so we are more likely to notice when
+ we get new errors.
+
+ Please only add more uses of this macro when you find it
+ _really_ hard to fix const warnings. Our aim is to eventually use
+ this function in only a very few places.
+
+ Also, please call this via the discard_const_p() macro interface, as that
+ makes the return type safe.
+*/
+#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
+
+/** Type-safe version of discard_const */
+#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
+
#ifndef HAVE_STRERROR
extern char *sys_errlist[];
#define strerror(i) sys_errlist[i]
@@ -137,7 +160,16 @@ size_t rep_strnlen(const char *s, size_t n);
#ifndef HAVE_SETENV
#define setenv rep_setenv
-int rep_setenv(const char *name, const char *value, int overwrite);
+int rep_setenv(const char *name, const char *value, int overwrite);
+#else
+#ifndef HAVE_SETENV_DECL
+int setenv(const char *name, const char *value, int overwrite);
+#endif
+#endif
+
+#ifndef HAVE_UNSETENV
+#define unsetenv rep_unsetenv
+int rep_unsetenv(const char *name);
#endif
#ifndef HAVE_SETEUID
@@ -181,7 +213,7 @@ int rep_ftruncate(int,off_t);
#endif
#ifndef HAVE_INITGROUPS
-#define ftruncate rep_ftruncate
+#define initgroups rep_initgroups
int rep_initgroups(char *name, gid_t id);
#endif
@@ -275,6 +307,12 @@ void rep_vsyslog (int facility_priority, const char *format, va_list arglist) PR
typedef int (*comparison_fn_t)(const void *, const void *);
#endif
+#ifdef REPLACE_STRPTIME
+#define strptime rep_strptime
+struct tm;
+char *rep_strptime(const char *buf, const char *format, struct tm *tm);
+#endif
+
/* Load header file for dynamic linking stuff */
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
@@ -401,6 +439,47 @@ typedef int bool;
#define __STRING(x) #x
#endif
+#ifndef _STRINGSTRING
+#define __STRINGSTRING(x) __STRING(x)
+#endif
+
+#ifndef __LINESTR__
+#define __LINESTR__ __STRINGSTRING(__LINE__)
+#endif
+
+#ifndef __location__
+#define __location__ __FILE__ ":" __LINESTR__
+#endif
+
+/**
+ * zero a structure
+ */
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+
+/**
+ * zero a structure given a pointer to the structure
+ */
+#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
+
+/**
+ * zero a structure given a pointer to the structure - no zero check
+ */
+#define ZERO_STRUCTPN(x) memset((char *)(x), 0, sizeof(*(x)))
+
+/* zero an array - note that sizeof(array) must work - ie. it must not be a
+ pointer */
+#define ZERO_ARRAY(x) memset((char *)(x), 0, sizeof(x))
+
+/**
+ * work out how many elements there are in a static array
+ */
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+/**
+ * pointer difference macro
+ */
+#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
+
#if MMAP_BLACKLIST
#undef HAVE_MMAP
#endif
diff --git a/source/lib/replace/samba.m4 b/source/lib/replace/samba.m4
index 3769c7f50e9..a2e04f53b1d 100644
--- a/source/lib/replace/samba.m4
+++ b/source/lib/replace/samba.m4
@@ -3,8 +3,16 @@ AC_LIBREPLACE_BROKEN_CHECKS
SMB_EXT_LIB(LIBREPLACE_EXT, [${LIBDL}])
SMB_ENABLE(LIBREPLACE_EXT)
+# remove leading ./
LIBREPLACE_DIR=`echo ${libreplacedir} |sed -e 's/^\.\///g'`
+# remove leading srcdir .. we are looking for the relative
+# path within the samba source tree or wherever libreplace is.
+# We need to make sure the object is not forced to end up in
+# the source directory because we might be using a separate
+# build directory.
+LIBREPLACE_DIR=`echo ${LIBREPLACE_DIR} | sed -e "s|^$srcdir/||g"`
+
LIBREPLACE_OBJS=""
for obj in ${LIBREPLACEOBJ}; do
LIBREPLACE_OBJS="${LIBREPLACE_OBJS} ${LIBREPLACE_DIR}/${obj}"
diff --git a/source/lib/replace/system/wait.h b/source/lib/replace/system/wait.h
index 3855f7ae724..179ef0774e0 100644
--- a/source/lib/replace/system/wait.h
+++ b/source/lib/replace/system/wait.h
@@ -40,4 +40,8 @@
#include <setjmp.h>
#endif
+#ifndef SA_RESETHAND
+#define SA_RESETHAND SA_ONESHOT
+#endif
+
#endif
diff --git a/source/lib/replace/test/os2_delete.c b/source/lib/replace/test/os2_delete.c
index c8abfccff9b..c6ef1800178 100644
--- a/source/lib/replace/test/os2_delete.c
+++ b/source/lib/replace/test/os2_delete.c
@@ -111,5 +111,7 @@ int test_readdir_os2_delete(void)
rmdir(TESTDIR) == 0 || FAILED("rmdir");
+ system("rm -rf " TESTDIR);
+
return test_readdir_os2_delete_ret;
}
diff --git a/source/lib/replace/test/testsuite.c b/source/lib/replace/test/testsuite.c
index effbdb13ef0..2d068c559f3 100644
--- a/source/lib/replace/test/testsuite.c
+++ b/source/lib/replace/test/testsuite.c
@@ -115,17 +115,31 @@ static int test_strlcpy(void)
static int test_strlcat(void)
{
- /* FIXME */
- return true;
-}
+ char tmp[10];
+ printf("test: strlcat\n");
+ strlcpy(tmp, "", sizeof(tmp));
+ if (strlcat(tmp, "bla", 3) != 3) {
+ printf("failure: strlcat [\ninvalid return code\n]\n");
+ return false;
+ }
+ if (strcmp(tmp, "bl") != 0) {
+ printf("failure: strlcat [\nexpected \"bl\", got \"%s\"\n]\n",
+ tmp);
+ return false;
+ }
-static int test_mktime(void)
-{
- /* FIXME */
+ strlcpy(tmp, "da", sizeof(tmp));
+ if (strlcat(tmp, "me", 4) != 4) {
+ printf("failure: strlcat [\nexpected \"dam\", got \"%s\"\n]\n",
+ tmp);
+ return false;
+ }
+
+ printf("success: strlcat\n");
return true;
}
-static int test_innetgr(void)
+static int test_mktime(void)
{
/* FIXME */
return true;
@@ -145,7 +159,16 @@ static int test_memmove(void)
static int test_strdup(void)
{
- /* FIXME */
+ char *x;
+ printf("test: strdup\n");
+ x = strdup("bla");
+ if (strcmp("bla", x) != 0) {
+ printf("failure: strdup [\nfailed: expected \"bla\", got \"%s\"\n]\n",
+ x);
+ return false;
+ }
+ free(x);
+ printf("success: strdup\n");
return true;
}
@@ -171,19 +194,109 @@ static int test_timegm(void)
static int test_setenv(void)
{
- /* FIXME */
+#define TEST_SETENV(key, value, overwrite, result) do { \
+ int _ret; \
+ char *_v; \
+ _ret = setenv(key, value, overwrite); \
+ if (_ret != 0) { \
+ printf("failure: setenv [\n" \
+ "setenv(%s, %s, %d) failed\n" \
+ "]\n", \
+ key, value, overwrite); \
+ return false; \
+ } \
+ _v=getenv(key); \
+ if (!_v) { \
+ printf("failure: setenv [\n" \
+ "getenv(%s) returned NULL\n" \
+ "]\n", \
+ key); \
+ return false; \
+ } \
+ if (strcmp(result, _v) != 0) { \
+ printf("failure: setenv [\n" \
+ "getenv(%s): '%s' != '%s'\n" \
+ "]\n", \
+ key, result, _v); \
+ return false; \
+ } \
+} while(0)
+
+#define TEST_UNSETENV(key) do { \
+ char *_v; \
+ unsetenv(key); \
+ _v=getenv(key); \
+ if (_v) { \
+ printf("failure: setenv [\n" \
+ "getenv(%s): NULL != '%s'\n" \
+ "]\n", \
+ SETENVTEST_KEY, _v); \
+ return false; \
+ } \
+} while (0)
+
+#define SETENVTEST_KEY "SETENVTESTKEY"
+#define SETENVTEST_VAL "SETENVTESTVAL"
+
+ printf("test: setenv\n");
+ TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"1", 0, SETENVTEST_VAL"1");
+ TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"2", 0, SETENVTEST_VAL"1");
+ TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"3", 1, SETENVTEST_VAL"3");
+ TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"4", 1, SETENVTEST_VAL"4");
+ TEST_UNSETENV(SETENVTEST_KEY);
+ TEST_UNSETENV(SETENVTEST_KEY);
+ TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"5", 0, SETENVTEST_VAL"5");
+ TEST_UNSETENV(SETENVTEST_KEY);
+ TEST_UNSETENV(SETENVTEST_KEY);
+ printf("success: setenv\n");
return true;
}
static int test_strndup(void)
{
- /* FIXME */
+ char *x;
+ printf("test: strndup\n");
+ x = strndup("bla", 0);
+ if (strcmp(x, "") != 0) {
+ printf("failure: strndup [\ninvalid\n]\n");
+ return false;
+ }
+ free(x);
+ x = strndup("bla", 2);
+ if (strcmp(x, "bl") != 0) {
+ printf("failure: strndup [\ninvalid\n]\n");
+ return false;
+ }
+ free(x);
+ x = strndup("bla", 10);
+ if (strcmp(x, "bla") != 0) {
+ printf("failure: strndup [\ninvalid\n]\n");
+ return false;
+ }
+ free(x);
+ printf("success: strndup\n");
return true;
}
static int test_strnlen(void)
{
- /* FIXME */
+ printf("test: strnlen\n");
+ if (strnlen("bla", 2) != 2) {
+ printf("failure: strnlen [\nunexpected length\n]\n");
+ return false;
+ }
+
+ if (strnlen("some text\n", 0) != 0) {
+ printf("failure: strnlen [\nunexpected length\n]\n");
+ return false;
+ }
+
+ if (strnlen("some text", 20) != 9) {
+ printf("failure: strnlen [\nunexpected length\n]\n");
+ return false;
+ }
+
+ printf("success: strnlen\n");
return true;
}
@@ -207,13 +320,43 @@ static int test_setegid(void)
static int test_asprintf(void)
{
- /* FIXME */
+ char *x;
+ printf("test: asprintf\n");
+ if (asprintf(&x, "%d", 9) != 1) {
+ printf("failure: asprintf [\ngenerate asprintf\n]\n");
+ return false;
+ }
+ if (strcmp(x, "9") != 0) {
+ printf("failure: asprintf [\ngenerate asprintf\n]\n");
+ return false;
+ }
+ if (asprintf(&x, "dat%s", "a") != 4) {
+ printf("failure: asprintf [\ngenerate asprintf\n]\n");
+ return false;
+ }
+ if (strcmp(x, "data") != 0) {
+ printf("failure: asprintf [\ngenerate asprintf\n]\n");
+ return false;
+ }
+ printf("success: asprintf\n");
return true;
}
static int test_snprintf(void)
{
- /* FIXME */
+ char tmp[10];
+ printf("test: snprintf\n");
+ if (snprintf(tmp, 3, "foo%d", 9) != 4) {
+ printf("failure: snprintf [\nsnprintf return code failed\n]\n");
+ return false;
+ }
+
+ if (strcmp(tmp, "fo") != 0) {
+ printf("failure: snprintf [\nsnprintf failed\n]\n");
+ return false;
+ }
+
+ printf("success: snprintf\n");
return true;
}
@@ -286,7 +429,14 @@ static int test_strerror(void)
static int test_errno(void)
{
- /* FIXME */
+ printf("test: errno\n");
+ errno = 3;
+ if (errno != 3) {
+ printf("failure: errno [\nerrno failed\n]\n");
+ return false;
+ }
+
+ printf("success: errno\n");
return true;
}
@@ -326,15 +476,275 @@ static int test_inet_ntoa(void)
return true;
}
+#define TEST_STRTO_X(type,fmt,func,str,base,res,diff,rrnoo) do {\
+ type _v; \
+ char _s[64]; \
+ char *_p = NULL;\
+ char *_ep = NULL; \
+ strlcpy(_s, str, sizeof(_s));\
+ if (diff >= 0) { \
+ _ep = &_s[diff]; \
+ } \
+ errno = 0; \
+ _v = func(_s, &_p, base); \
+ if (errno != rrnoo) { \
+ printf("failure: %s [\n" \
+ "\t%s\n" \
+ "\t%s(\"%s\",%d,%d): " fmt " (=/!)= " fmt "\n" \
+ "\terrno: %d != %d\n" \
+ "]\n", \
+ __STRING(func), __location__, __STRING(func), \
+ str, diff, base, res, _v, rrnoo, errno); \
+ return false; \
+ } else if (_v != res) { \
+ printf("failure: %s [\n" \
+ "\t%s\n" \
+ "\t%s(\"%s\",%d,%d): " fmt " != " fmt "\n" \
+ "]\n", \
+ __STRING(func), __location__, __STRING(func), \
+ str, diff, base, res, _v); \
+ return false; \
+ } else if (_p != _ep) { \
+ printf("failure: %s [\n" \
+ "\t%s\n" \
+ "\t%s(\"%s\",%d,%d): " fmt " (=/!)= " fmt "\n" \
+ "\tptr: %p - %p = %d != %d\n" \
+ "]\n", \
+ __STRING(func), __location__, __STRING(func), \
+ str, diff, base, res, _v, _ep, _p, diff - (_ep - _p), diff); \
+ return false; \
+ } \
+} while (0)
+
static int test_strtoll(void)
{
- /* FIXME */
+ printf("test: strtoll\n");
+
+#define TEST_STRTOLL(str,base,res,diff,errnoo) TEST_STRTO_X(int64_t, "%lld", strtoll,str,base,res,diff,errnoo)
+
+ TEST_STRTOLL("15", 10, 15LL, 2, 0);
+ TEST_STRTOLL(" 15", 10, 15LL, 4, 0);
+ TEST_STRTOLL("15", 0, 15LL, 2, 0);
+ TEST_STRTOLL(" 15 ", 0, 15LL, 3, 0);
+ TEST_STRTOLL("+15", 10, 15LL, 3, 0);
+ TEST_STRTOLL(" +15", 10, 15LL, 5, 0);
+ TEST_STRTOLL("+15", 0, 15LL, 3, 0);
+ TEST_STRTOLL(" +15 ", 0, 15LL, 4, 0);
+ TEST_STRTOLL("-15", 10, -15LL, 3, 0);
+ TEST_STRTOLL(" -15", 10, -15LL, 5, 0);
+ TEST_STRTOLL("-15", 0, -15LL, 3, 0);
+ TEST_STRTOLL(" -15 ", 0, -15LL, 4, 0);
+ TEST_STRTOLL("015", 10, 15LL, 3, 0);
+ TEST_STRTOLL(" 015", 10, 15LL, 5, 0);
+ TEST_STRTOLL("015", 0, 13LL, 3, 0);
+ TEST_STRTOLL(" 015", 0, 13LL, 5, 0);
+ TEST_STRTOLL("0x15", 10, 0LL, 1, 0);
+ TEST_STRTOLL(" 0x15", 10, 0LL, 3, 0);
+ TEST_STRTOLL("0x15", 0, 21LL, 4, 0);
+ TEST_STRTOLL(" 0x15", 0, 21LL, 6, 0);
+
+ TEST_STRTOLL("10", 16, 16LL, 2, 0);
+ TEST_STRTOLL(" 10 ", 16, 16LL, 4, 0);
+ TEST_STRTOLL("0x10", 16, 16LL, 4, 0);
+ TEST_STRTOLL("0x10", 0, 16LL, 4, 0);
+ TEST_STRTOLL(" 0x10 ", 0, 16LL, 5, 0);
+ TEST_STRTOLL("+10", 16, 16LL, 3, 0);
+ TEST_STRTOLL(" +10 ", 16, 16LL, 5, 0);
+ TEST_STRTOLL("+0x10", 16, 16LL, 5, 0);
+ TEST_STRTOLL("+0x10", 0, 16LL, 5, 0);
+ TEST_STRTOLL(" +0x10 ", 0, 16LL, 6, 0);
+ TEST_STRTOLL("-10", 16, -16LL, 3, 0);
+ TEST_STRTOLL(" -10 ", 16, -16LL, 5, 0);
+ TEST_STRTOLL("-0x10", 16, -16LL, 5, 0);
+ TEST_STRTOLL("-0x10", 0, -16LL, 5, 0);
+ TEST_STRTOLL(" -0x10 ", 0, -16LL, 6, 0);
+ TEST_STRTOLL("010", 16, 16LL, 3, 0);
+ TEST_STRTOLL(" 010 ", 16, 16LL, 5, 0);
+ TEST_STRTOLL("-010", 16, -16LL, 4, 0);
+
+ TEST_STRTOLL("11", 8, 9LL, 2, 0);
+ TEST_STRTOLL("011", 8, 9LL, 3, 0);
+ TEST_STRTOLL("011", 0, 9LL, 3, 0);
+ TEST_STRTOLL("-11", 8, -9LL, 3, 0);
+ TEST_STRTOLL("-011", 8, -9LL, 4, 0);
+ TEST_STRTOLL("-011", 0, -9LL, 4, 0);
+
+ TEST_STRTOLL("011", 8, 9LL, 3, 0);
+ TEST_STRTOLL("011", 0, 9LL, 3, 0);
+ TEST_STRTOLL("-11", 8, -9LL, 3, 0);
+ TEST_STRTOLL("-011", 8, -9LL, 4, 0);
+ TEST_STRTOLL("-011", 0, -9LL, 4, 0);
+
+ TEST_STRTOLL("Text", 0, 0LL, 0, 0);
+
+ TEST_STRTOLL("9223372036854775807", 10, 9223372036854775807LL, 19, 0);
+ TEST_STRTOLL("9223372036854775807", 0, 9223372036854775807LL, 19, 0);
+ TEST_STRTOLL("9223372036854775808", 0, 9223372036854775807LL, 19, ERANGE);
+ TEST_STRTOLL("9223372036854775808", 10, 9223372036854775807LL, 19, ERANGE);
+ TEST_STRTOLL("0x7FFFFFFFFFFFFFFF", 0, 9223372036854775807LL, 18, 0);
+ TEST_STRTOLL("0x7FFFFFFFFFFFFFFF", 16, 9223372036854775807LL, 18, 0);
+ TEST_STRTOLL("7FFFFFFFFFFFFFFF", 16, 9223372036854775807LL, 16, 0);
+ TEST_STRTOLL("0x8000000000000000", 0, 9223372036854775807LL, 18, ERANGE);
+ TEST_STRTOLL("0x8000000000000000", 16, 9223372036854775807LL, 18, ERANGE);
+ TEST_STRTOLL("80000000000000000", 16, 9223372036854775807LL, 17, ERANGE);
+ TEST_STRTOLL("0777777777777777777777", 0, 9223372036854775807LL, 22, 0);
+ TEST_STRTOLL("0777777777777777777777", 8, 9223372036854775807LL, 22, 0);
+ TEST_STRTOLL("777777777777777777777", 8, 9223372036854775807LL, 21, 0);
+ TEST_STRTOLL("01000000000000000000000", 0, 9223372036854775807LL, 23, ERANGE);
+ TEST_STRTOLL("01000000000000000000000", 8, 9223372036854775807LL, 23, ERANGE);
+ TEST_STRTOLL("1000000000000000000000", 8, 9223372036854775807LL, 22, ERANGE);
+
+ TEST_STRTOLL("-9223372036854775808", 10, -9223372036854775807LL -1, 20, 0);
+ TEST_STRTOLL("-9223372036854775808", 0, -9223372036854775807LL -1, 20, 0);
+ TEST_STRTOLL("-9223372036854775809", 0, -9223372036854775807LL -1, 20, ERANGE);
+ TEST_STRTOLL("-9223372036854775809", 10, -9223372036854775807LL -1, 20, ERANGE);
+ TEST_STRTOLL("-0x8000000000000000", 0, -9223372036854775807LL -1, 19, 0);
+ TEST_STRTOLL("-0x8000000000000000", 16, -9223372036854775807LL -1, 19, 0);
+ TEST_STRTOLL("-8000000000000000", 16, -9223372036854775807LL -1, 17, 0);
+ TEST_STRTOLL("-0x8000000000000001", 0, -9223372036854775807LL -1, 19, ERANGE);
+ TEST_STRTOLL("-0x8000000000000001", 16, -9223372036854775807LL -1, 19, ERANGE);
+ TEST_STRTOLL("-80000000000000001", 16, -9223372036854775807LL -1, 18, ERANGE);
+ TEST_STRTOLL("-01000000000000000000000",0, -9223372036854775807LL -1, 24, 0);
+ TEST_STRTOLL("-01000000000000000000000",8, -9223372036854775807LL -1, 24, 0);
+ TEST_STRTOLL("-1000000000000000000000", 8, -9223372036854775807LL -1, 23, 0);
+ TEST_STRTOLL("-01000000000000000000001",0, -9223372036854775807LL -1, 24, ERANGE);
+ TEST_STRTOLL("-01000000000000000000001",8, -9223372036854775807LL -1, 24, ERANGE);
+ TEST_STRTOLL("-1000000000000000000001", 8, -9223372036854775807LL -1, 23, ERANGE);
+
+ printf("success: strtoll\n");
return true;
}
static int test_strtoull(void)
{
- /* FIXME */
+ printf("test: strtoull\n");
+
+#define TEST_STRTOULL(str,base,res,diff,errnoo) TEST_STRTO_X(uint64_t,"%llu",strtoull,str,base,res,diff,errnoo)
+
+ TEST_STRTOULL("15", 10, 15LLU, 2, 0);
+ TEST_STRTOULL(" 15", 10, 15LLU, 4, 0);
+ TEST_STRTOULL("15", 0, 15LLU, 2, 0);
+ TEST_STRTOULL(" 15 ", 0, 15LLU, 3, 0);
+ TEST_STRTOULL("+15", 10, 15LLU, 3, 0);
+ TEST_STRTOULL(" +15", 10, 15LLU, 5, 0);
+ TEST_STRTOULL("+15", 0, 15LLU, 3, 0);
+ TEST_STRTOULL(" +15 ", 0, 15LLU, 4, 0);
+ TEST_STRTOULL("-15", 10, 18446744073709551601LLU, 3, 0);
+ TEST_STRTOULL(" -15", 10, 18446744073709551601LLU, 5, 0);
+ TEST_STRTOULL("-15", 0, 18446744073709551601LLU, 3, 0);
+ TEST_STRTOULL(" -15 ", 0, 18446744073709551601LLU, 4, 0);
+ TEST_STRTOULL("015", 10, 15LLU, 3, 0);
+ TEST_STRTOULL(" 015", 10, 15LLU, 5, 0);
+ TEST_STRTOULL("015", 0, 13LLU, 3, 0);
+ TEST_STRTOULL(" 015", 0, 13LLU, 5, 0);
+ TEST_STRTOULL("0x15", 10, 0LLU, 1, 0);
+ TEST_STRTOULL(" 0x15", 10, 0LLU, 3, 0);
+ TEST_STRTOULL("0x15", 0, 21LLU, 4, 0);
+ TEST_STRTOULL(" 0x15", 0, 21LLU, 6, 0);
+
+ TEST_STRTOULL("10", 16, 16LLU, 2, 0);
+ TEST_STRTOULL(" 10 ", 16, 16LLU, 4, 0);
+ TEST_STRTOULL("0x10", 16, 16LLU, 4, 0);
+ TEST_STRTOULL("0x10", 0, 16LLU, 4, 0);
+ TEST_STRTOULL(" 0x10 ", 0, 16LLU, 5, 0);
+ TEST_STRTOULL("+10", 16, 16LLU, 3, 0);
+ TEST_STRTOULL(" +10 ", 16, 16LLU, 5, 0);
+ TEST_STRTOULL("+0x10", 16, 16LLU, 5, 0);
+ TEST_STRTOULL("+0x10", 0, 16LLU, 5, 0);
+ TEST_STRTOULL(" +0x10 ", 0, 16LLU, 6, 0);
+ TEST_STRTOULL("-10", 16, -16LLU, 3, 0);
+ TEST_STRTOULL(" -10 ", 16, -16LLU, 5, 0);
+ TEST_STRTOULL("-0x10", 16, -16LLU, 5, 0);
+ TEST_STRTOULL("-0x10", 0, -16LLU, 5, 0);
+ TEST_STRTOULL(" -0x10 ", 0, -16LLU, 6, 0);
+ TEST_STRTOULL("010", 16, 16LLU, 3, 0);
+ TEST_STRTOULL(" 010 ", 16, 16LLU, 5, 0);
+ TEST_STRTOULL("-010", 16, -16LLU, 4, 0);
+
+ TEST_STRTOULL("11", 8, 9LLU, 2, 0);
+ TEST_STRTOULL("011", 8, 9LLU, 3, 0);
+ TEST_STRTOULL("011", 0, 9LLU, 3, 0);
+ TEST_STRTOULL("-11", 8, -9LLU, 3, 0);
+ TEST_STRTOULL("-011", 8, -9LLU, 4, 0);
+ TEST_STRTOULL("-011", 0, -9LLU, 4, 0);
+
+ TEST_STRTOULL("011", 8, 9LLU, 3, 0);
+ TEST_STRTOULL("011", 0, 9LLU, 3, 0);
+ TEST_STRTOULL("-11", 8, -9LLU, 3, 0);
+ TEST_STRTOULL("-011", 8, -9LLU, 4, 0);
+ TEST_STRTOULL("-011", 0, -9LLU, 4, 0);
+
+ TEST_STRTOULL("Text", 0, 0LLU, 0, 0);
+
+ TEST_STRTOULL("9223372036854775807", 10, 9223372036854775807LLU, 19, 0);
+ TEST_STRTOULL("9223372036854775807", 0, 9223372036854775807LLU, 19, 0);
+ TEST_STRTOULL("9223372036854775808", 0, 9223372036854775808LLU, 19, 0);
+ TEST_STRTOULL("9223372036854775808", 10, 9223372036854775808LLU, 19, 0);
+ TEST_STRTOULL("0x7FFFFFFFFFFFFFFF", 0, 9223372036854775807LLU, 18, 0);
+ TEST_STRTOULL("0x7FFFFFFFFFFFFFFF", 16, 9223372036854775807LLU, 18, 0);
+ TEST_STRTOULL("7FFFFFFFFFFFFFFF", 16, 9223372036854775807LLU, 16, 0);
+ TEST_STRTOULL("0x8000000000000000", 0, 9223372036854775808LLU, 18, 0);
+ TEST_STRTOULL("0x8000000000000000", 16, 9223372036854775808LLU, 18, 0);
+ TEST_STRTOULL("8000000000000000", 16, 9223372036854775808LLU, 16, 0);
+ TEST_STRTOULL("0777777777777777777777", 0, 9223372036854775807LLU, 22, 0);
+ TEST_STRTOULL("0777777777777777777777", 8, 9223372036854775807LLU, 22, 0);
+ TEST_STRTOULL("777777777777777777777", 8, 9223372036854775807LLU, 21, 0);
+ TEST_STRTOULL("01000000000000000000000",0, 9223372036854775808LLU, 23, 0);
+ TEST_STRTOULL("01000000000000000000000",8, 9223372036854775808LLU, 23, 0);
+ TEST_STRTOULL("1000000000000000000000", 8, 9223372036854775808LLU, 22, 0);
+
+ TEST_STRTOULL("-9223372036854775808", 10, 9223372036854775808LLU, 20, 0);
+ TEST_STRTOULL("-9223372036854775808", 0, 9223372036854775808LLU, 20, 0);
+ TEST_STRTOULL("-9223372036854775809", 0, 9223372036854775807LLU, 20, 0);
+ TEST_STRTOULL("-9223372036854775809", 10, 9223372036854775807LLU, 20, 0);
+ TEST_STRTOULL("-0x8000000000000000", 0, 9223372036854775808LLU, 19, 0);
+ TEST_STRTOULL("-0x8000000000000000", 16, 9223372036854775808LLU, 19, 0);
+ TEST_STRTOULL("-8000000000000000", 16, 9223372036854775808LLU, 17, 0);
+ TEST_STRTOULL("-0x8000000000000001", 0, 9223372036854775807LLU, 19, 0);
+ TEST_STRTOULL("-0x8000000000000001", 16, 9223372036854775807LLU, 19, 0);
+ TEST_STRTOULL("-8000000000000001", 16, 9223372036854775807LLU, 17, 0);
+ TEST_STRTOULL("-01000000000000000000000",0, 9223372036854775808LLU, 24, 0);
+ TEST_STRTOULL("-01000000000000000000000",8, 9223372036854775808LLU, 24, 0);
+ TEST_STRTOULL("-1000000000000000000000",8, 9223372036854775808LLU, 23, 0);
+ TEST_STRTOULL("-01000000000000000000001",0, 9223372036854775807LLU, 24, 0);
+ TEST_STRTOULL("-01000000000000000000001",8, 9223372036854775807LLU, 24, 0);
+ TEST_STRTOULL("-1000000000000000000001",8, 9223372036854775807LLU, 23, 0);
+
+ TEST_STRTOULL("18446744073709551615", 0, 18446744073709551615LLU, 20, 0);
+ TEST_STRTOULL("18446744073709551615", 10, 18446744073709551615LLU, 20, 0);
+ TEST_STRTOULL("18446744073709551616", 0, 18446744073709551615LLU, 20, ERANGE);
+ TEST_STRTOULL("18446744073709551616", 10, 18446744073709551615LLU, 20, ERANGE);
+ TEST_STRTOULL("0xFFFFFFFFFFFFFFFF", 0, 18446744073709551615LLU, 18, 0);
+ TEST_STRTOULL("0xFFFFFFFFFFFFFFFF", 16, 18446744073709551615LLU, 18, 0);
+ TEST_STRTOULL("FFFFFFFFFFFFFFFF", 16, 18446744073709551615LLU, 16, 0);
+ TEST_STRTOULL("0x10000000000000000", 0, 18446744073709551615LLU, 19, ERANGE);
+ TEST_STRTOULL("0x10000000000000000", 16, 18446744073709551615LLU, 19, ERANGE);
+ TEST_STRTOULL("10000000000000000", 16, 18446744073709551615LLU, 17, ERANGE);
+ TEST_STRTOULL("01777777777777777777777",0, 18446744073709551615LLU, 23, 0);
+ TEST_STRTOULL("01777777777777777777777",8, 18446744073709551615LLU, 23, 0);
+ TEST_STRTOULL("1777777777777777777777", 8, 18446744073709551615LLU, 22, 0);
+ TEST_STRTOULL("02000000000000000000000",0, 18446744073709551615LLU, 23, ERANGE);
+ TEST_STRTOULL("02000000000000000000000",8, 18446744073709551615LLU, 23, ERANGE);
+ TEST_STRTOULL("2000000000000000000000", 8, 18446744073709551615LLU, 22, ERANGE);
+
+ TEST_STRTOULL("-18446744073709551615", 0, 1LLU, 21, 0);
+ TEST_STRTOULL("-18446744073709551615", 10, 1LLU, 21, 0);
+ TEST_STRTOULL("-18446744073709551616", 0, 18446744073709551615LLU, 21, ERANGE);
+ TEST_STRTOULL("-18446744073709551616", 10, 18446744073709551615LLU, 21, ERANGE);
+ TEST_STRTOULL("-0xFFFFFFFFFFFFFFFF", 0, 1LLU, 19, 0);
+ TEST_STRTOULL("-0xFFFFFFFFFFFFFFFF", 16, 1LLU, 19, 0);
+ TEST_STRTOULL("-FFFFFFFFFFFFFFFF", 16, 1LLU, 17, 0);
+ TEST_STRTOULL("-0x10000000000000000", 0, 18446744073709551615LLU, 20, ERANGE);
+ TEST_STRTOULL("-0x10000000000000000", 16, 18446744073709551615LLU, 20, ERANGE);
+ TEST_STRTOULL("-10000000000000000", 16, 18446744073709551615LLU, 18, ERANGE);
+ TEST_STRTOULL("-01777777777777777777777",0, 1LLU, 24, 0);
+ TEST_STRTOULL("-01777777777777777777777",8, 1LLU, 24, 0);
+ TEST_STRTOULL("-1777777777777777777777",8, 1LLU, 23, 0);
+ TEST_STRTOULL("-02000000000000000000000",0, 18446744073709551615LLU, 24, ERANGE);
+ TEST_STRTOULL("-02000000000000000000000",8, 18446744073709551615LLU, 24, ERANGE);
+ TEST_STRTOULL("-2000000000000000000000",8, 18446744073709551615LLU, 23, ERANGE);
+
+ printf("success: strtuoll\n");
return true;
}
@@ -362,19 +772,42 @@ static int test_va_copy(void)
static int test_FUNCTION(void)
{
- /* FIXME: test __FUNCTION__ macro */
+ printf("test: FUNCTION\n");
+ if (strcmp(__FUNCTION__, "test_FUNCTION") != 0) {
+ printf("failure: FAILURE [\nFAILURE invalid\n]\n");
+ return false;
+ }
+ printf("success: FUNCTION\n");
return true;
}
static int test_MIN(void)
{
- /* FIXME */
+ printf("test: MIN\n");
+ if (MIN(20, 1) != 1) {
+ printf("failure: MIN [\nMIN invalid\n]\n");
+ return false;
+ }
+ if (MIN(1, 20) != 1) {
+ printf("failure: MIN [\nMIN invalid\n]\n");
+ return false;
+ }
+ printf("success: MIN\n");
return true;
}
static int test_MAX(void)
{
- /* FIXME */
+ printf("test: MAX\n");
+ if (MAX(20, 1) != 20) {
+ printf("failure: MAX [\nMAX invalid\n]\n");
+ return false;
+ }
+ if (MAX(1, 20) != 20) {
+ printf("failure: MAX [\nMAX invalid\n]\n");
+ return false;
+ }
+ printf("success: MAX\n");
return true;
}
@@ -418,6 +851,13 @@ static int test_socketpair(void)
return true;
}
+extern int libreplace_test_strptime(void);
+
+static int test_strptime(void)
+{
+ return libreplace_test_strptime();
+}
+
struct torture_context;
bool torture_local_replace(struct torture_context *ctx)
{
@@ -426,7 +866,6 @@ bool torture_local_replace(struct torture_context *ctx)
ret &= test_strlcpy();
ret &= test_strlcat();
ret &= test_mktime();
- ret &= test_innetgr();
ret &= test_initgroups();
ret &= test_memmove();
ret &= test_strdup();
@@ -459,13 +898,13 @@ bool torture_local_replace(struct torture_context *ctx)
ret &= test_getpass();
ret &= test_inet_ntoa();
ret &= test_strtoll();
- ret &= test_strtoll();
ret &= test_strtoull();
ret &= test_va_copy();
ret &= test_FUNCTION();
ret &= test_MIN();
ret &= test_MAX();
ret &= test_socketpair();
+ ret &= test_strptime();
return ret;
}
diff --git a/source/lib/talloc/talloc.h b/source/lib/talloc/talloc.h
index 75c130a2756..51640bb28d5 100644
--- a/source/lib/talloc/talloc.h
+++ b/source/lib/talloc/talloc.h
@@ -32,10 +32,12 @@ typedef void TALLOC_CTX;
/*
this uses a little trick to allow __LINE__ to be stringified
*/
-#define _STRING_LINE_(s) #s
-#define _STRING_LINE2_(s) _STRING_LINE_(s)
-#define __LINESTR__ _STRING_LINE2_(__LINE__)
-#define __location__ __FILE__ ":" __LINESTR__
+#ifndef __location__
+#define __TALLOC_STRING_LINE1__(s) #s
+#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
+#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
+#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
+#endif
#ifndef TALLOC_DEPRECATED
#define TALLOC_DEPRECATED 0
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 2866a443d47..94c5e82d153 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -974,6 +974,9 @@ BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
}
if (errno == EINPROGRESS || errno == EALREADY ||
+#ifdef EISCONN
+ errno == EISCONN ||
+#endif
errno == EAGAIN || errno == EINTR) {
/* These are the error messages that something is
progressing. */
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index 8e8297b07e5..b6627075b02 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -101,7 +101,7 @@ int kerberos_kinit_password_ext(const char *principal,
return code;
}
- code = krb5_get_init_creds_opt_alloc(ctx, &opt);
+ code = smb_krb5_get_init_creds_opt_alloc(ctx, &opt);
if (code) {
krb5_cc_close(ctx, cc);
krb5_free_context(ctx);
@@ -140,7 +140,7 @@ int kerberos_kinit_password_ext(const char *principal,
if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
kerb_prompter, NULL, 0, NULL, opt)))
{
- krb5_get_init_creds_opt_free(opt);
+ smb_krb5_get_init_creds_opt_free(ctx, opt);
smb_krb5_free_addresses(ctx, addr);
krb5_cc_close(ctx, cc);
krb5_free_principal(ctx, me);
@@ -148,7 +148,7 @@ int kerberos_kinit_password_ext(const char *principal,
return code;
}
- krb5_get_init_creds_opt_free(opt);
+ smb_krb5_get_init_creds_opt_free(ctx, opt);
if ((code = krb5_cc_initialize(ctx, cc, me))) {
smb_krb5_free_addresses(ctx, addr);
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 68ecb131b11..c6cef087047 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -117,6 +117,26 @@ BOOL cli_receive_smb(struct cli_state *cli)
}
if (!cli_check_sign_mac(cli)) {
+ /*
+ * If we get a signature failure in sessionsetup, then
+ * the server sometimes just reflects the sent signature
+ * back to us. Detect this and allow the upper layer to
+ * retrieve the correct Windows error message.
+ */
+ if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX &&
+ (smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) &&
+ (SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) &&
+ memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 &&
+ cli_is_error(cli)) {
+
+ /*
+ * Reflected signature on login error.
+ * Set bad sig but don't close fd.
+ */
+ cli->smb_rw_error = READ_BAD_SIG;
+ return True;
+ }
+
DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
cli->smb_rw_error = READ_BAD_SIG;
close(cli->fd);
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index 993e32c1edd..7043a26408c 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -1399,9 +1399,14 @@ done:
return ret;
}
-#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
- krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt)
+ krb5_error_code smb_krb5_get_init_creds_opt_alloc(krb5_context context,
+ krb5_get_init_creds_opt **opt)
{
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+ /* Heimdal or modern MIT version */
+ return krb5_get_init_creds_opt_alloc(context, opt);
+#else
+ /* Historical MIT version */
krb5_get_init_creds_opt *my_opt;
*opt = NULL;
@@ -1414,16 +1419,28 @@ done:
*opt = my_opt;
return 0;
+#endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC */
}
-#endif
-#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE
- void krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
+ void smb_krb5_get_init_creds_opt_free(krb5_context context,
+ krb5_get_init_creds_opt *opt)
{
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE
+
+#ifdef KRB5_CREDS_OPT_FREE_REQUIRES_CONTEXT
+ /* Modern MIT version */
+ krb5_get_init_creds_opt_free(context, opt);
+#else
+ /* Heimdal version */
+ krb5_get_init_creds_opt_free(opt);
+#endif
+
+#else /* HAVE_KRB5_GET_INIT_CREDS_OPT_FREE */
+ /* Historical MIT version */
SAFE_FREE(opt);
opt = NULL;
+#endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_FREE */
}
-#endif
krb5_error_code smb_krb5_mk_error(krb5_context context,
krb5_error_code error_code,
diff --git a/source/libsmb/namequery_dc.c b/source/libsmb/namequery_dc.c
index 110b9986b7f..65e860d45e7 100644
--- a/source/libsmb/namequery_dc.c
+++ b/source/libsmb/namequery_dc.c
@@ -215,6 +215,11 @@ BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct
if ( (our_domain && lp_security()==SEC_ADS) || realm ) {
ret = ads_dc_name(domain, realm, &dc_ip, srv_name);
}
+
+ if (!domain) {
+ /* if we have only the realm we can't do anything else */
+ return False;
+ }
if (!ret) {
/* fall back on rpc methods if the ADS methods fail */
diff --git a/source/libsmb/smb_share_modes.c b/source/libsmb/smb_share_modes.c
index 9236a96c5b2..b63ec7ff78b 100644
--- a/source/libsmb/smb_share_modes.c
+++ b/source/libsmb/smb_share_modes.c
@@ -28,6 +28,11 @@
#include "includes.h"
#include "smb_share_modes.h"
+/* Database context handle. */
+struct smbdb_ctx {
+ TDB_CONTEXT *smb_tdb;
+};
+
/* Remove the paranoid malloc checker. */
#ifdef malloc
#undef malloc
diff --git a/source/modules/vfs_gpfs.c b/source/modules/vfs_gpfs.c
index 20c9f56a170..6841300d5b3 100644
--- a/source/modules/vfs_gpfs.c
+++ b/source/modules/vfs_gpfs.c
@@ -597,8 +597,7 @@ int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
files_struct *fsp,
int fd, SMB_ACL_T theacl)
{
- errno = ENOTSUP;
- return -1;
+ return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name, SMB_ACL_TYPE_ACCESS, theacl);
}
int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
diff --git a/source/modules/vfs_readahead.c b/source/modules/vfs_readahead.c
index 550562d03d0..9c20acebd94 100644
--- a/source/modules/vfs_readahead.c
+++ b/source/modules/vfs_readahead.c
@@ -101,12 +101,12 @@ static ssize_t readahead_pread(vfs_handle_struct *handle,
(unsigned int)rhd->len,
err ));
#elif defined(HAVE_POSIX_FADVISE)
- int err = posix_fadvise(fromfd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
+ int err = posix_fadvise(fd, offset, (off_t)rhd->len, POSIX_FADV_WILLNEED);
DEBUG(10,("readahead_pread: posix_fadvise on fd %u, offset %llu, len %u returned %d\n",
(unsigned int)fd,
(unsigned long long)offset,
(unsigned int)rhd->len,
- (err ));
+ err ));
#else
if (!rhd->didmsg) {
DEBUG(0,("readahead_pread: no readahead on this platform\n"));
diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c
index 04df3e9a4f9..4b04751235d 100644
--- a/source/nmbd/nmbd_subnetdb.c
+++ b/source/nmbd/nmbd_subnetdb.c
@@ -223,6 +223,13 @@ BOOL create_subnets(void)
return False;
}
+ /* We must have at least one subnet. */
+ if (subnetlist == NULL) {
+ DEBUG(0,("create_subnets: unable to create any subnet from "
+ "given interfaces. nmbd is terminating\n"));
+ return False;
+ }
+
if (lp_we_are_a_wins_server()) {
/* Pick the first interface ip address as the WINS server ip. */
struct in_addr *nip = iface_n_ip(0);
diff --git a/source/nsswitch/idmap.c b/source/nsswitch/idmap.c
index 1bd93affac8..530e03089d0 100644
--- a/source/nsswitch/idmap.c
+++ b/source/nsswitch/idmap.c
@@ -43,6 +43,12 @@ struct idmap_alloc_backend {
struct idmap_cache_ctx;
+struct idmap_alloc_context {
+ const char *params;
+ struct idmap_alloc_methods *methods;
+ BOOL initialized;
+};
+
static TALLOC_CTX *idmap_ctx = NULL;
static struct idmap_cache_ctx *idmap_cache;
@@ -53,9 +59,10 @@ static int pdb_dom_num = -1;
static int def_dom_num = -1;
static struct idmap_alloc_backend *alloc_backends = NULL;
-static struct idmap_alloc_methods *alloc_methods = NULL;
+static struct idmap_alloc_context *idmap_alloc_ctx = NULL;
#define IDMAP_CHECK_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); goto done; } } while(0)
+#define IDMAP_REPORT_RET(ret) do { if ( ! NT_STATUS_IS_OK(ret)) { DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); } } while(0)
#define IDMAP_CHECK_ALLOC(mem) do { if (!mem) { DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; goto done; } } while(0)
static struct idmap_methods *get_methods(struct idmap_backend *be, const char *name)
@@ -84,6 +91,12 @@ static struct idmap_alloc_methods *get_alloc_methods(struct idmap_alloc_backend
return NULL;
}
+BOOL idmap_is_offline(void)
+{
+ return ( lp_winbind_offline_logon() &&
+ get_global_winbindd_state_offline() );
+}
+
/**********************************************************************
Allow a module to register itself as a method.
**********************************************************************/
@@ -203,9 +216,9 @@ static int close_domain_destructor(struct idmap_domain *dom)
NTSTATUS idmap_close(void)
{
/* close the alloc backend first before freeing idmap_ctx */
- if (alloc_methods) {
- alloc_methods->close_fn();
- alloc_methods = NULL;
+ if (idmap_alloc_ctx) {
+ idmap_alloc_ctx->methods->close_fn();
+ idmap_alloc_ctx->methods = NULL;
}
alloc_backends = NULL;
@@ -254,35 +267,23 @@ NTSTATUS idmap_init_cache(void)
NTSTATUS idmap_init(void)
{
NTSTATUS ret;
- static NTSTATUS backend_init_status = NT_STATUS_UNSUCCESSFUL;
+ static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL;
struct idmap_domain *dom;
char *compat_backend = NULL;
char *compat_params = NULL;
const char **dom_list = NULL;
- char *alloc_backend;
+ char *alloc_backend = NULL;
BOOL default_already_defined = False;
BOOL pri_dom_is_in_list = False;
int compat = 0;
int i;
- /* Always initialize the cache. We'll have to delay initialization
- of backends if we are offline */
-
ret = idmap_init_cache();
if ( !NT_STATUS_IS_OK(ret) )
return ret;
- if ( NT_STATUS_IS_OK(backend_init_status) ) {
+ if (NT_STATUS_IS_OK(idmap_init_status))
return NT_STATUS_OK;
- }
-
- /* We can't reliably call intialization code here unless
- we are online */
-
- if ( get_global_winbindd_state_offline() ) {
- backend_init_status = NT_STATUS_FILE_IS_OFFLINE;
- return backend_init_status;
- }
static_init_idmap;
@@ -414,13 +415,18 @@ NTSTATUS idmap_init(void)
/* now that we have methods, set the destructor for this domain */
talloc_set_destructor(dom, close_domain_destructor);
+ if (compat_params) {
+ dom->params = talloc_strdup(dom, compat_params);
+ IDMAP_CHECK_ALLOC(dom->params);
+ } else {
+ dom->params = NULL;
+ }
+
/* Finally instance a backend copy for this domain */
- ret = dom->methods->init(dom, compat_params);
+ ret = dom->methods->init(dom);
if ( ! NT_STATUS_IS_OK(ret)) {
- DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s)\n",
+ DEBUG(0, ("ERROR: Initialization failed for backend %s (domain %s), deferred!\n",
parm_backend, dom->name));
- ret = NT_STATUS_UNSUCCESSFUL;
- goto done;
}
idmap_domains = talloc_realloc(idmap_ctx, idmap_domains, struct idmap_domain *, i+1);
if ( ! idmap_domains) {
@@ -471,8 +477,15 @@ NTSTATUS idmap_init(void)
/* now that we have methods, set the destructor for this domain */
talloc_set_destructor(dom, close_domain_destructor);
+ if (compat_params) {
+ dom->params = talloc_strdup(dom, compat_params);
+ IDMAP_CHECK_ALLOC(dom->params);
+ } else {
+ dom->params = NULL;
+ }
+
/* Finally instance a backend copy for this domain */
- ret = dom->methods->init(dom, compat_params);
+ ret = dom->methods->init(dom);
if ( ! NT_STATUS_IS_OK(ret)) {
DEBUG(0, ("ERROR: Initialization failed for idmap_nss ?!\n"));
ret = NT_STATUS_UNSUCCESSFUL;
@@ -515,8 +528,15 @@ NTSTATUS idmap_init(void)
/* now that we have methods, set the destructor for this domain */
talloc_set_destructor(dom, close_domain_destructor);
+ if (compat_params) {
+ dom->params = talloc_strdup(dom, compat_params);
+ IDMAP_CHECK_ALLOC(dom->params);
+ } else {
+ dom->params = NULL;
+ }
+
/* Finally instance a backend copy for this domain */
- ret = dom->methods->init(dom, compat_params);
+ ret = dom->methods->init(dom);
if ( ! NT_STATUS_IS_OK(ret)) {
DEBUG(0, ("ERROR: Initialization failed for idmap_passdb ?!\n"));
ret = NT_STATUS_UNSUCCESSFUL;
@@ -561,11 +581,11 @@ NTSTATUS idmap_init(void)
}
- /***************************
- * initialize alloc module
- */
- DEBUG(1, ("Initializing idmap alloc module\n"));
+ /* Initialize alloc module */
+
+ DEBUG(3, ("Initializing idmap alloc module\n"));
+ alloc_backend = NULL;
if (compat) {
alloc_backend = talloc_strdup(idmap_ctx, compat_backend);
} else {
@@ -573,41 +593,54 @@ NTSTATUS idmap_init(void)
if (ab && (ab[0] != '\0')) {
alloc_backend = talloc_strdup(idmap_ctx, lp_idmap_alloc_backend());
- } else {
- alloc_backend = talloc_strdup(idmap_ctx, "tdb");
}
}
- IDMAP_CHECK_ALLOC(alloc_backend);
- alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
- if ( ! alloc_methods) {
- ret = smb_probe_module("idmap", alloc_backend);
- if (NT_STATUS_IS_OK(ret)) {
- alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
+ if ( alloc_backend ) {
+
+ idmap_alloc_ctx = talloc_zero(idmap_ctx, struct idmap_alloc_context);
+ IDMAP_CHECK_ALLOC(idmap_alloc_ctx);
+
+ idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, alloc_backend);
+ if ( ! idmap_alloc_ctx->methods) {
+ ret = smb_probe_module("idmap", alloc_backend);
+ if (NT_STATUS_IS_OK(ret)) {
+ idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends, alloc_backend);
+ }
}
- }
- if ( alloc_methods) {
- ret = alloc_methods->init(compat_params);
- if ( ! NT_STATUS_IS_OK(ret)) {
- DEBUG(0, ("idmap_init: Initialization failed for alloc "
- "backend %s\n", alloc_backend));
- ret = NT_STATUS_UNSUCCESSFUL;
- goto done;
+ if (idmap_alloc_ctx->methods) {
+
+ if (compat_params) {
+ idmap_alloc_ctx->params = talloc_strdup(idmap_alloc_ctx, compat_params);
+ IDMAP_CHECK_ALLOC(idmap_alloc_ctx->params);
+ } else {
+ idmap_alloc_ctx->params = NULL;
+ }
+
+ ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("ERROR: Initialization failed for alloc "
+ "backend %s, deferred!\n", alloc_backend));
+ } else {
+ idmap_alloc_ctx->initialized = True;
+ }
+ } else {
+ DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n",
+ alloc_backend));
+ /* certain compat backends are just readonly */
+ if ( compat ) {
+ TALLOC_FREE(idmap_alloc_ctx);
+ ret = NT_STATUS_OK;
+ } else {
+ ret = NT_STATUS_UNSUCCESSFUL;
+ }
}
- } else {
- DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n",
- alloc_backend));
- /* certain compat backends are just readonly */
- if ( compat )
- ret = NT_STATUS_OK;
- else
- ret = NT_STATUS_UNSUCCESSFUL;
}
-
+
/* cleanpu temporary strings */
TALLOC_FREE( compat_backend );
-
- backend_init_status = NT_STATUS_OK;
+
+ idmap_init_status = NT_STATUS_OK;
return ret;
@@ -615,12 +648,35 @@ done:
DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
idmap_close();
- /* save the init status for later checks */
- backend_init_status = ret;
-
return ret;
}
+static NTSTATUS idmap_alloc_init(void)
+{
+ NTSTATUS ret;
+
+ if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ return ret;
+ }
+
+ if ( ! idmap_alloc_ctx) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
+ if ( ! idmap_alloc_ctx->initialized) {
+ ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("ERROR: Initialization failed for alloc "
+ "backend, deferred!\n"));
+ return ret;
+ } else {
+ idmap_alloc_ctx->initialized = True;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
/**************************************************************************
idmap allocator interface functions
**************************************************************************/
@@ -629,48 +685,48 @@ NTSTATUS idmap_allocate_uid(struct unixid *id)
{
NTSTATUS ret;
- if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
return ret;
}
id->type = ID_TYPE_UID;
- return alloc_methods->allocate_id(id);
+ return idmap_alloc_ctx->methods->allocate_id(id);
}
NTSTATUS idmap_allocate_gid(struct unixid *id)
{
NTSTATUS ret;
- if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
return ret;
}
id->type = ID_TYPE_GID;
- return alloc_methods->allocate_id(id);
+ return idmap_alloc_ctx->methods->allocate_id(id);
}
NTSTATUS idmap_set_uid_hwm(struct unixid *id)
{
NTSTATUS ret;
- if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
return ret;
}
id->type = ID_TYPE_UID;
- return alloc_methods->set_id_hwm(id);
+ return idmap_alloc_ctx->methods->set_id_hwm(id);
}
NTSTATUS idmap_set_gid_hwm(struct unixid *id)
{
NTSTATUS ret;
- if (! NT_STATUS_IS_OK(ret = idmap_init())) {
+ if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
return ret;
}
id->type = ID_TYPE_GID;
- return alloc_methods->set_id_hwm(id);
+ return idmap_alloc_ctx->methods->set_id_hwm(id);
}
/******************************************************************************
@@ -781,68 +837,57 @@ static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map)
{
NTSTATUS ret;
struct idmap_domain *dom;
- const char *domname, *name;
- enum lsa_SidType sid_type;
- BOOL wbret;
+
+ /* If we are offline we cannot lookup SIDs, deny mapping */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
ret = idmap_can_map(map, &dom);
if ( ! NT_STATUS_IS_OK(ret)) {
return NT_STATUS_NONE_MAPPED;
}
-
- /* by default calls to winbindd are disabled
- the following call will not recurse so this is safe */
- winbind_on();
- wbret = winbind_lookup_sid(ctx, map->sid, &domname, &name, &sid_type);
- winbind_off();
/* check if this is a valid SID and then map it */
- if (wbret) {
- switch (sid_type) {
- case SID_NAME_USER:
- ret = idmap_allocate_uid(&map->xid);
- if ( ! NT_STATUS_IS_OK(ret)) {
- /* can't allocate id, let's just leave it unmapped */
- DEBUG(2, ("uid allocation failed! Can't create mapping\n"));
- return NT_STATUS_NONE_MAPPED;
- }
- break;
- case SID_NAME_DOM_GRP:
- case SID_NAME_ALIAS:
- case SID_NAME_WKN_GRP:
- ret = idmap_allocate_gid(&map->xid);
- if ( ! NT_STATUS_IS_OK(ret)) {
- /* can't allocate id, let's just leave it unmapped */
- DEBUG(2, ("gid allocation failed! Can't create mapping\n"));
- return NT_STATUS_NONE_MAPPED;
- }
- break;
- default:
- /* invalid sid, let's just leave it unmapped */
- DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid)));
+ switch (map->xid.type) {
+ case ID_TYPE_UID:
+ ret = idmap_allocate_uid(&map->xid);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* can't allocate id, let's just leave it unmapped */
+ DEBUG(2, ("uid allocation failed! Can't create mapping\n"));
return NT_STATUS_NONE_MAPPED;
}
+ break;
+ case ID_TYPE_GID:
+ ret = idmap_allocate_gid(&map->xid);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* can't allocate id, let's just leave it unmapped */
+ DEBUG(2, ("gid allocation failed! Can't create mapping\n"));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ break;
+ default:
+ /* invalid sid, let's just leave it unmapped */
+ DEBUG(3,("idmap_new_mapping: Refusing to create a "
+ "mapping for an unspecified ID type.\n"));
+ return NT_STATUS_NONE_MAPPED;
+ }
- /* ok, got a new id, let's set a mapping */
- map->status = ID_MAPPED;
+ /* ok, got a new id, let's set a mapping */
+ map->status = ID_MAPPED;
- DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
- sid_string_static(map->sid),
- (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
- (unsigned long)map->xid.id));
- ret = dom->methods->set_mapping(dom, map);
+ DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
+ sid_string_static(map->sid),
+ (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
+ (unsigned long)map->xid.id));
+ ret = dom->methods->set_mapping(dom, map);
- if ( ! NT_STATUS_IS_OK(ret)) {
- /* something wrong here :-( */
- DEBUG(2, ("Failed to commit mapping\n!"));
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ /* something wrong here :-( */
+ DEBUG(2, ("Failed to commit mapping\n!"));
- /* TODO: would it make sense to have an "unalloc_id function?" */
+ /* TODO: would it make sense to have an "unalloc_id function?" */
- return NT_STATUS_NONE_MAPPED;
- }
- } else {
- DEBUG(2,("Invalid SID, not mapping %s (type %d)\n",
- sid_string_static(map->sid), sid_type));
return NT_STATUS_NONE_MAPPED;
}
@@ -896,11 +941,6 @@ static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
_ids = ids;
- /* make sure all maps are marked as in UNKNOWN status */
- for (i = 0; _ids[i]; i++) {
- _ids[i]->status = ID_UNKNOWN;
- }
-
unmapped = NULL;
for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */
@@ -909,12 +949,12 @@ static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
DEBUG(10, ("Query sids from domain %s\n", dom->name));
ret = dom->methods->unixids_to_sids(dom, _ids);
- IDMAP_CHECK_RET(ret);
+ IDMAP_REPORT_RET(ret);
unmapped = NULL;
for (i = 0, u = 0; _ids[i]; i++) {
- if (_ids[i]->status == ID_UNKNOWN || _ids[i]->status == ID_UNMAPPED) {
+ if (_ids[i]->status != ID_MAPPED) {
unmapped = talloc_realloc(ctx, unmapped, struct id_map *, u + 2);
IDMAP_CHECK_ALLOC(unmapped);
unmapped[u] = _ids[i];
@@ -934,7 +974,9 @@ static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
if (unmapped) {
/* there are still unmapped ids, map them to the unix users/groups domains */
+ /* except for expired entries, these will be returned as valid (offline mode) */
for (i = 0; unmapped[i]; i++) {
+ if (unmapped[i]->status == ID_EXPIRED) continue;
switch (unmapped[i]->xid.type) {
case ID_TYPE_UID:
uid_to_unix_users_sid((uid_t)unmapped[i]->xid.id, unmapped[i]->sid);
@@ -984,11 +1026,8 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
for (i = 0; ids[i]; i++) {
uint32 idx;
- /* make sure they are unknown to start off */
- ids[i]->status = ID_UNKNOWN;
-
if ( (dom = find_idmap_domain_from_sid( ids[i]->sid )) == NULL ) {
- /* no vailable idmap_domain. Move on */
+ /* no available idmap_domain. Move on */
continue;
}
@@ -1016,7 +1055,7 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
dom = idmap_domains[i];
DEBUG(10, ("Query ids from domain %s\n", dom->name));
ret = dom->methods->sids_to_unixids(dom, dom_ids[i]);
- IDMAP_CHECK_RET(ret);
+ IDMAP_REPORT_RET(ret);
}
}
@@ -1024,6 +1063,8 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
/* let's see if we have any unmapped SID left and act accordingly */
for (i = 0; ids[i]; i++) {
+ /* NOTE: this will NOT touch ID_EXPIRED entries that the backend
+ * was not able to confirm/deny (offline mode) */
if (ids[i]->status == ID_UNKNOWN || ids[i]->status == ID_UNMAPPED) {
/* ok this is an unmapped one, see if we can map it */
ret = idmap_new_mapping(ctx, ids[i]);
@@ -1034,7 +1075,8 @@ static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
/* could not map it */
ids[i]->status = ID_UNMAPPED;
} else {
- /* Something very bad happened down there */
+ /* Something very bad happened down there
+ * OR we are offline */
ids[i]->status = ID_UNKNOWN;
}
}
@@ -1123,13 +1165,6 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids)
/* let's see if there is any id mapping to be retieved from the backends */
if (bi) {
- /* Only do query if we are online */
- if ( lp_winbind_offline_logon() &&
- get_global_winbindd_state_offline() )
- {
- ret = NT_STATUS_FILE_IS_OFFLINE;
- goto done;
- }
ret = idmap_backends_unixids_to_sids(bids);
IDMAP_CHECK_RET(ret);
@@ -1138,11 +1173,17 @@ NTSTATUS idmap_unixids_to_sids(struct id_map **ids)
for (i = 0; i < bi; i++) {
if (bids[i]->status == ID_MAPPED) {
ret = idmap_cache_set(idmap_cache, bids[i]);
+ } else if (bids[i]->status == ID_EXPIRED) {
+ /* the cache returned an expired entry and the backend was
+ * was not able to clear the situation (offline).
+ * This handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * for disconnected mode, */
+ bids[i]->status = ID_MAPPED;
} else if (bids[i]->status == ID_UNKNOWN) {
- /* return an expired entry in the cache or an unknown */
- /* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
- * for disconnected mode */
- idmap_cache_map_id(idmap_cache, ids[i]);
+ /* something bad here. We were not able to handle this for some
+ * reason, mark it as unmapped and hope next time things will
+ * settle down. */
+ bids[i]->status = ID_UNMAPPED;
} else { /* unmapped */
ret = idmap_cache_set_negative_id(idmap_cache, bids[i]);
}
@@ -1229,13 +1270,6 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids)
/* let's see if there is any id mapping to be retieved from the backends */
if (bids) {
- /* Only do query if we are online */
- if ( lp_winbind_offline_logon() &&
- get_global_winbindd_state_offline() )
- {
- ret = NT_STATUS_FILE_IS_OFFLINE;
- goto done;
- }
ret = idmap_backends_sids_to_unixids(bids);
IDMAP_CHECK_RET(ret);
@@ -1244,12 +1278,18 @@ NTSTATUS idmap_sids_to_unixids(struct id_map **ids)
for (i = 0; bids[i]; i++) {
if (bids[i]->status == ID_MAPPED) {
ret = idmap_cache_set(idmap_cache, bids[i]);
+ } else if (bids[i]->status == ID_EXPIRED) {
+ /* the cache returned an expired entry and the backend was
+ * was not able to clear the situation (offline).
+ * This handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * for disconnected mode, */
+ bids[i]->status = ID_MAPPED;
} else if (bids[i]->status == ID_UNKNOWN) {
- /* return an expired entry in the cache or an unknown */
- /* this handles a previous NT_STATUS_SYNCHRONIZATION_REQUIRED
- * for disconnected mode */
- idmap_cache_map_id(idmap_cache, ids[i]);
- } else {
+ /* something bad here. We were not able to handle this for some
+ * reason, mark it as unmapped and hope next time things will
+ * settle down. */
+ bids[i]->status = ID_UNMAPPED;
+ } else { /* unmapped */
ret = idmap_cache_set_negative_sid(idmap_cache, bids[i]);
}
IDMAP_CHECK_RET(ret);
@@ -1321,16 +1361,18 @@ void idmap_dump_maps(char *logfile)
return;
}
- allid.type = ID_TYPE_UID;
- allid.id = 0;
- alloc_methods->get_id_hwm(&allid);
- fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id);
-
- allid.type = ID_TYPE_GID;
- allid.id = 0;
- alloc_methods->get_id_hwm(&allid);
- fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id);
-
+ if (NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
+ allid.type = ID_TYPE_UID;
+ allid.id = 0;
+ idmap_alloc_ctx->methods->get_id_hwm(&allid);
+ fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id);
+
+ allid.type = ID_TYPE_GID;
+ allid.id = 0;
+ idmap_alloc_ctx->methods->get_id_hwm(&allid);
+ fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id);
+ }
+
maps = talloc(idmap_ctx, struct id_map);
num_maps = 0;
@@ -1352,6 +1394,8 @@ void idmap_dump_maps(char *logfile)
(unsigned long)maps[i].xid.id,
sid_string_static(maps[i].sid));
break;
+ case ID_TYPE_NOT_SPECIFIED:
+ break;
}
}
@@ -1381,3 +1425,4 @@ char *idmap_fetch_secret(const char *backend, bool alloc,
return ret;
}
+
diff --git a/source/nsswitch/idmap_ad.c b/source/nsswitch/idmap_ad.c
index 5ec543819ef..e15e4b90fb8 100644
--- a/source/nsswitch/idmap_ad.c
+++ b/source/nsswitch/idmap_ad.c
@@ -160,17 +160,12 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
/************************************************************************
***********************************************************************/
-static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params)
+static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
{
struct idmap_ad_context *ctx;
char *config_option;
- const char *range;
- ADS_STRUCT *ads;
-
- /* verify AD is reachable (not critical, we may just be offline at start) */
- if ( (ads = ad_idmap_cached_connection()) == NULL ) {
- DEBUG(1, ("WARNING: Could not init an AD connection! Mapping might not work.\n"));
- }
+ const char *range = NULL;
+ const char *schema_mode = NULL;
if ( (ctx = talloc_zero(dom, struct idmap_ad_context)) == NULL ) {
DEBUG(0, ("Out of memory!\n"));
@@ -194,7 +189,22 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params
}
}
+ /* schema mode */
+ if ( ad_map_type == WB_POSIX_MAP_UNKNOWN )
+ ad_map_type = WB_POSIX_MAP_RFC2307;
+ schema_mode = lp_parm_const_string(-1, config_option, "schema_mode", NULL);
+ if ( schema_mode && schema_mode[0] ) {
+ if ( strequal(schema_mode, "sfu") )
+ ad_map_type = WB_POSIX_MAP_SFU;
+ else if ( strequal(schema_mode, "rfc2307" ) )
+ ad_map_type = WB_POSIX_MAP_RFC2307;
+ else
+ DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n",
+ schema_mode));
+ }
+
dom->private_data = ctx;
+ dom->initialized = True;
talloc_free(config_option);
@@ -251,6 +261,7 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
NULL, /* gidnumber */
NULL };
LDAPMessage *res = NULL;
+ LDAPMessage *entry = NULL;
char *filter = NULL;
int idx = 0;
int bidx = 0;
@@ -259,6 +270,19 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
char *u_filter = NULL;
char *g_filter = NULL;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
+ /* Initilization my have been deferred because we were offline */
+ if ( ! dom->initialized) {
+ ret = idmap_ad_initialize(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
if ( (memctx = talloc_new(ctx)) == NULL ) {
@@ -310,7 +334,7 @@ again:
break;
default:
- DEBUG(3, ("Unknown ID type\n"));
+ DEBUG(3, ("Error: mapping requested but Unknown ID type\n"));
ids[idx]->status = ID_UNKNOWN;
continue;
}
@@ -329,7 +353,7 @@ again:
}
filter = talloc_asprintf_append(filter, ")");
CHECK_ALLOC_DONE(filter);
- DEBUG(10, ("Filter: [%s]\n", filter));
+
rc = ads_search_retry(ads, &res, filter, attrs);
if (!ADS_ERR_OK(rc)) {
DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
@@ -341,8 +365,8 @@ again:
DEBUG(10, ("No IDs found\n"));
}
- for (i = 0; i < count; i++) {
- LDAPMessage *entry = NULL;
+ entry = res;
+ for (i = 0; (i < count) && entry; i++) {
DOM_SID sid;
enum id_type type;
struct id_map *map;
@@ -350,13 +374,14 @@ again:
uint32_t atype;
if (i == 0) { /* first entry */
- entry = ads_first_entry(ads, res);
+ entry = ads_first_entry(ads, entry);
} else { /* following ones */
entry = ads_next_entry(ads, entry);
}
- if ( ! entry) {
+
+ if ( !entry ) {
DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
- continue;
+ break;
}
/* first check if the SID is present */
@@ -430,9 +455,9 @@ again:
ret = NT_STATUS_OK;
- /* mark all unknown ones as unmapped */
+ /* mark all unknown/expired ones as unmapped */
for (i = 0; ids[i]; i++) {
- if (ids[i]->status == ID_UNKNOWN)
+ if (ids[i]->status != ID_MAPPED)
ids[i]->status = ID_UNMAPPED;
}
@@ -457,6 +482,7 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
NULL, /* attr_gidnumber */
NULL };
LDAPMessage *res = NULL;
+ LDAPMessage *entry = NULL;
char *filter = NULL;
int idx = 0;
int bidx = 0;
@@ -464,6 +490,19 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
int i;
char *sidstr;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
+ /* Initilization my have been deferred because we were offline */
+ if ( ! dom->initialized) {
+ ret = idmap_ad_initialize(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
if ( (memctx = talloc_new(ctx)) == NULL ) {
@@ -514,8 +553,8 @@ again:
DEBUG(10, ("No IDs found\n"));
}
- for (i = 0; i < count; i++) {
- LDAPMessage *entry = NULL;
+ entry = res;
+ for (i = 0; (i < count) && entry; i++) {
DOM_SID sid;
enum id_type type;
struct id_map *map;
@@ -523,13 +562,14 @@ again:
uint32_t atype;
if (i == 0) { /* first entry */
- entry = ads_first_entry(ads, res);
+ entry = ads_first_entry(ads, entry);
} else { /* following ones */
entry = ads_next_entry(ads, entry);
}
- if ( ! entry) {
+
+ if ( !entry ) {
DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
- continue;
+ break;
}
/* first check if the SID is present */
@@ -602,9 +642,9 @@ again:
ret = NT_STATUS_OK;
- /* mark all unknwon ones as unmapped */
+ /* mark all unknwoni/expired ones as unmapped */
for (i = 0; ids[i]; i++) {
- if (ids[i]->status == ID_UNKNOWN)
+ if (ids[i]->status != ID_MAPPED)
ids[i]->status = ID_UNMAPPED;
}
@@ -655,9 +695,6 @@ static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
ad_map_type = WB_POSIX_MAP_SFU;
- if ( !ad_idmap_ads )
- return idmap_ad_initialize( NULL, NULL );
-
return NT_STATUS_OK;
}
@@ -676,9 +713,6 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
ad_map_type = WB_POSIX_MAP_RFC2307;
- if ( !ad_idmap_ads )
- return idmap_ad_initialize( NULL, NULL );
-
return NT_STATUS_OK;
}
@@ -697,6 +731,11 @@ static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
{
ADS_STRUCT *ads_internal = NULL;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
/* We are assuming that the internal ADS_STRUCT is for the
same forest as the incoming *ads pointer */
diff --git a/source/nsswitch/idmap_cache.c b/source/nsswitch/idmap_cache.c
index 689f363e535..037b1cb1e81 100644
--- a/source/nsswitch/idmap_cache.c
+++ b/source/nsswitch/idmap_cache.c
@@ -365,7 +365,7 @@ BOOL idmap_cache_is_negative(const char *val)
/* search the cahce for the SID an return a mapping if found *
*
- * 3 cases are possible
+ * 4 cases are possible
*
* 1 map found
* in this case id->status = ID_MAPPED and NT_STATUS_OK is returned
@@ -373,21 +373,20 @@ BOOL idmap_cache_is_negative(const char *val)
* in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned
* 3 negative cache found
* in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned
- *
- * As a special case if the cache is expired NT_STATUS_SYNCHRONIZATION_REQUIRED
- * is returned instead of NT_STATUS_OK. In this case revalidation of the cache
- * is needed.
+ * 4 map found but timer expired
+ * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * is returned. In this case revalidation of the cache is needed.
*/
NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id)
{
NTSTATUS ret;
TDB_DATA keybuf, databuf;
- time_t t;
+ time_t t, now;
char *sidkey;
char *endptr;
- /* make sure it is marked as not mapped by default */
+ /* make sure it is marked as unknown by default */
id->status = ID_UNKNOWN;
ret = idmap_cache_build_sidkey(cache, &sidkey, id);
@@ -413,11 +412,13 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id)
goto done;
}
+ now = time(NULL);
+
/* check it is not negative */
if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) {
-
+
DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
- "timeout = %s", t > time(NULL) ? "valid" :
+ "timeout = %s", t > now ? "valid" :
"expired", sidkey, endptr+1, ctime(&t)));
/* this call if successful will also mark the entry as mapped */
@@ -431,35 +432,21 @@ NTSTATUS idmap_cache_map_sid(struct idmap_cache_ctx *cache, struct id_map *id)
/* here ret == NT_STATUS_OK and id->status = ID_MAPPED */
- if (t <= time(NULL)) {
- /* If we've been told to be offline - stay in
- that state... */
- if (lp_winbind_offline_logon() &&
- get_global_winbindd_state_offline())
- {
- DEBUG(10,("idmap_cache_map_sid: winbindd is "
- "globally offline.\n"));
- } else {
- /* We're expired, set an error code
- for upper layer */
- ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
- }
+ if (t <= now) {
+
+ /* we have it, but it is expired */
+ id->status = ID_EXPIRED;
+
+ /* We're expired, set an error code
+ for upper layer */
+ ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
}
} else {
- if (t <= time(NULL)) {
- /* If we've been told to be offline - stay in
- that state... */
- if (lp_winbind_offline_logon() &&
- get_global_winbindd_state_offline())
- {
- DEBUG(10,("idmap_cache_map_sid: winbindd is "
- "globally offline.\n"));
- } else {
- /* We're expired, delete the entry and return
- not mapped */
- tdb_delete(cache->tdb, keybuf);
- ret = NT_STATUS_NONE_MAPPED;
- }
+ if (t <= now) {
+ /* We're expired, delete the NEGATIVE entry and return
+ not mapped */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
} else {
/* this is not mapped as it was a negative cache hit */
id->status = ID_UNMAPPED;
@@ -483,21 +470,20 @@ done:
* in this case id->status = ID_UNKNOWN and NT_STATUS_NONE_MAPPED is returned
* 3 negative cache found
* in this case id->status = ID_UNMAPPED and NT_STATUS_OK is returned
- *
- * As a special case if the cache is expired NT_STATUS_SYNCHRONIZATION_REQUIRED
- * is returned instead of NT_STATUS_OK. In this case revalidation of the cache
- * is needed.
+ * 4 map found but timer expired
+ * in this case id->status = ID_EXPIRED and NT_STATUS_SYNCHRONIZATION_REQUIRED
+ * is returned. In this case revalidation of the cache is needed.
*/
NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
{
NTSTATUS ret;
TDB_DATA keybuf, databuf;
- time_t t;
+ time_t t, now;
char *idkey;
char *endptr;
- /* make sure it is marked as not mapped by default */
+ /* make sure it is marked as unknown by default */
id->status = ID_UNKNOWN;
ret = idmap_cache_build_idkey(cache, &idkey, id);
@@ -523,11 +509,13 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
goto done;
}
+ now = time(NULL);
+
/* check it is not negative */
if (strcmp("IDMAP/NEGATIVE", endptr+1) != 0) {
DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
- "timeout = %s", t > time(NULL) ? "valid" :
+ "timeout = %s", t > now ? "valid" :
"expired", idkey, endptr+1, ctime(&t)));
/* this call if successful will also mark the entry as mapped */
@@ -539,39 +527,25 @@ NTSTATUS idmap_cache_map_id(struct idmap_cache_ctx *cache, struct id_map *id)
goto done;
}
- /* here ret == NT_STATUS_OK and id->mapped = True */
-
- if (t <= time(NULL)) {
- /* If we've been told to be offline - stay in
- that state... */
- if (lp_winbind_offline_logon() &&
- get_global_winbindd_state_offline())
- {
- DEBUG(10,("idmap_cache_map_sid: winbindd is "
- "globally offline.\n"));
- } else {
- /* We're expired, set an error code
- for upper layer */
- ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
- }
+ /* here ret == NT_STATUS_OK and id->mapped = ID_MAPPED */
+
+ if (t <= now) {
+
+ /* we have it, but it is expired */
+ id->status = ID_EXPIRED;
+
+ /* We're expired, set an error code
+ for upper layer */
+ ret = NT_STATUS_SYNCHRONIZATION_REQUIRED;
}
} else {
- if (t <= time(NULL)) {
- /* If we've been told to be offline - stay in
- that state... */
- if (lp_winbind_offline_logon() &&
- get_global_winbindd_state_offline())
- {
- DEBUG(10,("idmap_cache_map_sid: winbindd is "
- "globally offline.\n"));
- } else {
- /* We're expired, delete the entry and
- return not mapped */
- tdb_delete(cache->tdb, keybuf);
- ret = NT_STATUS_NONE_MAPPED;
- }
+ if (t <= now) {
+ /* We're expired, delete the NEGATIVE entry and return
+ not mapped */
+ tdb_delete(cache->tdb, keybuf);
+ ret = NT_STATUS_NONE_MAPPED;
} else {
- /* this is not mapped is it was a negative cache hit */
+ /* this is not mapped as it was a negative cache hit */
id->status = ID_UNMAPPED;
ret = NT_STATUS_OK;
}
diff --git a/source/nsswitch/idmap_ldap.c b/source/nsswitch/idmap_ldap.c
index f74372eceab..e6cd5c7f231 100644
--- a/source/nsswitch/idmap_ldap.c
+++ b/source/nsswitch/idmap_ldap.c
@@ -151,6 +151,7 @@ static NTSTATUS verify_idpool(void)
&result);
if (rc != LDAP_SUCCESS) {
+ DEBUG(1, ("Unable to verify the idpool, cannot continue initialization!\n"));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -209,6 +210,11 @@ static NTSTATUS idmap_ldap_alloc_init(const char *params)
gid_t low_gid = 0;
gid_t high_gid = 0;
+ /* Only do init if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
idmap_alloc_ldap = talloc_zero(NULL, struct idmap_ldap_alloc_context);
CHECK_ALLOC_DONE( idmap_alloc_ldap );
@@ -344,6 +350,11 @@ static NTSTATUS idmap_ldap_allocate_id(struct unixid *xid)
const char **attr_list;
const char *type;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
if ( ! idmap_alloc_ldap) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -490,6 +501,11 @@ static NTSTATUS idmap_ldap_get_hwm(struct unixid *xid)
const char **attr_list;
const char *type;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
if ( ! idmap_alloc_ldap) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -580,6 +596,11 @@ static NTSTATUS idmap_ldap_set_hwm(struct unixid *xid)
const char **attr_list;
const char *type;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
if ( ! idmap_alloc_ldap) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -700,14 +721,19 @@ static int idmap_ldap_close_destructor(struct idmap_ldap_context *ctx)
Initialise idmap database.
********************************/
-static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, const char *params)
+static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom)
{
NTSTATUS ret;
struct idmap_ldap_context *ctx = NULL;
char *config_option = NULL;
const char *range = NULL;
const char *tmp = NULL;
-
+
+ /* Only do init if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
ctx = talloc_zero(dom, struct idmap_ldap_context);
if ( ! ctx) {
DEBUG(0, ("Out of memory!\n"));
@@ -732,9 +758,9 @@ static NTSTATUS idmap_ldap_db_init(struct idmap_domain *dom, const char *params)
}
}
- if (params && *params) {
+ if (dom->params && *(dom->params)) {
/* assume location is the only parameter */
- ctx->url = talloc_strdup(ctx, params);
+ ctx->url = talloc_strdup(ctx, dom->params);
} else {
tmp = lp_parm_const_string(-1, config_option, "ldap_url", NULL);
@@ -837,6 +863,19 @@ static NTSTATUS idmap_ldap_unixids_to_sids(struct idmap_domain *dom, struct id_m
int rc;
int i;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
+ /* Initilization my have been deferred because we were offline */
+ if ( ! dom->initialized) {
+ ret = idmap_ldap_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
memctx = talloc_new(ctx);
@@ -991,10 +1030,10 @@ again:
ret = NT_STATUS_OK;
-
- /* mark all unknwon ones as unmapped */
+ /* mark all unknwon/expired ones as unmapped */
for (i = 0; ids[i]; i++) {
- if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
+ if (ids[i]->status != ID_MAPPED)
+ ids[i]->status = ID_UNMAPPED;
}
done:
@@ -1025,6 +1064,7 @@ static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
{
+ LDAPMessage *entry = NULL;
NTSTATUS ret;
TALLOC_CTX *memctx;
struct idmap_ldap_context *ctx;
@@ -1040,6 +1080,19 @@ static NTSTATUS idmap_ldap_sids_to_unixids(struct idmap_domain *dom, struct id_m
int rc;
int i;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
+ /* Initilization my have been deferred because we were offline */
+ if ( ! dom->initialized) {
+ ret = idmap_ldap_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
memctx = talloc_new(ctx);
@@ -1105,7 +1158,6 @@ again:
}
for (i = 0; i < count; i++) {
- LDAPMessage *entry = NULL;
char *sidstr = NULL;
char *tmp = NULL;
enum id_type type;
@@ -1192,9 +1244,10 @@ again:
ret = NT_STATUS_OK;
- /* mark all unknwon ones as unmapped */
+ /* mark all unknwon/expired ones as unmapped */
for (i = 0; ids[i]; i++) {
- if (ids[i]->status == ID_UNKNOWN) ids[i]->status = ID_UNMAPPED;
+ if (ids[i]->status != ID_MAPPED)
+ ids[i]->status = ID_UNMAPPED;
}
done:
@@ -1221,6 +1274,19 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id
char *dn;
int rc = -1;
+ /* Only do query if we are online */
+ if (idmap_is_offline()) {
+ return NT_STATUS_FILE_IS_OFFLINE;
+ }
+
+ /* Initilization my have been deferred because we were offline */
+ if ( ! dom->initialized) {
+ ret = idmap_ldap_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_ldap_context);
switch(map->xid.type) {
@@ -1301,15 +1367,6 @@ done:
}
/**********************************
- remove a mapping.
-**********************************/
-
-static NTSTATUS idmap_ldap_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
-{
- return NT_STATUS_UNSUCCESSFUL;
-}
-
-/**********************************
Close the idmap ldap instance
**********************************/
@@ -1333,8 +1390,6 @@ static struct idmap_methods idmap_ldap_methods = {
.unixids_to_sids = idmap_ldap_unixids_to_sids,
.sids_to_unixids = idmap_ldap_sids_to_unixids,
.set_mapping = idmap_ldap_set_mapping,
- .remove_mapping = idmap_ldap_remove_mapping,
- /* .dump_data = TODO */
.close_fn = idmap_ldap_close
};
diff --git a/source/nsswitch/idmap_nss.c b/source/nsswitch/idmap_nss.c
index 3cd8a8e8eae..e3e425f105f 100644
--- a/source/nsswitch/idmap_nss.c
+++ b/source/nsswitch/idmap_nss.c
@@ -30,8 +30,9 @@
Initialise idmap database.
*****************************/
-static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom)
{
+ dom->initialized = True;
return NT_STATUS_OK;
}
diff --git a/source/nsswitch/idmap_passdb.c b/source/nsswitch/idmap_passdb.c
index a5f8a084b3a..665ead5bb10 100644
--- a/source/nsswitch/idmap_passdb.c
+++ b/source/nsswitch/idmap_passdb.c
@@ -29,8 +29,9 @@
Initialise idmap database.
*****************************/
-static NTSTATUS idmap_pdb_init(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_pdb_init(struct idmap_domain *dom)
{
+ dom->initialized = True;
return NT_STATUS_OK;
}
diff --git a/source/nsswitch/idmap_rid.c b/source/nsswitch/idmap_rid.c
index 298d6fed355..8e016879b8c 100644
--- a/source/nsswitch/idmap_rid.c
+++ b/source/nsswitch/idmap_rid.c
@@ -37,7 +37,7 @@ struct idmap_rid_context {
we support multiple domains in the new idmap
*****************************************************************************/
-static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_rid_initialize(struct idmap_domain *dom)
{
NTSTATUS ret;
struct idmap_rid_context *ctx;
@@ -86,9 +86,6 @@ failed:
static NTSTATUS idmap_rid_id_to_sid(TALLOC_CTX *memctx, struct idmap_rid_context *ctx, struct id_map *map)
{
- const char *domname, *name;
- enum lsa_SidType sid_type;
- BOOL ret;
struct winbindd_domain *domain;
/* apply filters before checking */
@@ -104,45 +101,9 @@ static NTSTATUS idmap_rid_id_to_sid(TALLOC_CTX *memctx, struct idmap_rid_context
sid_compose(map->sid, &domain->sid, map->xid.id - ctx->low_id + ctx->base_rid);
- /* by default calls to winbindd are disabled
- the following call will not recurse so this is safe */
- winbind_on();
- ret = winbind_lookup_sid(memctx, map->sid, &domname, &name, &sid_type);
- winbind_off();
-
- if (ret) {
- switch (sid_type) {
- case SID_NAME_USER:
- if (map->xid.type != ID_TYPE_UID) {
- /* wrong type */
- map->status = ID_UNMAPPED;
- DEBUG(5, ("Resulting SID is of wrong ID type\n"));
- return NT_STATUS_NONE_MAPPED;
- }
- break;
- case SID_NAME_DOM_GRP:
- case SID_NAME_ALIAS:
- case SID_NAME_WKN_GRP:
- if (map->xid.type != ID_TYPE_GID) {
- /* wrong type */
- map->status = ID_UNMAPPED;
- DEBUG(5, ("Resulting SID is of wrong ID type\n"));
- return NT_STATUS_NONE_MAPPED;
- }
- break;
- default:
- /* invalid sid?? */
- map->status = ID_UNKNOWN;
- DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid)));
- return NT_STATUS_NONE_MAPPED;
- }
- } else {
- /* TODO: how do we known if the lookup was negative
- * or something just failed? */
- map->status = ID_UNMAPPED;
- DEBUG(2, ("Failed: to resolve SID\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
+ /* We **really** should have some way of validating
+ the SID exists and is the correct type here. But
+ that is a deficiency in the idmap_rid design. */
map->status = ID_MAPPED;
@@ -155,46 +116,13 @@ static NTSTATUS idmap_rid_id_to_sid(TALLOC_CTX *memctx, struct idmap_rid_context
static NTSTATUS idmap_rid_sid_to_id(TALLOC_CTX *memctx, struct idmap_rid_context *ctx, struct id_map *map)
{
- const char *domname, *name;
- enum lsa_SidType sid_type;
uint32_t rid;
- BOOL ret;
sid_peek_rid(map->sid, &rid);
map->xid.id = rid - ctx->base_rid + ctx->low_id;
- /* by default calls to winbindd are disabled
- the following call will not recurse so this is safe */
- winbind_on();
- /* check if this is a valid SID and set the type */
- ret = winbind_lookup_sid(memctx, map->sid, &domname, &name, &sid_type);
- winbind_off();
-
- if (ret) {
- switch (sid_type) {
- case SID_NAME_USER:
- map->xid.type = ID_TYPE_UID;
- break;
- case SID_NAME_DOM_GRP:
- case SID_NAME_ALIAS:
- case SID_NAME_WKN_GRP:
- map->xid.type = ID_TYPE_GID;
- break;
- default:
- /* invalid sid, let's just leave it unmapped */
- DEBUG(10, ("SID %s is UNKNOWN, skip mapping\n", sid_string_static(map->sid)));
- map->status = ID_UNKNOWN;
- return NT_STATUS_NONE_MAPPED;
- }
- } else {
- /* TODO: how do we known if the lookup was negative
- * or something just failed? */
- map->status = ID_UNMAPPED;
- DEBUG(2, ("Failed: to resolve SID\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
/* apply filters before returning result */
+
if ((map->xid.id < ctx->low_id) || (map->xid.id > ctx->high_id)) {
DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
map->xid.id, ctx->low_id, ctx->high_id));
@@ -202,6 +130,10 @@ static NTSTATUS idmap_rid_sid_to_id(TALLOC_CTX *memctx, struct idmap_rid_context
return NT_STATUS_NONE_MAPPED;
}
+ /* We **really** should have some way of validating
+ the SID exists and is the correct type here. But
+ that is a deficiency in the idmap_rid design. */
+
map->status = ID_MAPPED;
return NT_STATUS_OK;
diff --git a/source/nsswitch/idmap_tdb.c b/source/nsswitch/idmap_tdb.c
index c21c066fea1..8ce88e015d4 100644
--- a/source/nsswitch/idmap_tdb.c
+++ b/source/nsswitch/idmap_tdb.c
@@ -611,7 +611,7 @@ struct idmap_tdb_context {
Initialise idmap database.
*****************************/
-static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *compat_params)
+static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom)
{
NTSTATUS ret;
struct idmap_tdb_context *ctx;
@@ -645,6 +645,7 @@ static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *compat_p
}
dom->private_data = ctx;
+ dom->initialized = True;
talloc_free(config_option);
return NT_STATUS_OK;
@@ -799,6 +800,14 @@ static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_ma
NTSTATUS ret;
int i;
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
for (i = 0; ids[i]; i++) {
@@ -837,6 +846,14 @@ static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_ma
NTSTATUS ret;
int i;
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
for (i = 0; ids[i]; i++) {
@@ -875,6 +892,14 @@ static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom, const struct id_
NTSTATUS ret;
TDB_DATA ksid, kid, data;
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
if (!map || !map->sid) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -978,6 +1003,14 @@ static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom, const struct
NTSTATUS ret;
TDB_DATA ksid, kid, data;
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
if (!map || !map->sid) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -1155,6 +1188,14 @@ static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **ma
struct dump_data *data;
NTSTATUS ret = NT_STATUS_OK;
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
data = talloc_zero(ctx, struct dump_data);
diff --git a/source/nsswitch/idmap_util.c b/source/nsswitch/idmap_util.c
index 540dafaa734..40a5fb854be 100644
--- a/source/nsswitch/idmap_util.c
+++ b/source/nsswitch/idmap_util.c
@@ -105,18 +105,24 @@ NTSTATUS idmap_sid_to_uid(DOM_SID *sid, uid_t *uid)
DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid)));
map.sid = sid;
+ map.xid.type = ID_TYPE_UID;
maps[0] = &map;
maps[1] = NULL;
ret = idmap_sids_to_unixids(maps);
if ( ! NT_STATUS_IS_OK(ret)) {
- DEBUG(10, ("error mapping sid [%s] to uid\n", sid_string_static(sid)));
+ DEBUG(10, ("error mapping sid [%s] to uid\n",
+ sid_string_static(sid)));
return ret;
}
if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_UID)) {
- DEBUG(10, ("sid [%s] not mapped to an uid [%u,%u,%u]\n", sid_string_static(sid), map.status, map.xid.type, map.xid.id));
+ DEBUG(10, ("sid [%s] not mapped to an uid [%u,%u,%u]\n",
+ sid_string_static(sid),
+ map.status,
+ map.xid.type,
+ map.xid.id));
return NT_STATUS_NONE_MAPPED;
}
@@ -139,18 +145,24 @@ NTSTATUS idmap_sid_to_gid(DOM_SID *sid, gid_t *gid)
DEBUG(10,("idmap_sid_to_gid: sid = [%s]\n", sid_string_static(sid)));
map.sid = sid;
+ map.xid.type = ID_TYPE_GID;
maps[0] = &map;
maps[1] = NULL;
ret = idmap_sids_to_unixids(maps);
if ( ! NT_STATUS_IS_OK(ret)) {
- DEBUG(10, ("error mapping sid [%s] to gid\n", sid_string_static(sid)));
+ DEBUG(10, ("error mapping sid [%s] to gid\n",
+ sid_string_static(sid)));
return ret;
}
if ((map.status != ID_MAPPED) || (map.xid.type != ID_TYPE_GID)) {
- DEBUG(10, ("sid [%s] not mapped to an gid [%u,%u,%u]\n", sid_string_static(sid), map.status, map.xid.type, map.xid.id));
+ DEBUG(10, ("sid [%s] not mapped to an gid [%u,%u,%u]\n",
+ sid_string_static(sid),
+ map.status,
+ map.xid.type,
+ map.xid.id));
return NT_STATUS_NONE_MAPPED;
}
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 9d52dc89d0a..ec6361e52be 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -921,9 +921,9 @@ static void _pam_warn_logon_type(pam_handle_t *pamh, int ctrl, const char *usern
} else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) {
_make_remark(pamh, ctrl, PAM_ERROR_MSG,
- "Logging on using cached account. Network resources can be unavailable");
+ "Domain Controller unreachable, using cached credentials instead. Network resources may be unavailable");
_pam_log_debug(pamh, ctrl, LOG_DEBUG,
- "User %s logged on using cached account\n", username);
+ "User %s logged on using cached credentials\n", username);
}
}
@@ -1517,7 +1517,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
dictionary *d = NULL;
char *username_ret = NULL;
char *new_authtok_required = NULL;
- const char *real_username = NULL;
+ char *real_username = NULL;
/* parse arguments */
int ctrl = _pam_parse(pamh, flags, argc, argv, &d);
diff --git a/source/nsswitch/winbind_nss_config.h b/source/nsswitch/winbind_nss_config.h
index d595631362b..c36d4e72325 100644
--- a/source/nsswitch/winbind_nss_config.h
+++ b/source/nsswitch/winbind_nss_config.h
@@ -103,18 +103,6 @@ typedef int BOOL;
#endif /* don't lie. If we don't have it, then don't use it */
#endif
-
-
-/* zero a structure */
-#ifndef ZERO_STRUCT
-#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
-#endif
-
-/* zero a structure given a pointer to the structure */
-#ifndef ZERO_STRUCTP
-#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }
-#endif
-
/* Some systems (SCO) treat UNIX domain sockets as FIFOs */
#ifndef S_IFSOCK
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index 3b518fe3206..59bb04e7d2a 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -248,7 +248,9 @@ static struct winbindd_dispatch_table {
{ WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
{ WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
{ WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
+#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */
{ WINBINDD_SIDS_TO_XIDS, winbindd_sids_to_unixids, "SIDS_TO_XIDS" },
+#endif /* end DISABLED */
{ WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" },
{ WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" },
{ WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" },
@@ -1062,6 +1064,11 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ /* Initialize cache (ensure version is correct). */
+ if (!initialize_winbindd_cache()) {
+ exit(1);
+ }
+
/* React on 'smbcontrol winbindd reload-config' in the same way
as to SIGHUP signal */
message_register(MSG_SMB_CONF_UPDATED, msg_reload_services, NULL);
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index ff5f93bfedd..a9ade4459e8 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -29,12 +29,53 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+#define WINBINDD_CACHE_VERSION 1
+#define WINBINDD_CACHE_VERSION_KEYSTR "WINBINDD_CACHE_VERSION"
+
extern struct winbindd_methods reconnect_methods;
extern BOOL opt_nocache;
#ifdef HAVE_ADS
extern struct winbindd_methods ads_methods;
#endif
+/*
+ * JRA. KEEP THIS LIST UP TO DATE IF YOU ADD CACHE ENTRIES.
+ * Here are the list of entry types that are *not* stored
+ * as form struct cache_entry in the cache.
+ */
+
+static const char *non_centry_keys[] = {
+ "SEQNUM/",
+ "DR/",
+ "DE/",
+ "WINBINDD_OFFLINE",
+ WINBINDD_CACHE_VERSION_KEYSTR,
+ NULL
+};
+
+/************************************************************************
+ Is this key a non-centry type ?
+************************************************************************/
+
+static BOOL is_non_centry_key(TDB_DATA kbuf)
+{
+ int i;
+
+ if (kbuf.dptr == NULL || kbuf.dsize == 0) {
+ return False;
+ }
+ for (i = 0; non_centry_keys[i] != NULL; i++) {
+ size_t namelen = strlen(non_centry_keys[i]);
+ if (kbuf.dsize < namelen) {
+ continue;
+ }
+ if (strncmp(non_centry_keys[i], (const char *)kbuf.dptr, namelen) == 0) {
+ return True;
+ }
+ }
+ return False;
+}
+
/* Global online/offline state - False when online. winbindd starts up online
and sets this to true if the first query fails and there's an entry in
the cache tdb telling us to stay offline. */
@@ -227,19 +268,11 @@ static NTTIME centry_nttime(struct cache_entry *centry)
}
/*
- pull a time_t from a cache entry
+ pull a time_t from a cache entry. time_t stored portably as a 64-bit time.
*/
static time_t centry_time(struct cache_entry *centry)
{
- time_t ret;
- if (centry->len - centry->ofs < sizeof(time_t)) {
- DEBUG(0,("centry corruption? needed %u bytes, have %u\n",
- (unsigned int)sizeof(time_t), (unsigned int)(centry->len - centry->ofs)));
- smb_panic("centry_time");
- }
- ret = IVAL(centry->data, centry->ofs); /* FIXME: correct ? */
- centry->ofs += sizeof(time_t);
- return ret;
+ return (time_t)centry_nttime(centry);
}
/* pull a string from a cache entry, using the supplied
@@ -713,13 +746,13 @@ static void centry_put_nttime(struct cache_entry *centry, NTTIME nt)
}
/*
- push a time_t into a centry
+ push a time_t into a centry - use a 64 bit size.
+ NTTIME here is being used as a convenient 64-bit size.
*/
static void centry_put_time(struct cache_entry *centry, time_t t)
{
- centry_expand(centry, sizeof(time_t));
- SIVAL(centry->data, centry->ofs, t); /* FIXME: is this correct ?? */
- centry->ofs += sizeof(time_t);
+ NTTIME nt = (NTTIME)t;
+ centry_put_nttime(centry, nt);
}
/*
@@ -2119,7 +2152,7 @@ void wcache_invalidate_cache(void)
}
}
-BOOL init_wcache(void)
+static BOOL init_wcache(void)
{
if (wcache == NULL) {
wcache = SMB_XMALLOC_P(struct winbind_cache);
@@ -2143,6 +2176,61 @@ BOOL init_wcache(void)
return True;
}
+/************************************************************************
+ This is called by the parent to initialize the cache file.
+ We don't need sophisticated locking here as we know we're the
+ only opener.
+************************************************************************/
+
+BOOL initialize_winbindd_cache(void)
+{
+ BOOL cache_bad = True;
+ uint32 vers;
+
+ if (!init_wcache()) {
+ DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n"));
+ return False;
+ }
+
+ /* Check version number. */
+ if (tdb_fetch_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers) &&
+ vers == WINBINDD_CACHE_VERSION) {
+ cache_bad = False;
+ }
+
+ if (cache_bad) {
+ DEBUG(0,("initialize_winbindd_cache: clearing cache "
+ "and re-creating with version number %d\n",
+ WINBINDD_CACHE_VERSION ));
+
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
+
+ if (unlink(lock_path("winbindd_cache.tdb")) == -1) {
+ DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ",
+ lock_path("winbindd_cache.tdb"),
+ strerror(errno) ));
+ return False;
+ }
+ if (!init_wcache()) {
+ DEBUG(0,("initialize_winbindd_cache: re-initialization "
+ "init_wcache failed.\n"));
+ return False;
+ }
+
+ /* Write the version. */
+ if (!tdb_store_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION)) {
+ DEBUG(0,("initialize_winbindd_cache: version number store failed %s\n",
+ tdb_errorstr(wcache->tdb) ));
+ return False;
+ }
+ }
+
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
+ return True;
+}
+
void cache_store_response(pid_t pid, struct winbindd_response *response)
{
fstring key_str;
@@ -2340,11 +2428,21 @@ void cache_name2sid(struct winbindd_domain *domain,
}
/* delete all centries that don't have NT_STATUS_OK set */
+/*
+ * The original idea that this cache only contains centries has
+ * been blurred - now other stuff gets put in here. Ensure we
+ * ignore these things on cleanup.
+ */
+
static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
TDB_DATA dbuf, void *state)
{
struct cache_entry *centry;
+ if (is_non_centry_key(kbuf)) {
+ return 0;
+ }
+
centry = wcache_fetch_raw(kbuf.dptr);
if (!centry) {
return 0;
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index 26debd26745..8d475e6c9f9 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -364,7 +364,9 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
{ WINBINDD_CHECK_MACHACC, winbindd_dual_check_machine_acct, "CHECK_MACHACC" },
{ WINBINDD_DUAL_SID2UID, winbindd_dual_sid2uid, "DUAL_SID2UID" },
{ WINBINDD_DUAL_SID2GID, winbindd_dual_sid2gid, "DUAL_SID2GID" },
+#if 0 /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */
{ WINBINDD_DUAL_SIDS2XIDS, winbindd_dual_sids2xids, "DUAL_SIDS2XIDS" },
+#endif /* end DISABLED */
{ WINBINDD_DUAL_UID2SID, winbindd_dual_uid2sid, "DUAL_UID2SID" },
{ WINBINDD_DUAL_GID2SID, winbindd_dual_gid2sid, "DUAL_GID2SID" },
{ WINBINDD_DUAL_UID2NAME, winbindd_dual_uid2name, "DUAL_UID2NAME" },
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 13b2cd05550..a40d35c5820 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -183,6 +183,40 @@ static void sid2uid_recv(void *private_data, BOOL success, uid_t uid)
request_ok(state);
}
+static void sid2uid_lookupsid_recv( void *private_data, BOOL success,
+ const char *domain_name,
+ const char *name,
+ enum lsa_SidType type)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private_data, struct winbindd_cli_state);
+ DOM_SID sid;
+
+ if (!success) {
+ DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ if ( (type!=SID_NAME_USER) || (type!=SID_NAME_COMPUTER) ) {
+ DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ if (!string_to_sid(&sid, state->request.data.sid)) {
+ DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ /* always use the async interface (may block) */
+ winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
+}
+
void winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
@@ -200,8 +234,11 @@ void winbindd_sid_to_uid(struct winbindd_cli_state *state)
return;
}
- /* always use the async interface (may block) */
- winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
+ /* Validate the SID as a user. Hopefully this will hit cache.
+ Needed to prevent DoS by exhausting the uid allocation
+ range from random SIDs. */
+
+ winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state );
}
/* Convert a sid to a gid. We assume we only have one rid attached to the
@@ -223,6 +260,43 @@ static void sid2gid_recv(void *private_data, BOOL success, gid_t gid)
request_ok(state);
}
+static void sid2gid_lookupsid_recv( void *private_data, BOOL success,
+ const char *domain_name,
+ const char *name,
+ enum lsa_SidType type)
+{
+ struct winbindd_cli_state *state =
+ talloc_get_type_abort(private_data, struct winbindd_cli_state);
+ DOM_SID sid;
+
+ if (!success) {
+ DEBUG(5, ("sid2gid_lookupsid_recv: Could not convert get sid type for %s\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ if ( (type!=SID_NAME_DOM_GRP) ||
+ (type!=SID_NAME_ALIAS) ||
+ (type!=SID_NAME_WKN_GRP) )
+ {
+ DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ if (!string_to_sid(&sid, state->request.data.sid)) {
+ DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n",
+ state->request.data.sid));
+ request_error(state);
+ return;
+ }
+
+ /* always use the async interface (may block) */
+ winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
+}
+
void winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
@@ -240,8 +314,11 @@ void winbindd_sid_to_gid(struct winbindd_cli_state *state)
return;
}
- /* always use the async interface (may block) */
- winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
+ /* Validate the SID as a group. Hopefully this will hit cache.
+ Needed to prevent DoS by exhausting the uid allocation
+ range from random SIDs. */
+
+ winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state );
}
static void sids2xids_recv(void *private_data, BOOL success, void *data, int len)
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index 72c85a9c6a4..abfd3f6fccf 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -389,9 +389,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
request->cmd = WINBINDD_GETDCNAME;
fstrcpy(request->domain_name, domain->name);
- /* save online flag */
request_domain = find_our_domain();
- request_domain->online = domain->online;
async_domain_request(mem_ctx, request_domain, request, response,
init_child_getdc_recv, state);
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index a9913d102ff..8d30b65d905 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -2229,7 +2229,7 @@ static int lp_int(const char *s)
return (-1);
}
- return atoi(s);
+ return (int)strtol(s, NULL, 0);
}
/*******************************************************************
@@ -2243,7 +2243,7 @@ static unsigned long lp_ulong(const char *s)
return (0);
}
- return strtoul(s, NULL, 10);
+ return strtoul(s, NULL, 0);
}
/*******************************************************************
@@ -5293,15 +5293,22 @@ struct share_params *snum2params_static(int snum)
A useful volume label function.
********************************************************************/
-char *volume_label(int snum)
+const char *volume_label(int snum)
{
- char *ret = lp_volume(snum);
- if (!*ret)
- return lp_servicename(snum);
- return (ret);
+ char *ret;
+ const char *label = lp_volume(snum);
+ if (!*label) {
+ label = lp_servicename(snum);
+ }
+
+ /* This returns a 33 byte guarenteed null terminated string. */
+ ret = talloc_strndup(main_loop_talloc_get(), label, 32);
+ if (!ret) {
+ return "";
+ }
+ return ret;
}
-
/*******************************************************************
Set the server type we will announce as via nmbd.
********************************************************************/
diff --git a/source/profile/profile.c b/source/profile/profile.c
index 69c240061e1..b7a2ea23beb 100644
--- a/source/profile/profile.c
+++ b/source/profile/profile.c
@@ -42,13 +42,10 @@ BOOL do_profile_flag = False;
BOOL do_profile_times = False;
/****************************************************************************
-receive a set profile level message
+Set a profiling level.
****************************************************************************/
-void profile_message(int msg_type, struct process_id src, void *buf, size_t len, void *private_data)
+void set_profile_level(int level, struct process_id src)
{
- int level;
-
- memcpy(&level, buf, sizeof(int));
#ifdef WITH_PROFILE
switch (level) {
case 0: /* turn off profiling */
@@ -94,6 +91,17 @@ void profile_message(int msg_type, struct process_id src, void *buf, size_t len,
}
/****************************************************************************
+receive a set profile level message
+****************************************************************************/
+void profile_message(int msg_type, struct process_id src, void *buf, size_t len, void *private_data)
+{
+ int level;
+
+ memcpy(&level, buf, sizeof(int));
+ set_profile_level(level, src);
+}
+
+/****************************************************************************
receive a request profile level message
****************************************************************************/
void reqprofile_message(int msg_type, struct process_id src,
diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c
index 54bbe3adf6c..540db5b6a85 100644
--- a/source/rpc_parse/parse_prs.c
+++ b/source/rpc_parse/parse_prs.c
@@ -1456,31 +1456,31 @@ BOOL prs_uint32_post(const char *name, prs_struct *ps, int depth, uint32 *data32
/* useful function to store a structure in rpc wire format */
int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps)
{
- TDB_DATA kbuf, dbuf;
- kbuf.dptr = keystr;
- kbuf.dsize = strlen(keystr)+1;
- dbuf.dptr = ps->data_p;
- dbuf.dsize = prs_offset(ps);
- return tdb_trans_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ TDB_DATA kbuf, dbuf;
+ kbuf.dptr = keystr;
+ kbuf.dsize = strlen(keystr)+1;
+ dbuf.dptr = ps->data_p;
+ dbuf.dsize = prs_offset(ps);
+ return tdb_trans_store(tdb, kbuf, dbuf, TDB_REPLACE);
}
/* useful function to fetch a structure into rpc wire format */
int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *mem_ctx)
{
- TDB_DATA kbuf, dbuf;
- kbuf.dptr = keystr;
- kbuf.dsize = strlen(keystr)+1;
+ TDB_DATA kbuf, dbuf;
+ kbuf.dptr = keystr;
+ kbuf.dsize = strlen(keystr)+1;
- prs_init(ps, 0, mem_ctx, UNMARSHALL);
+ prs_init(ps, 0, mem_ctx, UNMARSHALL);
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- return -1;
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr)
+ return -1;
- prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True);
+ prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True);
- return 0;
-}
+ return 0;
+}
/*******************************************************************
hash a stream.
diff --git a/source/smbd/connection.c b/source/smbd/connection.c
index 0442a9441ad..325d4a58c64 100644
--- a/source/smbd/connection.c
+++ b/source/smbd/connection.c
@@ -108,13 +108,13 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u
if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) {
DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
- procid_str_static(&crec.pid), crec.cnum, crec.name));
+ procid_str_static(&crec.pid), crec.cnum, crec.servicename));
if (tdb_delete(the_tdb, kbuf) != 0)
DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) ));
return 0;
}
- if (strequal(crec.name, cs->name))
+ if (strequal(crec.servicename, cs->name))
cs->curr_connections++;
return 0;
@@ -191,8 +191,8 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti
if (conn) {
crec.uid = conn->uid;
crec.gid = conn->gid;
- safe_strcpy(crec.name,
- lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
+ safe_strcpy(crec.servicename,
+ lp_servicename(SNUM(conn)),sizeof(crec.servicename)-1);
}
crec.start = time(NULL);
crec.bcast_msg_flags = msg_flags;
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 836801ba82c..8dec71958ea 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -1153,8 +1153,8 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
char outbuf_saved[smb_wct];
int outsize = smb_len(outbuf) + 4;
- /* maybe its not chained */
- if (smb_com2 == 0xFF) {
+ /* Maybe its not chained, or it's an error packet. */
+ if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
SCVAL(outbuf,smb_vwv0,0xFF);
return outsize;
}
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index ddfcb8e0f86..feb28e2c743 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -662,7 +662,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
BOOL retval;
DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
- unbecome();
+ unbecome_root();
return retval;
}
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 98d72ba742b..bad3c6f0a80 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -468,13 +468,22 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
if (global_encrypted_passwords_negotiated) {
password = data_blob(smb_buf(inbuf),passlen);
+ if (lp_security() == SEC_SHARE) {
+ /*
+ * Security = share always has a pad byte
+ * after the password.
+ */
+ p = smb_buf(inbuf) + passlen + 1;
+ } else {
+ p = smb_buf(inbuf) + passlen;
+ }
} else {
password = data_blob(smb_buf(inbuf),passlen+1);
/* Ensure correct termination */
- password.data[passlen]=0;
+ password.data[passlen]=0;
+ p = smb_buf(inbuf) + passlen + 1;
}
- p = smb_buf(inbuf) + passlen;
p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
/*
@@ -2705,8 +2714,10 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
- if (nread != -1)
+ /* Only call chain_reply if not an error. */
+ if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
nread = chain_reply(inbuf,outbuf,length,bufsize);
+ }
END_PROFILE(SMBreadX);
return nread;
diff --git a/source/smbd/server.c b/source/smbd/server.c
index ab32d656d38..99fe2348b11 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -833,6 +833,7 @@ extern void build_options(BOOL screen);
static BOOL no_process_group = False;
static BOOL log_stdout = False;
static char *ports = NULL;
+ static char *profile_level = NULL;
int opt;
poptContext pc;
@@ -845,6 +846,7 @@ extern void build_options(BOOL screen);
{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
{"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" },
{"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"},
+ {"profiling-level", 'P', POPT_ARG_STRING, &profile_level, 0, "Set profiling level","PROFILE_LEVEL"},
POPT_COMMON_SAMBA
POPT_COMMON_DYNCONFIG
POPT_TABLEEND
@@ -967,6 +969,14 @@ extern void build_options(BOOL screen);
DEBUG(0,("ERROR: failed to setup profiling\n"));
return -1;
}
+ if (profile_level != NULL) {
+ int pl = atoi(profile_level);
+ struct process_id src;
+
+ DEBUG(1, ("setting profiling level: %s\n",profile_level));
+ src.pid = getpid();
+ set_profile_level(pl, src);
+ }
#endif
DEBUG(3,( "loaded services\n"));
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 5efad04b550..2604b21f55f 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -2232,7 +2232,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
uint16 info_level;
int data_len, len;
SMB_STRUCT_STAT st;
- char *vname = volume_label(SNUM(conn));
+ const char *vname = volume_label(SNUM(conn));
int snum = SNUM(conn);
char *fstype = lp_fstype(SNUM(conn));
int quota_flag = 0;
@@ -2353,9 +2353,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
(str_checksum(get_local_machine_name())<<16));
+ /* Max label len is 32 characters. */
len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
SIVAL(pdata,12,len);
data_len = 18+len;
+
DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
(int)strlen(vname),vname, lp_servicename(snum)));
break;
diff --git a/source/tdb/common/transaction.c b/source/tdb/common/transaction.c
index 24aa5c32234..8bda651f1e4 100644
--- a/source/tdb/common/transaction.c
+++ b/source/tdb/common/transaction.c
@@ -526,6 +526,8 @@ int tdb_transaction_cancel(struct tdb_context *tdb)
F_UNLCK,F_SETLKW, 0, 1);
}
tdb->num_locks = 0;
+ tdb->num_lockrecs = 0;
+ SAFE_FREE(tdb->lockrecs);
}
/* restore the normal io methods */
diff --git a/source/utils/net_status.c b/source/utils/net_status.c
index bfc30eac78a..354111f6092 100644
--- a/source/utils/net_status.c
+++ b/source/utils/net_status.c
@@ -102,7 +102,7 @@ static int show_share(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
}
d_printf("%-10.10s %s %-12s %s",
- crec.name,procid_str_static(&crec.pid),
+ crec.servicename,procid_str_static(&crec.pid),
crec.machine,
time_to_asc(crec.start));
@@ -168,7 +168,7 @@ static int show_share_parseable(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
}
d_printf("%s\\%s\\%s\\%s\\%s\\%s\\%s",
- crec.name,procid_str_static(&crec.pid),
+ crec.servicename,procid_str_static(&crec.pid),
guest ? "" : uidtoname(ids->entries[i].uid),
guest ? "" : gidtoname(ids->entries[i].gid),
crec.machine,
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c
index da9ac8d279d..74606624412 100644
--- a/source/utils/smbpasswd.c
+++ b/source/utils/smbpasswd.c
@@ -190,7 +190,7 @@ static int process_options(int argc, char **argv, int local_flags)
if (!lp_load(configfile,True,False,False,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n",
- dyn_CONFIGFILE);
+ configfile);
exit(1);
}
diff --git a/source/utils/status.c b/source/utils/status.c
index deba6a9523b..df742f73e79 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -205,7 +205,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
}
d_printf("%-10s %s %-12s %s",
- crec.name,procid_str_static(&crec.pid),
+ crec.servicename,procid_str_static(&crec.pid),
crec.machine,
time_to_asc(crec.start));
diff --git a/source/web/statuspage.c b/source/web/statuspage.c
index a88e5debd0e..e4d726c4fd2 100644
--- a/source/web/statuspage.c
+++ b/source/web/statuspage.c
@@ -230,7 +230,7 @@ static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st
return 0;
printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
- crec.name,uidtoname(crec.uid),
+ crec.servicename,uidtoname(crec.uid),
gidtoname(crec.gid),procid_str_static(&crec.pid),
crec.machine,
tstring(crec.start));