From: scantor Date: Thu, 24 May 2012 16:07:50 +0000 (+0000) Subject: https://issues.shibboleth.net/jira/browse/SSPCPP-319 X-Git-Tag: 2.5.0~81 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fsp.git;a=commitdiff_plain;h=024ea649b2d1d8b0d0a658996ed2c91e30126409 https://issues.shibboleth.net/jira/browse/SSPCPP-319 git-svn-id: https://svn.shibboleth.net/cpp-sp/branches/REL_2@3677 cb58f699-b61c-0410-a6fe-9272a202ed29 --- diff --git a/Shibboleth.sln b/Shibboleth.sln index d36fe87..e6a53a0 100644 --- a/Shibboleth.sln +++ b/Shibboleth.sln @@ -134,6 +134,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugins", "plugins\plugins. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_shib_24", "apache\mod_shib24.vcxproj", "{B44C0852-83B8-4FB2-A86E-097C9C8256D1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugins-lite", "plugins\plugins-lite.vcxproj", "{A2140D6E-C2C6-4329-84E3-2F530CEBE442}" + ProjectSection(ProjectDependencies) = postProject + {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} = {81F0F7A6-DC36-46EF-957F-F9E81D4403F7} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -276,6 +281,14 @@ Global {B44C0852-83B8-4FB2-A86E-097C9C8256D1}.Release|Win32.Build.0 = Release|Win32 {B44C0852-83B8-4FB2-A86E-097C9C8256D1}.Release|x64.ActiveCfg = Release|x64 {B44C0852-83B8-4FB2-A86E-097C9C8256D1}.Release|x64.Build.0 = Release|x64 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Debug|Win32.Build.0 = Debug|Win32 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Debug|x64.ActiveCfg = Debug|x64 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Debug|x64.Build.0 = Debug|x64 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Release|Win32.ActiveCfg = Release|Win32 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Release|Win32.Build.0 = Release|Win32 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Release|x64.ActiveCfg = Release|x64 + {A2140D6E-C2C6-4329-84E3-2F530CEBE442}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -293,6 +306,7 @@ Global {26D4FABF-ACDE-4947-9C4A-7AE1B50CD83B} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C} {666A63A7-983F-4C19-8411-207F24305198} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C} {A2140D6E-C2C6-4329-84E3-2F530CEBE445} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C} + {A2140D6E-C2C6-4329-84E3-2F530CEBE442} = {96AE4FC9-45EF-4C18-9F3B-EDA439E26E4C} {F13141B6-6C87-40BB-8D4E-5CC56EBB4C5A} = {FED80230-119E-4B2F-9F53-D2660A5F022B} {F13141B6-6C87-40BB-8D4E-5CC56EBB4C59} = {FED80230-119E-4B2F-9F53-D2660A5F022B} {8CF7DDFA-EAA0-416E-853E-3DCB210C4AE0} = {8E1AF2CF-24E1-4983-8681-394D89DF9AD2} diff --git a/configure.ac b/configure.ac index 0eeb4a9..9c2eda1 100644 --- a/configure.ac +++ b/configure.ac @@ -77,7 +77,7 @@ AC_FUNC_STRFTIME AC_FUNC_STRERROR_R AC_CHECK_HEADERS([sys/utsname.h grp.h pwd.h]) AC_CHECK_HEADERS([sys/socket.h], [AC_DEFINE([SHIBSP_HAVE_SYS_SOCKET_H],[1],[Define to 1 if you have the header file.])], []) -AC_CHECK_FUNCS([strchr strdup strstr timegm gmtime_r strtok_r strcasecmp getpwnam getgrnam]) +AC_CHECK_FUNCS([strchr strdup strstr timegm gmtime_r localtime_r strtok_r strcasecmp getpwnam getgrnam]) AC_CHECK_TYPES([struct sockaddr_storage], [], [], [[#include ]]) AC_CHECK_MEMBERS([struct sockaddr.sa_len], [], [], [[#include ]]) diff --git a/msi/WiX/ShibbolethSP-defs-x86.wxi b/msi/WiX/ShibbolethSP-defs-x86.wxi index 573ef35..58fbedb 100644 --- a/msi/WiX/ShibbolethSP-defs-x86.wxi +++ b/msi/WiX/ShibbolethSP-defs-x86.wxi @@ -59,6 +59,7 @@ + @@ -72,6 +73,7 @@ + diff --git a/msi/WiX/ShibbolethSP-exe-x64.wxs b/msi/WiX/ShibbolethSP-exe-x64.wxs index ef3962b..672fe0d 100644 --- a/msi/WiX/ShibbolethSP-exe-x64.wxs +++ b/msi/WiX/ShibbolethSP-exe-x64.wxs @@ -45,7 +45,7 @@ - + @@ -62,6 +62,9 @@ + + + @@ -90,6 +93,9 @@ + + + diff --git a/msi/WiX/ShibbolethSP-exe-x86.wxs b/msi/WiX/ShibbolethSP-exe-x86.wxs index 85e8326..480b95d 100644 --- a/msi/WiX/ShibbolethSP-exe-x86.wxs +++ b/msi/WiX/ShibbolethSP-exe-x86.wxs @@ -71,6 +71,9 @@ + + + @@ -108,6 +111,9 @@ + + + diff --git a/plugins/Makefile.am b/plugins/Makefile.am index c97e828..e9ec3e0 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS = foreign plugindir = $(libdir)/@PACKAGE_NAME@ -plugin_LTLIBRARIES = plugins.la +plugin_LTLIBRARIES = plugins.la plugins-lite.la noinst_HEADERS = \ internal.h @@ -14,20 +14,22 @@ plugins_la_SOURCES = \ CaseFoldingAttributeResolver.cpp \ GSSAPIAttributeExtractor.cpp \ TemplateAttributeResolver.cpp \ + TimeAccessControlFactory.cpp \ TransformAttributeResolver.cpp -#plugins_lite_la_SOURCES = \ -# ${common_sources} +plugins_lite_la_SOURCES = \ + ${common_sources} \ + TimeAccessControlFactory.cpp plugins_la_LIBADD = $(XMLSEC_LIBS) \ $(top_builddir)/shibsp/libshibsp.la -#plugins_lite_la_LIBADD = $(LITE_LIBS) \ -# $(top_builddir)/shibsp/libshibsp-lite.la +plugins_lite_la_LIBADD = $(LITE_LIBS) \ + $(top_builddir)/shibsp/libshibsp-lite.la plugins_la_LDFLAGS = -module -avoid-version -#plugins_lite_la_LDFLAGS = -module -avoid-version -#plugins_lite_la_CPPFLAGS = -DSHIBSP_LITE +plugins_lite_la_LDFLAGS = -module -avoid-version +plugins_lite_la_CPPFLAGS = -DSHIBSP_LITE install-data-hook: for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done diff --git a/plugins/TimeAccessControl.cpp b/plugins/TimeAccessControl.cpp new file mode 100644 index 0000000..60550b1 --- /dev/null +++ b/plugins/TimeAccessControl.cpp @@ -0,0 +1,285 @@ +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * UCAID licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the + * License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +/** + * TimeAccessControl.cpp + * + * Access control plugin for time-based policies. + */ + +#include "internal.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace xercesc; +using namespace boost; +using namespace std; + +namespace shibsp { + + class Rule : public AccessControl + { + public: + Rule(const DOMElement* e); + ~Rule() {} + + Lockable* lock() {return this;} + void unlock() {} + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + enum { TM_AUTHN, TM_TIME, TM_YEAR, TM_MONTH, TM_DAY, TM_HOUR, TM_MINUTE, TM_SECOND, TM_WDAY } m_type; + enum { OP_LT, OP_LE, OP_EQ, OP_GE, OP_GT } m_op; + time_t m_value; + }; + + class TimeAccessControl : public AccessControl + { + public: + TimeAccessControl(const DOMElement* e); + ~TimeAccessControl() {} + + Lockable* lock() { + return this; + } + void unlock() { + } + + aclresult_t authorized(const SPRequest& request, const Session* session) const; + + private: + enum { OP_AND, OP_OR } m_op; + ptr_vector m_rules; + }; + + AccessControl* SHIBSP_DLLLOCAL TimeAccessControlFactory(const DOMElement* const & e) + { + return new TimeAccessControl(e); + } + + static const XMLCh _operator[] = UNICODE_LITERAL_8(o,p,e,r,a,t,o,r); + static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); + static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); + static const XMLCh Day[] = UNICODE_LITERAL_3(D,a,y); + static const XMLCh DayOfWeek[] = UNICODE_LITERAL_9(D,a,y,O,f,W,e,e,k); + static const XMLCh Hour[] = UNICODE_LITERAL_4(H,o,u,r); + static const XMLCh Minute[] = UNICODE_LITERAL_6(M,i,n,u,t,e); + static const XMLCh Month[] = UNICODE_LITERAL_5(M,o,n,t,h); + static const XMLCh Second[] = UNICODE_LITERAL_6(S,e,c,o,n,d); + static const XMLCh Time[] = UNICODE_LITERAL_4(T,i,m,e); + static const XMLCh TimeSinceAuthn[] = UNICODE_LITERAL_14(T,i,m,e,S,i,n,c,e,A,u,t,h,n); + static const XMLCh Year[] = UNICODE_LITERAL_4(Y,e,a,r); +} + +Rule::Rule(const DOMElement* e) +{ + if (XMLString::equals(e->getLocalName(), TimeSinceAuthn)) { + m_type = TM_AUTHN; + DateTime dur(e->getTextContent()); + dur.parseDuration(); + m_value = dur.getEpoch(true); + return; + } + + auto_ptr_char temp(e->getTextContent()); + string s(temp.get() ? temp.get() : ""); + vector tokens; + if (split(tokens, s, is_space(), algorithm::token_compress_on).size() != 2) + throw ConfigurationException("Time-based rule requires element content of the form \"LT|LE|EQ|GE|GT value\"."); + string& op = tokens.front(); + if (op == "LT") m_op = OP_LT; + else if (op == "LE") m_op = OP_LE; + else if (op == "EQ") m_op = OP_EQ; + else if (op == "GE") m_op = OP_GE; + else if (op == "GT") m_op = OP_GT; + else + throw ConfigurationException("First component of time-based rule must be one of LT, LE, EQ, GE, GT."); + + if (XMLString::equals(e->getLocalName(), Time)) { + m_type = TM_TIME; + auto_ptr_XMLCh widen(tokens.back().c_str()); + DateTime dt(widen.get()); + dt.parseDateTime(); + m_value = dt.getEpoch(); + return; + } + + m_value = lexical_cast(tokens.back()); + + if (XMLString::equals(e->getLocalName(), Year)) m_type = TM_YEAR; + else if (XMLString::equals(e->getLocalName(), Month)) m_type = TM_MONTH; + else if (XMLString::equals(e->getLocalName(), Day)) m_type = TM_DAY; + else if (XMLString::equals(e->getLocalName(), Hour)) m_type = TM_HOUR; + else if (XMLString::equals(e->getLocalName(), Minute)) m_type = TM_MINUTE; + else if (XMLString::equals(e->getLocalName(), Second)) m_type = TM_SECOND; + else if (XMLString::equals(e->getLocalName(), DayOfWeek)) m_type = TM_WDAY; + else + throw ConfigurationException("Unrecognized time-based rule."); +} + +/* + + PT1H + + LT|LE|EQ|GE|GT nn + LT|LE|EQ|GE|GT nn + LT|LE|EQ|GE|GT nn + LT|LE|EQ|GE|GT nn + LT|LE|EQ|GE|GT nn + LT|LE|EQ|GE|GT nn + LT|LE|EQ|GE|GT 0-6 + +*/ + +AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const +{ + time_t operand = 0; + + if (m_type == TM_AUTHN) { + if (session) { + auto_ptr_XMLCh atime(session->getAuthnInstant()); + if (atime.get()) { + try { + DateTime dt(atime.get()); + dt.parseDateTime(); + if (time(nullptr) - dt.getEpoch() <= m_value) + return shib_acl_true; + request.log(SPRequest::SPDebug, "elapsed time since authentication exceeds limit"); + return shib_acl_false; + } + catch (std::exception& e) { + request.log(SPRequest::SPError, e.what()); + } + } + } + request.log(SPRequest::SPDebug, "session or authentication time unavailable"); + return shib_acl_false; + } + + // Extract value from tm struct or time directly. + operand = time(nullptr); + if (m_type != TM_TIME) { +#ifndef HAVE_LOCALTIME_R + struct tm* ptime = localtime(&operand); +#else + struct tm res; + struct tm* ptime = localtime_r(&operand, &res); +#endif + switch (m_type) { + case TM_YEAR: + operand = ptime->tm_year + 1900; + break; + case TM_MONTH: + operand = ptime->tm_mon + 1; + break; + case TM_DAY: + operand = ptime->tm_mday; + break; + case TM_HOUR: + operand = ptime->tm_hour; + break; + case TM_MINUTE: + operand = ptime->tm_min; + break; + case TM_SECOND: + operand = ptime->tm_sec; + break; + case TM_WDAY: + operand = ptime->tm_wday; + break; + } + } + + // Compare operand to test value in rule using rule operator. + switch (m_op) { + case OP_LT: + return (operand < m_value) ? shib_acl_true : shib_acl_false; + case OP_LE: + return (operand <= m_value) ? shib_acl_true : shib_acl_false; + case OP_EQ: + return (operand == m_value) ? shib_acl_true : shib_acl_false; + case OP_GE: + return (operand >= m_value) ? shib_acl_true : shib_acl_false; + case OP_GT: + return (operand > m_value) ? shib_acl_true : shib_acl_false; + } + return shib_acl_false; +} + +TimeAccessControl::TimeAccessControl(const DOMElement* e) : m_op(OP_AND) +{ + const XMLCh* op = e ? e->getAttributeNS(nullptr, _operator) : nullptr; + if (XMLString::equals(op, OR)) + m_op = OP_OR; + else if (op && *op && !XMLString::equals(op, AND)) + throw ConfigurationException("Unrecognized operator in Time AccessControl configuration."); + + e = XMLHelper::getFirstChildElement(e); + while (e) { + auto_ptr np(new Rule(e)); + m_rules.push_back(np.get()); + np.release(); + e = XMLHelper::getNextSiblingElement(e); + } + if (m_rules.empty()) + throw ConfigurationException("Time AccessControl plugin requires at least one rule."); +} + +AccessControl::aclresult_t TimeAccessControl::authorized(const SPRequest& request, const Session* session) const +{ + switch (m_op) { + case OP_AND: + { + for (ptr_vector::const_iterator i = m_rules.begin(); i != m_rules.end(); ++i) { + if (i->authorized(request, session) != shib_acl_true) { + request.log(SPRequest::SPDebug, "time-based rule unsuccessful, denying access"); + return shib_acl_false; + } + } + return shib_acl_true; + } + + case OP_OR: + { + for (ptr_vector::const_iterator i = m_rules.begin(); i != m_rules.end(); ++i) { + if (i->authorized(request,session) == shib_acl_true) + return shib_acl_true; + } + request.log(SPRequest::SPDebug, "all time-based rules unsuccessful, denying access"); + return shib_acl_false; + } + } + request.log(SPRequest::SPWarn, "unknown operator in access control policy, denying access"); + return shib_acl_false; +} diff --git a/plugins/plugins-lite.vcxproj b/plugins/plugins-lite.vcxproj new file mode 100644 index 0000000..f21e8eb --- /dev/null +++ b/plugins/plugins-lite.vcxproj @@ -0,0 +1,200 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {A2140D6E-C2C6-4329-84E3-2F530CEBE442} + Win32Proj + plugins-lite + + + + DynamicLibrary + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + DynamicLibrary + MultiByte + true + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + .so + .so + .so + .so + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;SHIBSP_LITE;%(PreprocessorDefinitions) + .;..;..\..\cpp-xmltooling;%(AdditionalIncludeDirectories) + true + false + + + Windows + true + ..\..\cpp-xmltooling\$(Configuration);%(AdditionalLibraryDirectories) + log4shib1D.lib;xerces-c_3D.lib;xmltooling-lite1D.lib;%(AdditionalDependencies) + + + + + X64 + + + Disabled + .;..;..\..\cpp-xmltooling;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;SHIBSP_LITE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + + + true + Level3 + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + + + log4shib1D.lib;xerces-c_3D.lib;xmltooling-lite1D.lib;%(AdditionalDependencies) + ..\..\cpp-xmltooling\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + true + Windows + + + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;SHIBSP_LITE;%(PreprocessorDefinitions) + .;..;..\..\cpp-xmltooling;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + ..\..\cpp-xmltooling\$(Configuration);%(AdditionalLibraryDirectories) + log4shib1.lib;xerces-c_3.lib;xmltooling-lite1.lib;%(AdditionalDependencies) + + + + + X64 + + + .;..;..\..\cpp-xmltooling;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;SHIBSP_LITE;%(PreprocessorDefinitions) + + + Level3 + + + log4shib1.lib;xerces-c_3.lib;xmltooling-lite1.lib;%(AdditionalDependencies) + ..\..\cpp-xmltooling\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + true + Windows + true + true + + + + + + + + + + + + + + + + + + + + + {81f0f7a6-dc36-46ef-957f-f9e81d4403f7} + false + + + + + + diff --git a/plugins/plugins.cpp b/plugins/plugins.cpp index 323f7d4..d23f127 100644 --- a/plugins/plugins.cpp +++ b/plugins/plugins.cpp @@ -41,29 +41,35 @@ using namespace std; #endif namespace shibsp { -#ifdef HAVE_GSSAPI_NAMINGEXTS + PluginManager::Factory TimeAccessControlFactory; +#ifndef SHIBSP_LITE +# ifdef HAVE_GSSAPI_NAMINGEXTS PluginManager::Factory GSSAPIExtractorFactory; -#endif +# endif PluginManager::Factory TemplateAttributeResolverFactory; PluginManager::Factory TransformAttributeResolverFactory; PluginManager::Factory UpperCaseAttributeResolverFactory; PluginManager::Factory LowerCaseAttributeResolverFactory; +#endif }; extern "C" int PLUGINS_EXPORTS xmltooling_extension_init(void*) { SPConfig& conf = SPConfig::getConfig(); -#ifdef HAVE_GSSAPI_NAMINGEXTS + conf.AccessControlManager.registerFactory("Time", TimeAccessControlFactory); +#ifndef SHIBSP_LITE +# ifdef HAVE_GSSAPI_NAMINGEXTS conf.AttributeExtractorManager.registerFactory("GSSAPI", GSSAPIExtractorFactory); static const XMLCh _GSSAPIName[] = UNICODE_LITERAL_10(G,S,S,A,P,I,N,a,m,e); static const XMLCh _GSSAPIContext[] = UNICODE_LITERAL_13(G,S,S,A,P,I,C,o,n,t,e,x,t); XMLObjectBuilder::registerBuilder(xmltooling::QName(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _GSSAPIName), new AnyElementBuilder()); XMLObjectBuilder::registerBuilder(xmltooling::QName(shibspconstants::SHIB2ATTRIBUTEMAP_NS, _GSSAPIContext), new AnyElementBuilder()); -#endif +# endif conf.AttributeResolverManager.registerFactory("Template", TemplateAttributeResolverFactory); conf.AttributeResolverManager.registerFactory("Transform", TransformAttributeResolverFactory); conf.AttributeResolverManager.registerFactory("UpperCase", UpperCaseAttributeResolverFactory); conf.AttributeResolverManager.registerFactory("LowerCase", LowerCaseAttributeResolverFactory); +#endif return 0; // signal success } diff --git a/plugins/plugins.vcxproj b/plugins/plugins.vcxproj index c5c78cd..5454262 100644 --- a/plugins/plugins.vcxproj +++ b/plugins/plugins.vcxproj @@ -140,7 +140,7 @@ MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGINS_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) .;..;..\..\cpp-opensaml;..\..\cpp-xmltooling;%(AdditionalIncludeDirectories) @@ -179,6 +179,7 @@ + diff --git a/plugins/plugins.vcxproj.filters b/plugins/plugins.vcxproj.filters index f47d1e8..09299f3 100644 --- a/plugins/plugins.vcxproj.filters +++ b/plugins/plugins.vcxproj.filters @@ -6,6 +6,7 @@ + diff --git a/shibsp/impl/TransactionLog.cpp b/shibsp/impl/TransactionLog.cpp index 1207c59..211baed 100644 --- a/shibsp/impl/TransactionLog.cpp +++ b/shibsp/impl/TransactionLog.cpp @@ -462,7 +462,7 @@ namespace { } if (t == 0) return false; -#ifndef HAVE_GMTIME_R +#ifndef HAVE_LOCALTIME_R struct tm* ptime=localtime(&t); #else struct tm res; @@ -501,7 +501,7 @@ namespace { } if (t == 0) return false; -#ifndef HAVE_GMTIME_R +#ifndef HAVE_LOCALTIME_R struct tm* ptime=localtime(&t); #else struct tm res; @@ -524,7 +524,7 @@ namespace { } if (t == 0) return false; -#ifndef HAVE_GMTIME_R +#ifndef HAVE_LOCALTIME_R struct tm* ptime=localtime(&t); #else struct tm res;