summaryrefslogtreecommitdiff
path: root/external
diff options
context:
space:
mode:
authorSzymon Kłos <eszkadev@gmail.com>2016-05-15 00:52:50 +0200
committerDavid Tardon <dtardon@redhat.com>2016-05-16 07:24:23 +0000
commit511db54e95d02292417d7cd076e4bd6d50956d64 (patch)
treeab8b4d46a35b1c9cc52679e966e0786bd18ca916 /external
parent5e54d9e9bc856520808a446f20575e29a50d017b (diff)
tdf#87938 libcmis: Google 2FA implementation
2 Factor Authentication for Google Drive, changes: + parsing additional page with challenge - pin code verification + calling the interaction dialog requesting the code + dialog title changed to more general: Authentication Code + dialog shows url field only if not empty Change-Id: Idb3ebbad6a12849b9e50af87b46324bfbe966bab Reviewed-on: https://gerrit.libreoffice.org/25002 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: David Tardon <dtardon@redhat.com>
Diffstat (limited to 'external')
-rw-r--r--external/libcmis/UnpackedTarball_cmis.mk1
-rwxr-xr-xexternal/libcmis/libcmis-google-2FA-implementation.patch156
2 files changed, 157 insertions, 0 deletions
diff --git a/external/libcmis/UnpackedTarball_cmis.mk b/external/libcmis/UnpackedTarball_cmis.mk
index 435e7c588018..bd66e2efeb5e 100644
--- a/external/libcmis/UnpackedTarball_cmis.mk
+++ b/external/libcmis/UnpackedTarball_cmis.mk
@@ -16,6 +16,7 @@ $(eval $(call gb_UnpackedTarball_set_patchlevel,cmis,1))
$(eval $(call gb_UnpackedTarball_add_patches,cmis, \
external/libcmis/libcmis-libxml2_compatibility.patch \
external/libcmis/libcmis-fix-google-drive.patch \
+ external/libcmis/libcmis-google-2FA-implementation.patch \
))
ifeq ($(OS)$(COM),WNTMSC)
diff --git a/external/libcmis/libcmis-google-2FA-implementation.patch b/external/libcmis/libcmis-google-2FA-implementation.patch
new file mode 100755
index 000000000000..23f9775f6f59
--- /dev/null
+++ b/external/libcmis/libcmis-google-2FA-implementation.patch
@@ -0,0 +1,156 @@
+diff --git a/src/libcmis/oauth2-providers.cxx b/src/libcmis/oauth2-providers.cxx
+--- a/src/libcmis/oauth2-providers.cxx
++++ b/src/libcmis/oauth2-providers.cxx
+@@ -29,6 +29,7 @@
+ #include <libxml/HTMLparser.h>
+ #include <libxml/xmlreader.h>
+
++#include "session-factory.hxx"
+ #include "oauth2-providers.hxx"
+ #include "http-session.hxx"
+
+@@ -51,10 +52,23 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
+ * 4) subsequent post to send a consent for the application
+ * receive a single-use authorization code
+ * this code is returned as a string
++ *
++ * Sequence with 2FA is:
++ * 1) a get to activate login page
++ * receive first login page, html format
++ * 2) subsequent post to sent email
++ * receive html page for password input
++ * 3) subsequent post to send password
++ * receive html page for pin input
++ * 3b) subsequent post to send pin number
++ * receive html page for application consent
++ * 4) subsequent post to send a consent for the application
++ * receive a single-use authorization code
++ * this code is returned as a string
+ */
+
+ static const string CONTENT_TYPE( "application/x-www-form-urlencoded" );
+- // STEP 1: Log in
++ // STEP 1: get login page
+ string res;
+ try
+ {
+@@ -66,6 +80,8 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
+ return string( );
+ }
+
++ // STEP 2: send email
++
+ string loginEmailPost, loginEmailLink;
+ if ( !parseResponse( res.c_str( ), loginEmailPost, loginEmailLink ) )
+ return string( );
+@@ -86,6 +102,8 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
+ return string( );
+ }
+
++ // STEP 3: password page
++
+ string loginPasswdPost, loginPasswdLink;
+ if ( !parseResponse( loginEmailRes.c_str( ), loginPasswdPost, loginPasswdLink ) )
+ return string( );
+@@ -106,10 +124,53 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
+ return string( );
+ }
+
+- // STEP 2: allow libcmis to access google drive
+ string approvalPost, approvalLink;
+ if ( !parseResponse( loginPasswdRes. c_str( ), approvalPost, approvalLink) )
+ return string( );
++
++ // when 2FA is enabled, link doesn't start with 'http'
++ if ( approvalLink.compare(0, 4, "http") != 0 )
++ {
++ // STEP 3b: 2 Factor Authentication, pin code request
++
++ string loginChallengePost( approvalPost );
++ string loginChallengeLink( approvalLink );
++
++ libcmis::OAuth2AuthCodeProvider fallbackProvider = libcmis::SessionFactory::getOAuth2AuthCodeProvider( );
++ string pin( fallbackProvider( "", "", "" ) );
++
++ loginChallengeLink = "https://accounts.google.com" + loginChallengeLink;
++ loginChallengePost += "Pin=";
++ loginChallengePost += string( pin );
++
++ istringstream loginChallengeIs( loginChallengePost );
++ string loginChallengeRes;
++ try
++ {
++ // send a post with pin, receive the application consent page
++ loginChallengeRes = session->httpPostRequest ( loginChallengeLink, loginChallengeIs, CONTENT_TYPE )
++ ->getStream( )->str( );
++ }
++ catch ( const CurlException& e )
++ {
++ return string( );
++ }
++
++ approvalPost = string();
++ approvalLink = string();
++
++ if ( !parseResponse( loginChallengeRes. c_str( ), approvalPost, approvalLink) )
++ return string( );
++ }
++ else if( approvalLink.compare( "https://accounts.google.com/ServiceLoginAuth" ) == 0 )
++ {
++ // wrong password,
++ // unset OAuth2AuthCode Provider to avoid showing pin request again in the HttpSession::oauth2Authenticate
++ libcmis::SessionFactory::setOAuth2AuthCodeProvider( NULL );
++ return string( );
++ }
++
++ // STEP 4: allow libcmis to access google drive
+ approvalPost += "submit_access=true";
+
+ istringstream approvalIs( approvalPost );
+@@ -125,7 +186,7 @@ string OAuth2Providers::OAuth2Gdrive( HttpSession* session, const string& authUr
+ throw e.getCmisException( );
+ }
+
+- // STEP 3: Take the authentication code from the text bar
++ // Take the authentication code from the text bar
+ string code = parseCode( approvalRes.c_str( ) );
+
+ return code;
+@@ -216,6 +277,9 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
+ if ( doc == NULL ) return 0;
+ xmlTextReaderPtr reader = xmlReaderWalker( doc );
+ if ( reader == NULL ) return 0;
++
++ bool readInputField = false;
++
+ while ( true )
+ {
+ // Go to the next node, quit if not found
+@@ -227,15 +291,24 @@ int OAuth2Providers::parseResponse ( const char* response, string& post, string&
+ {
+ xmlChar* action = xmlTextReaderGetAttribute( reader,
+ BAD_CAST( "action" ));
++
++ // GDrive pin code page contains 3 forms.
++ // First form resends pin code, we need to omit its input fields.
++ // Also we mustn't parse action field from the 'select challenge' form.
+ if ( action != NULL )
+ {
+- if ( xmlStrlen(action) > 0)
++ if ( ( strcmp( (char*)action, "/signin/challenge" ) != 0 )
++ && ( strcmp( (char*)action, "/signin/selectchallenge" ) != 0 )
++ && xmlStrlen(action) > 0 )
++ {
+ link = string ( (char*) action);
++ readInputField = true;
++ }
+ xmlFree (action);
+ }
+ }
+ // Find input values
+- if ( !xmlStrcmp( nodeName, BAD_CAST( "input" ) ) )
++ if ( readInputField && !xmlStrcmp( nodeName, BAD_CAST( "input" ) ) )
+ {
+ xmlChar* name = xmlTextReaderGetAttribute( reader,
+ BAD_CAST( "name" ));
+