Skip to content

Commit 120dd0e

Browse files
committed
Merge branch 'development' of https://git01.codeplex.com/casablanca into json_unicode
2 parents 6263d69 + 1530786 commit 120dd0e

File tree

4 files changed

+211
-156
lines changed

4 files changed

+211
-156
lines changed

Release/include/cpprest/x509_cert_utilities.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/***
22
* ==++==
33
*
4-
* Copyright (c) Microsoft Corporation. All rights reserved.
4+
* Copyright (c) Microsoft Corporation. All rights reserved.
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
77
* You may obtain a copy of the License at
@@ -18,7 +18,7 @@
1818
*
1919
* x509_cert_utilities.h
2020
*
21-
* Contains utility functions for helping to verify server certificates in OS X/iOS.
21+
* Contains utility functions for helping to verify server certificates in OS X/iOS and Android.
2222
*
2323
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
2424
*
@@ -30,8 +30,23 @@
3030
#include <vector>
3131
#include <string>
3232

33+
#if defined(__APPLE__) || defined(ANDROID)
34+
35+
#include <boost/asio/ssl.hpp>
36+
3337
namespace web { namespace http { namespace client { namespace details {
3438

39+
/// <summary>
40+
/// Using platform specific APIs verifies server certificate.
41+
/// Currently implemented to work on iOS, Android, and OS X.
42+
/// </summary>
43+
/// <param name="verifyCtx">Boost.ASIO context get certificate chain from.</param>
44+
/// <param name="hostName">Host name from the URI.</param>
45+
/// <returns>True if verification passed and server can be trusted, false otherwise.</returns>
46+
bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName);
47+
3548
bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std::string &hostName);
3649

3750
}}}}
51+
52+
#endif

Release/src/http/client/http_linux.cpp

Lines changed: 32 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/***
22
* ==++==
33
*
4-
* Copyright (c) Microsoft Corporation. All rights reserved.
4+
* Copyright (c) Microsoft Corporation. All rights reserved.
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
77
* You may obtain a copy of the License at
@@ -19,7 +19,7 @@
1919
* http_linux.cpp
2020
*
2121
* HTTP Library: Client-side APIs.
22-
*
22+
*
2323
* This file contains the implementation for Linux
2424
*
2525
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
@@ -95,7 +95,7 @@ namespace web { namespace http
9595
bool is_reused() const { return m_is_reused; }
9696

9797
void set_keep_alive(bool keep_alive) { m_keep_alive = keep_alive; }
98-
bool keep_alive() const { return m_keep_alive; }
98+
bool keep_alive() const { return m_keep_alive; }
9999
tcp::socket& socket() { return m_socket; }
100100

101101
private:
@@ -258,29 +258,29 @@ namespace web { namespace http
258258
}
259259
request_context::report_error(errorcodeValue, message);
260260
}
261-
261+
262262
void set_timer(const int secs)
263263
{
264264
m_timeout_timer.expires_from_now(boost::posix_time::milliseconds(secs * 1000));
265265
m_timeout_timer.async_wait(boost::bind(&linux_client_request_context::handle_timeout_timer, this, boost::asio::placeholders::error));
266266
}
267-
267+
268268
void reset_timer(const int secs)
269269
{
270270
if (m_timeout_timer.expires_from_now(boost::posix_time::milliseconds(secs * 1000)) > 0)
271271
{
272272
m_timeout_timer.async_wait(boost::bind(&linux_client_request_context::handle_timeout_timer, this, boost::asio::placeholders::error));
273273
}
274274
}
275-
275+
276276
std::unique_ptr<boost::asio::ssl::stream<tcp::socket &> > m_ssl_stream;
277277
uint64_t m_known_size;
278278
bool m_needChunked;
279279
bool m_timedout;
280280
boost::asio::streambuf m_body_buf;
281281
boost::asio::deadline_timer m_timeout_timer;
282282
std::shared_ptr<linux_connection> m_connection;
283-
283+
284284
#if defined(__APPLE__) || defined(ANDROID)
285285
bool m_openssl_failed;
286286
#endif
@@ -301,8 +301,8 @@ namespace web { namespace http
301301
}
302302

303303
linux_client_request_context(
304-
const std::shared_ptr<_http_client_communicator> &client,
305-
http_request request,
304+
const std::shared_ptr<_http_client_communicator> &client,
305+
http_request request,
306306
const std::shared_ptr<linux_connection> &connection);
307307

308308
protected:
@@ -332,7 +332,7 @@ namespace web { namespace http
332332
{
333333
if (request_ctx->m_request._cancellation_token().is_canceled())
334334
{
335-
request_ctx->report_error(make_error_code(std::errc::operation_canceled).value(), "Request cancelled by user.");
335+
request_ctx->report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user.");
336336
return;
337337
}
338338

@@ -380,7 +380,7 @@ namespace web { namespace http
380380
if (ctx->m_request.headers().match(header_names::transfer_encoding, transferencoding) && transferencoding == "chunked")
381381
{
382382
ctx->m_needChunked = true;
383-
}
383+
}
384384
else if (!ctx->m_request.headers().match(header_names::content_length, ctx->m_known_size))
385385
{
386386
// Stream without content length is the signal of requiring transfer encoding chunked.
@@ -460,7 +460,7 @@ namespace web { namespace http
460460
}
461461
}
462462

463-
void handle_resolve(const boost::system::error_code& ec, tcp::resolver::iterator endpoints, std::shared_ptr<linux_client_request_context> ctx)
463+
void handle_resolve(const boost::system::error_code& ec, tcp::resolver::iterator endpoints, const std::shared_ptr<linux_client_request_context> &ctx)
464464
{
465465
if (ec)
466466
{
@@ -500,8 +500,8 @@ namespace web { namespace http
500500
ctx->m_timeout_timer.cancel();
501501

502502
// Replace the connection. This causes old connection object to go out of scope.
503-
ctx->m_connection = m_pool.obtain();
504-
503+
ctx->m_connection = m_pool.obtain();
504+
505505
if (ctx->m_ssl_stream)
506506
{
507507
reset_ssl_stream(ctx);
@@ -521,66 +521,27 @@ namespace web { namespace http
521521
// certificate, i.e. actual server certificate is at the '0' position in the
522522
// certificate chain, the rest are optional intermediate certificates, followed
523523
// finally by the root CA self signed certificate.
524-
524+
525525
#if defined(__APPLE__) || defined(ANDROID)
526+
// On OS X, iOS, and Android, OpenSSL doesn't have access to where the OS
527+
// stores keychains. If OpenSSL fails we will doing verification at the
528+
// end using the whole certificate chain so wait until the 'leaf' cert.
529+
// For now return true so OpenSSL continues down the certificate chain.
526530
if(!preverified)
527531
{
528532
requestCtx->m_openssl_failed = true;
529533
}
530534
if(requestCtx->m_openssl_failed)
531535
{
532-
// On OS X, iOS, and Android, OpenSSL doesn't have access to where the OS
533-
// stores keychains. If OpenSSL fails we will doing verification at the
534-
// end using the whole certificate chain so wait until the 'leaf' cert.
535-
// For now return true so OpenSSL continues down the certificate chain.
536-
X509_STORE_CTX *storeContext = verifyCtx.native_handle();
537-
int currentDepth = X509_STORE_CTX_get_error_depth(storeContext);
538-
if(currentDepth != 0)
539-
{
540-
return true;
541-
}
542-
543-
STACK_OF(X509) *certStack = X509_STORE_CTX_get_chain(storeContext);
544-
const int numCerts = sk_X509_num(certStack);
545-
if(numCerts < 0)
546-
{
547-
return false;
548-
}
549-
550-
std::vector<std::string> certChain;
551-
certChain.reserve(numCerts);
552-
for(int i = 0; i < numCerts; ++i)
553-
{
554-
X509 *cert = sk_X509_value(certStack, i);
555-
556-
// Encode into DER format into raw memory.
557-
int len = i2d_X509(cert, nullptr);
558-
if(len < 0)
559-
{
560-
return false;
561-
}
562-
563-
std::string certData;
564-
certData.resize(len);
565-
unsigned char * buffer = reinterpret_cast<unsigned char *>(&certData[0]);
566-
len = i2d_X509(cert, &buffer);
567-
if(len < 0)
568-
{
569-
return false;
570-
}
571-
572-
certChain.push_back(std::move(certData));
573-
}
574-
575-
return verify_X509_cert_chain(certChain, m_uri.host());
536+
return verify_cert_chain_platform_specific(verifyCtx, m_uri.host());
576537
}
577538
#endif
578-
539+
579540
boost::asio::ssl::rfc2818_verification rfc2818(m_uri.host());
580541
return rfc2818(preverified, verifyCtx);
581542
}
582543

583-
void handle_handshake(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
544+
void handle_handshake(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
584545
{
585546
if (!ec)
586547
{
@@ -592,7 +553,7 @@ namespace web { namespace http
592553
}
593554
}
594555

595-
void handle_write_chunked_body(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
556+
void handle_write_chunked_body(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
596557
{
597558
if (ec)
598559
{
@@ -664,7 +625,7 @@ namespace web { namespace http
664625
});
665626
}
666627

667-
void handle_write_large_body(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
628+
void handle_write_large_body(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
668629
{
669630
if (ec || ctx->m_uploaded >= ctx->m_known_size)
670631
{
@@ -721,7 +682,7 @@ namespace web { namespace http
721682
});
722683
}
723684

724-
void handle_write_headers(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
685+
void handle_write_headers(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
725686
{
726687
if(ec)
727688
{
@@ -740,7 +701,7 @@ namespace web { namespace http
740701
}
741702
}
742703

743-
void handle_write_body(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
704+
void handle_write_body(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
744705
{
745706
if (!ec)
746707
{
@@ -776,7 +737,7 @@ namespace web { namespace http
776737
}
777738
}
778739

779-
void handle_status_line(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
740+
void handle_status_line(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> &ctx)
780741
{
781742
if (!ec)
782743
{
@@ -799,7 +760,7 @@ namespace web { namespace http
799760
ctx->report_error("Invalid HTTP status line", ec, httpclient_errorcode_context::readheader);
800761
return;
801762
}
802-
763+
803764
read_headers(ctx);
804765
}
805766
else
@@ -916,7 +877,7 @@ namespace web { namespace http
916877
}
917878

918879
template <typename ReadHandler>
919-
void async_read_until_buffersize(size_t size, ReadHandler handler, std::shared_ptr<linux_client_request_context> ctx)
880+
void async_read_until_buffersize(size_t size, ReadHandler handler, const std::shared_ptr<linux_client_request_context> &ctx)
920881
{
921882
size_t size_to_read = 0;
922883
if (ctx->m_body_buf.size() < size)
@@ -934,7 +895,7 @@ namespace web { namespace http
934895
}
935896
}
936897

937-
void handle_chunk_header(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
898+
void handle_chunk_header(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
938899
{
939900
if (!ec)
940901
{
@@ -962,7 +923,7 @@ namespace web { namespace http
962923
}
963924
}
964925

965-
void handle_chunk(const boost::system::error_code& ec, int to_read, std::shared_ptr<linux_client_request_context> ctx)
926+
void handle_chunk(const boost::system::error_code& ec, int to_read, const std::shared_ptr<linux_client_request_context> &ctx)
966927
{
967928
if (!ec)
968929
{
@@ -1036,7 +997,7 @@ namespace web { namespace http
1036997
}
1037998
}
1038999

1039-
void handle_read_content(const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
1000+
void handle_read_content(const boost::system::error_code& ec, const std::shared_ptr<linux_client_request_context> &ctx)
10401001
{
10411002
auto writeBuffer = ctx->_get_writebuffer();
10421003

0 commit comments

Comments
 (0)