From e58110dfc02d6f90246d9c5ed1a6d207c0ce5bd2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 21 Apr 2007 21:51:01 +0000 Subject: r22434: sync from the 3.0.25 tree for rc2 --- packaging/RHEL/samba.spec.tmpl | 3 +- source/Makefile.in | 9 +- source/auth/auth_util.c | 42 +-- source/client/client.c | 4 +- source/configure.in | 26 ++ source/include/idmap.h | 10 +- source/include/includes.h | 7 +- source/include/smb.h | 8 +- source/include/smb_macros.h | 24 -- source/include/smb_share_modes.h | 8 +- source/lib/fault.c | 7 + source/lib/messages.c | 2 +- source/lib/replace/Makefile.in | 2 +- source/lib/replace/README | 19 +- source/lib/replace/libreplace.m4 | 16 +- source/lib/replace/libreplace_macros.m4 | 9 + source/lib/replace/replace.c | 53 ++-- source/lib/replace/replace.h | 83 +++++- source/lib/replace/samba.m4 | 8 + source/lib/replace/system/wait.h | 4 + source/lib/replace/test/os2_delete.c | 2 + source/lib/replace/test/testsuite.c | 481 ++++++++++++++++++++++++++++++-- source/lib/talloc/talloc.h | 10 +- source/lib/util_sock.c | 3 + source/libads/kerberos.c | 6 +- source/libsmb/clientgen.c | 20 ++ source/libsmb/clikrb5.c | 29 +- source/libsmb/namequery_dc.c | 5 + source/libsmb/smb_share_modes.c | 5 + source/modules/vfs_gpfs.c | 3 +- source/modules/vfs_readahead.c | 4 +- source/nmbd/nmbd_subnetdb.c | 7 + source/nsswitch/idmap.c | 367 +++++++++++++----------- source/nsswitch/idmap_ad.c | 99 +++++-- source/nsswitch/idmap_cache.c | 120 ++++---- source/nsswitch/idmap_ldap.c | 97 +++++-- source/nsswitch/idmap_nss.c | 3 +- source/nsswitch/idmap_passdb.c | 3 +- source/nsswitch/idmap_rid.c | 86 +----- source/nsswitch/idmap_tdb.c | 43 ++- source/nsswitch/idmap_util.c | 20 +- source/nsswitch/pam_winbind.c | 6 +- source/nsswitch/winbind_nss_config.h | 12 - source/nsswitch/winbindd.c | 7 + source/nsswitch/winbindd_cache.c | 128 ++++++++- source/nsswitch/winbindd_dual.c | 2 + source/nsswitch/winbindd_sid.c | 85 +++++- source/nsswitch/winbindd_util.c | 2 - source/param/loadparm.c | 23 +- source/profile/profile.c | 18 +- source/rpc_parse/parse_prs.c | 32 +-- source/smbd/connection.c | 8 +- source/smbd/process.c | 4 +- source/smbd/quotas.c | 2 +- source/smbd/reply.c | 17 +- source/smbd/server.c | 10 + source/smbd/trans2.c | 4 +- source/tdb/common/transaction.c | 2 + source/utils/net_status.c | 4 +- source/utils/smbpasswd.c | 2 +- source/utils/status.c | 2 +- source/web/statuspage.c | 2 +- 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; iptok->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_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 ], @@ -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 ]) AC_HAVE_DECL(setresgid, [#include ]) @@ -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 ]) +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 #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 @@ -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 #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) { @@ -1300,15 +1366,6 @@ done: return ret; } -/********************************** - remove a mapping. -**********************************/ - -static NTSTATUS idmap_ldap_remove_mapping(struct idmap_domain *dom, const struct id_map *map) -{ - return NT_STATUS_UNSUCCESSFUL; -} - /********************************** Close the idmap ldap instance **********************************/ @@ -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] = ↦ 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] = ↦ 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 */ @@ -93,6 +90,17 @@ void profile_message(int msg_type, struct process_id src, void *buf, size_t len, #endif /* WITH_PROFILE */ } +/**************************************************************************** +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 ****************************************************************************/ 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("%s%s%s%s%s%s\n", - crec.name,uidtoname(crec.uid), + crec.servicename,uidtoname(crec.uid), gidtoname(crec.gid),procid_str_static(&crec.pid), crec.machine, tstring(crec.start)); -- cgit