various fixes, see CHANGELOG

This commit is contained in:
Guenter Obiltschnig
2013-11-14 21:44:04 +01:00
parent a5c36205fa
commit af3d2537aa
7 changed files with 118 additions and 59 deletions

View File

@@ -1,5 +1,16 @@
This is the changelog file for the POCO C++ Libraries. This is the changelog file for the POCO C++ Libraries.
Release 1.4.6p3 (2013-12-20)
============================
- fixed GH# 305 (memcpy in Poco::Buffer uses wrong size if type != char)
- fixed GH# 316: Poco::DateTimeFormatter::append() gives wrong result for
Poco::LocalDateTime
- Poco::Data::MySQL: added SQLite thread cleanup handler
- Poco::Net::X509Certificate: improved and fixed domain name verification for
wildcard domains
Release 1.4.6p2 (2013-09-16) Release 1.4.6p2 (2013-09-16)
============================ ============================
@@ -1858,4 +1869,4 @@ building the libraries.
-- --
$Id: //poco/1.4/dist/CHANGELOG#94 $ $Id: //poco/1.4/dist/CHANGELOG#95 $

View File

@@ -1,7 +1,7 @@
// //
// SesssionHandle.cpp // SesssionHandle.cpp
// //
// $Id: //poco/1.4/Data/MySQL/src/SessionHandle.cpp#1 $ // $Id: //poco/1.4/Data/MySQL/src/SessionHandle.cpp#2 $
// //
// Library: Data/MySQL // Library: Data/MySQL
// Package: MySQL // Package: MySQL
@@ -35,7 +35,11 @@
#include "Poco/Data/MySQL/SessionHandle.h" #include "Poco/Data/MySQL/SessionHandle.h"
#include "Poco/SingletonHolder.h"
#include <cstring> #include <cstring>
#ifdef POCO_OS_FAMILY_UNIX
#include <pthread.h>
#endif
namespace Poco { namespace Poco {
@@ -43,6 +47,42 @@ namespace Data {
namespace MySQL { namespace MySQL {
#ifdef POCO_OS_FAMILY_UNIX
class ThreadCleanupHelper
{
public:
ThreadCleanupHelper()
{
if (pthread_key_create(&_key, &ThreadCleanupHelper::cleanup) != 0)
throw Poco::SystemException("cannot create TLS key for mysql cleanup");
}
void init()
{
if (pthread_setspecific(_key, reinterpret_cast<void*>(1)))
throw Poco::SystemException("cannot set TLS key for mysql cleanup");
}
static ThreadCleanupHelper& instance()
{
return *_sh.get();
}
static void cleanup(void* data)
{
mysql_thread_end();
}
private:
pthread_key_t _key;
static Poco::SingletonHolder<ThreadCleanupHelper> _sh;
};
Poco::SingletonHolder<ThreadCleanupHelper> ThreadCleanupHelper::_sh;
#endif
SessionHandle::SessionHandle(MYSQL* mysql) SessionHandle::SessionHandle(MYSQL* mysql)
{ {
h = mysql_init(mysql); h = mysql_init(mysql);
@@ -51,6 +91,9 @@ SessionHandle::SessionHandle(MYSQL* mysql)
{ {
throw ConnectionException("mysql_init error"); throw ConnectionException("mysql_init error");
} }
#ifdef POCO_OS_FAMILY_UNIX
ThreadCleanupHelper::instance().init();
#endif
} }

View File

@@ -1,7 +1,7 @@
// //
// Version.h // Version.h
// //
// $Id: //poco/1.4/Foundation/include/Poco/Version.h#15 $ // $Id: //poco/1.4/Foundation/include/Poco/Version.h#16 $
// //
// Library: Foundation // Library: Foundation
// Package: Core // Package: Core
@@ -54,7 +54,7 @@
// Ax are alpha releases // Ax are alpha releases
// Bx are beta releases // Bx are beta releases
// //
#define POCO_VERSION 0x01040602 #define POCO_VERSION 0x01040603
#endif // Foundation_Version_INCLUDED #endif // Foundation_Version_INCLUDED

View File

@@ -1,7 +1,7 @@
// //
// SocketImpl.cpp // SocketImpl.cpp
// //
// $Id: //poco/1.4/Net/src/SocketImpl.cpp#9 $ // $Id: //poco/1.4/Net/src/SocketImpl.cpp#10 $
// //
// Library: Net // Library: Net
// Package: Sockets // Package: Sockets
@@ -959,7 +959,7 @@ void SocketImpl::error(int code, const std::string& arg)
case POCO_EFAULT: case POCO_EFAULT:
throw IOException("Bad address", code); throw IOException("Bad address", code);
case POCO_EINVAL: case POCO_EINVAL:
throw InvalidArgumentException(code); throw SystemException("Invalid argument", code);
case POCO_EMFILE: case POCO_EMFILE:
throw IOException("Too many open files", code); throw IOException("Too many open files", code);
case POCO_EWOULDBLOCK: case POCO_EWOULDBLOCK:
@@ -1021,6 +1021,8 @@ void SocketImpl::error(int code, const std::string& arg)
#if defined(POCO_OS_FAMILY_UNIX) #if defined(POCO_OS_FAMILY_UNIX)
case EPIPE: case EPIPE:
throw IOException("Broken pipe", code); throw IOException("Broken pipe", code);
case EBADF:
throw IOException("Bad socket descriptor", code);
#endif #endif
default: default:
throw IOException(NumberFormatter::format(code), arg, code); throw IOException(NumberFormatter::format(code), arg, code);

View File

@@ -1,7 +1,7 @@
// //
// WebSocketImpl.cpp // WebSocketImpl.cpp
// //
// $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#9 $ // $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#10 $
// //
// Library: Net // Library: Net
// Package: WebSocket // Package: WebSocket
@@ -43,7 +43,7 @@
#include "Poco/MemoryStream.h" #include "Poco/MemoryStream.h"
#include "Poco/Format.h" #include "Poco/Format.h"
#include <cstring> #include <cstring>
#include <iostream>
namespace Poco { namespace Poco {
namespace Net { namespace Net {
@@ -130,6 +130,8 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
int maskOffset = 0; int maskOffset = 0;
if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4; if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4;
lengthByte &= 0x7f; lengthByte &= 0x7f;
if (lengthByte > 0 || maskOffset > 0)
{
if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH) if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH)
{ {
n = receiveNBytes(header + 2, lengthByte + maskOffset); n = receiveNBytes(header + 2, lengthByte + maskOffset);
@@ -138,10 +140,9 @@ int WebSocketImpl::receiveBytes(void* buffer, int length, int)
{ {
n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2); n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2);
} }
if (n <= 0) throw WebSocketException("Incomplete header received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
if (n <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
n += 2; n += 2;
}
Poco::MemoryInputStream istr(header, n); Poco::MemoryInputStream istr(header, n);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt8 flags; Poco::UInt8 flags;

View File

@@ -1,7 +1,7 @@
// //
// X509Certificate.h // X509Certificate.h
// //
// $Id: //poco/1.4/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h#1 $ // $Id: //poco/1.4/NetSSL_OpenSSL/include/Poco/Net/X509Certificate.h#2 $
// //
// Library: NetSSL_OpenSSL // Library: NetSSL_OpenSSL
// Package: SSLCore // Package: SSLCore
@@ -108,7 +108,7 @@ public:
protected: protected:
static bool containsWildcards(const std::string& commonName); static bool containsWildcards(const std::string& commonName);
static bool matchByAlias(const std::string& alias, const HostEntry& heData); static bool matchByAlias(const std::string& alias, const std::string& hostName);
private: private:
enum enum

View File

@@ -1,7 +1,7 @@
// //
// X509Certificate.cpp // X509Certificate.cpp
// //
// $Id: //poco/1.4/NetSSL_OpenSSL/src/X509Certificate.cpp#2 $ // $Id: //poco/1.4/NetSSL_OpenSSL/src/X509Certificate.cpp#3 $
// //
// Library: NetSSL_OpenSSL // Library: NetSSL_OpenSSL
// Package: SSLCore // Package: SSLCore
@@ -107,23 +107,20 @@ bool X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, c
std::string commonName; std::string commonName;
std::set<std::string> dnsNames; std::set<std::string> dnsNames;
certificate.extractNames(commonName, dnsNames); certificate.extractNames(commonName, dnsNames);
if (!commonName.empty()) dnsNames.insert(commonName);
bool ok = (dnsNames.find(hostName) != dnsNames.end()); bool ok = (dnsNames.find(hostName) != dnsNames.end());
if (!ok)
char buffer[NAME_BUFFER_SIZE]; {
X509_NAME* subj = 0; for (std::set<std::string>::const_iterator it = dnsNames.begin(); !ok && it != dnsNames.end(); ++it)
if (!ok && (subj = X509_get_subject_name(const_cast<X509*>(certificate.certificate()))) && X509_NAME_get_text_by_NID(subj, NID_commonName, buffer, sizeof(buffer)) > 0)
{ {
buffer[NAME_BUFFER_SIZE - 1] = 0;
std::string commonName(buffer); // commonName can contain wildcards like *.appinf.com
try try
{ {
// two cases: strData contains wildcards or not // two cases: strData contains wildcards or not
if (containsWildcards(commonName)) if (containsWildcards(*it))
{ {
// a compare by IPAddress is not possible with wildcards // a compare by IPAddress is not possible with wildcards
// only allow compare by name // only allow compare by name
const HostEntry& heData = DNS::resolve(hostName); ok = matchByAlias(*it, hostName);
ok = matchByAlias(commonName, heData);
} }
else else
{ {
@@ -132,7 +129,7 @@ bool X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, c
if (IPAddress::tryParse(hostName, ip)) if (IPAddress::tryParse(hostName, ip))
{ {
// compare by IP // compare by IP
const HostEntry& heData = DNS::resolve(commonName); const HostEntry& heData = DNS::resolve(*it);
const HostEntry::AddressList& addr = heData.addresses(); const HostEntry::AddressList& addr = heData.addresses();
HostEntry::AddressList::const_iterator it = addr.begin(); HostEntry::AddressList::const_iterator it = addr.begin();
HostEntry::AddressList::const_iterator itEnd = addr.end(); HostEntry::AddressList::const_iterator itEnd = addr.end();
@@ -144,14 +141,13 @@ bool X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, c
else else
{ {
// compare by name // compare by name
const HostEntry& heData = DNS::resolve(hostName); ok = matchByAlias(*it, hostName);
ok = matchByAlias(commonName, heData);
} }
} }
} }
catch (HostNotFoundException&) catch (HostNotFoundException&)
{ {
return false; }
} }
} }
return ok; return ok;
@@ -164,8 +160,9 @@ bool X509Certificate::containsWildcards(const std::string& commonName)
} }
bool X509Certificate::matchByAlias(const std::string& alias, const HostEntry& heData) bool X509Certificate::matchByAlias(const std::string& alias, const std::string& hostName)
{ {
const HostEntry& heData = DNS::resolve(hostName);
// fix wildcards // fix wildcards
std::string aliasRep = Poco::replace(alias, ".", "\\."); std::string aliasRep = Poco::replace(alias, ".", "\\.");
Poco::replaceInPlace(aliasRep, "*", ".*"); Poco::replaceInPlace(aliasRep, "*", ".*");
@@ -183,11 +180,16 @@ bool X509Certificate::matchByAlias(const std::string& alias, const HostEntry& he
found = expr.match(*it); found = expr.match(*it);
} }
// Handle the case where the list of aliases is empty. // Handle the case where the list of aliases is empty.
if (aliases.empty()) if (!found)
{ {
// Compare the host name against the wildcard host name in the certificate. // Compare the resolved host name against the wildcard host name in the certificate.
found = expr.match(heData.name()); found = expr.match(heData.name());
} }
if (!found)
{
// Compare the original host name against the wildcard host name in the certificate.
found = expr.match(hostName);
}
return found; return found;
} }