test/Makefile.am | 4 + test/UnitOAuth.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wsd/Storage.cpp | 3 + 3 files changed, 155 insertions(+), 1 deletion(-)
New commits: commit 5d96dfc4934384f58fc6b3f16dd54ba4d33c9916 Author: Henry Castro <hcas...@collabora.com> Date: Thu Aug 3 17:05:48 2017 -0400 wsd: OAuth token passing MS-WOPI: "The following HTTP header MUST be included in all WOPI requests." "Authorization "Bearer" and <token>" Change-Id: Ie5327286e93b86a49a0248ff5886bf3ea99df768 Reviewed-on: https://gerrit.libreoffice.org/40942 Reviewed-by: Jan Holesovsky <ke...@collabora.com> Tested-by: Jan Holesovsky <ke...@collabora.com> diff --git a/test/Makefile.am b/test/Makefile.am index 754f0f12..cef15a91 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -16,7 +16,7 @@ noinst_LTLIBRARIES = \ unit-timeout.la unit-prefork.la \ unit-storage.la \ unit-admin.la unit-tilecache.la \ - unit-fuzz.la unit-oob.la + unit-fuzz.la unit-oob.la unit-oauth.la MAGIC_TO_FORCE_SHLIB_CREATION = -rpath /dummy AM_LDFLAGS = -pthread -module $(MAGIC_TO_FORCE_SHLIB_CREATION) $(ZLIB_LIBS) @@ -60,6 +60,8 @@ unit_timeout_la_SOURCES = UnitTimeout.cpp unit_prefork_la_SOURCES = UnitPrefork.cpp unit_storage_la_SOURCES = UnitStorage.cpp unit_tilecache_la_SOURCES = UnitTileCache.cpp +unit_oauth_la_SOURCES = UnitOAuth.cpp +unit_oauth_la_LIBADD = $(CPPUNIT_LIBS) if HAVE_LO_PATH SYSTEM_STAMP = @SYSTEMPLATE_PATH@/system_stamp diff --git a/test/UnitOAuth.cpp b/test/UnitOAuth.cpp new file mode 100644 index 00000000..2a24ed9b --- /dev/null +++ b/test/UnitOAuth.cpp @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "config.h" + +//#include "Exceptions.hpp" +#include "Log.hpp" +#include "Unit.hpp" +#include "helpers.hpp" +#include <Poco/JSON/Object.h> +#include <Poco/LocalDateTime.h> +#include <Poco/DateTimeFormat.h> +#include <Poco/DateTimeFormatter.h> +#include <Poco/Net/HTTPRequest.h> +#include <Poco/Net/HTTPResponse.h> +#include <Poco/Net/HTTPServer.h> +#include <Poco/Net/HTTPRequestHandlerFactory.h> +#include <Poco/Net/HTTPRequestHandler.h> +#include <Poco/Net/HTTPServerRequest.h> +#include <Poco/Net/HTTPServerResponse.h> +#include <Poco/Net/HTTPServerParams.h> +#include <Poco/Net/ServerSocket.h> +#include <Poco/Net/OAuth20Credentials.h> + +using Poco::DateTimeFormatter; +using Poco::DateTimeFormat; +using Poco::JSON::Object; +using Poco::Net::HTTPServer; +using Poco::Net::HTTPRequest; +using Poco::Net::HTTPResponse; +using Poco::Net::HTTPRequestHandlerFactory; +using Poco::Net::HTTPRequestHandler; +using Poco::Net::HTTPServerRequest; +using Poco::Net::HTTPServerResponse; +using Poco::Net::HTTPServerParams; +using Poco::Net::OAuth20Credentials; +using Poco::Net::ServerSocket; + +class WopiHostRequestHandler: public HTTPRequestHandler +{ +public: + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + Poco::URI uriReq(request.getURI()); + + // The resource server MUST validate the access token + // and ensure that it has not expired and that its scope + // covers the requested resource. + OAuth20Credentials creds(request); + assert (creds.getBearerToken() == "s3hn3ct0k3v"); + + // CheckFileInfo + if (uriReq.getPath() == "/wopi/files/0") + { + Poco::LocalDateTime now; + Object::Ptr fileInfo = new Object(); + fileInfo->set("BaseFileName", "empty.odt"); + fileInfo->set("Size", "1024"); + fileInfo->set("Version", "1.0"); + fileInfo->set("OwnerId", "test"); + fileInfo->set("UserId", "test"); + fileInfo->set("UserFriendlyName", "test"); + fileInfo->set("UserCanWrite", "true"); + fileInfo->set("PostMessageOrigin", "localhost"); + fileInfo->set("LastModifiedTime", DateTimeFormatter::format(now, DateTimeFormat::ISO8601_FORMAT)); + + std::ostringstream oss; + fileInfo->stringify(oss); + response.setContentType("application/json; charset=utf-8"); + std::ostream& ostr = response.send(); + ostr << oss.str(); + } + // GetFile + else if (uriReq.getPath() == "/wopi/files/0/contents") + { + response.sendFile(Poco::Path(TDOC, "empty.odt").toString(), "application/vnd.oasis.opendocument.text"); + response.setStatusAndReason(HTTPResponse::HTTP_OK); + } + } + +}; + +class WopiHostRequestHandlerFactory: public HTTPRequestHandlerFactory +{ +public: + HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& /*request*/) + { + return new WopiHostRequestHandler(); + } +}; + + +class UnitOAuth : public UnitWSD +{ +public: + UnitOAuth() + { + } + + virtual void configure(Poco::Util::LayeredConfiguration& /*config*/) override + { + } + + void invokeTest() override + { + HTTPResponse response; + ServerSocket wopiSocket(0); + HTTPServerParams* wopiParams = new HTTPServerParams(); + wopiParams->setKeepAlive(false); + HTTPServer fakeWopiHost(new WopiHostRequestHandlerFactory, wopiSocket, wopiParams); + fakeWopiHost.start(); + + std::string WopiSrc; + const std::string testName = "UnitOAuth "; + + // RFC 6749 + // 7. Accessing Protected Resources + // The client accesses protected resources by presenting the access + // token (access_token) to the resource server. + Poco::URI wopiURL("http://localhost/wopi/files/0?access_token=s3hn3ct0k3v"); + wopiURL.setPort(wopiSocket.address().port()); + Poco::URI::encode(wopiURL.toString(), ":/?", WopiSrc); + Poco::URI loolUri(helpers::getTestServerURI()); + HTTPRequest request(HTTPRequest::HTTP_GET, "lool/" + WopiSrc + "/ws"); + + auto socket = helpers::connectLOKit(loolUri, request, response); + helpers::sendTextFrame(socket, "load url=" + WopiSrc, testName); + + const auto status = helpers::assertResponseString(socket, "status:", testName); + + Poco::Thread::sleep(1000); + fakeWopiHost.stop(); + + exitTest(TestResult::Ok); + } +}; + +UnitBase *unit_create_wsd(void) +{ + return new UnitOAuth(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp index 4ce78fa0..39e56fc0 100644 --- a/wsd/Storage.cpp +++ b/wsd/Storage.cpp @@ -516,6 +516,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const st Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uriObject.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); request.set("User-Agent", WOPI_AGENT_STRING); + request.set("Authorization", "Bearer " + accessToken); addStorageDebugCookie(request); psession->sendRequest(request); @@ -618,6 +619,7 @@ std::string WopiStorage::loadStorageFileToLocal(const std::string& accessToken) Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uriObject.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); request.set("User-Agent", WOPI_AGENT_STRING); + request.set("Authorization", "Bearer " + accessToken); addStorageDebugCookie(request); psession->sendRequest(request); @@ -687,6 +689,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const std::string& a Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, uriObject.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); request.set("X-WOPI-Override", "PUT"); + request.set("Authorization", "Bearer " + accessToken); if (!_forceSave) { // Request WOPI host to not overwrite if timestamps mismatch _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits