diff options
author | Szymon Kłos <eszkadev@gmail.com> | 2016-05-15 00:52:50 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2016-05-16 07:24:23 +0000 |
commit | 511db54e95d02292417d7cd076e4bd6d50956d64 (patch) | |
tree | ab8b4d46a35b1c9cc52679e966e0786bd18ca916 /external | |
parent | 5e54d9e9bc856520808a446f20575e29a50d017b (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.mk | 1 | ||||
-rwxr-xr-x | external/libcmis/libcmis-google-2FA-implementation.patch | 156 |
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" )); + |