Android: QR Code - Error During Transport Update

I host passbolt on an Ubuntu 20.xx server using the source/script install.

Cannot get the QR code to scan returns an error each time. I got as far as guessing its a certificate error. (I presume).

Certbot/letsencrypt produces 4 keys, and I did try importing them to my android phone but that always returns a "a security key is required to install this certificate)

CERTIFICATES
============

I use certbot with Apache to generate self-signed certs.

it generates 4, cert, chain, fullchain and privkey, the latter two of which are refered to in the apache config

OTHER
======

Server is behind cloudflare. I have tried with both cloudflare proxy on and off

JWT Check
=========

dim@ubuntu:/var/www/passbolt/config/jwt$ openssl rsa -in /var/www/passbolt/config/jwt/jwt.key -check -noout
RSA key ok
dim@ubuntu:/var/www/passbolt/config/jwt$ if openssl rsa -in /var/www/passbolt/config/jwt/jwt.key -outform PEM -pubout 2>/dev/null | diff /var/www/passbolt/config/jwt/jwt.pem - > /dev/null; then echo "OK: JWT key matches with JWT pem"; else echo "NOT OK: JWT key and pem doesn't match"; fi
OK: JWT key matches with JWT pem

Apache Config (Included the suggest rewrite)

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName REMOVED
  DocumentRoot /var/www/passbolt/webroot/

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
        ErrorDocument 403 /403.html
        ErrorDocument 404 /404.html
        ErrorDocument 500 /500.html
        ErrorDocument 502 /502.html
        ErrorDocument 503 /503.html
        ErrorDocument 504 /504.html
  <Directory />
    Options FollowSymLinks
    AllowOverride All
  </Directory>

  <Directory /var/www/passbolt/>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>


Include /etc/letsencrypt/options-ssl-apache.conf

        <Location "/auth/verify.json">
        SecRuleRemoveById 200004 942100
</Location>

<Location "/import/resources.json">
        SecRuleRemoveById 942100
</Location>

<Location "/resources.json">
        SecRuleRemoveById 942100
</Location>

<LocationMatch "^/resources/.*">
        SecRuleRemoveById 911100 980130 942100
</LocationMatch>

<LocationMatch "^/users/.*">
        SecRuleRemoveById 911100
</LocationMatch>

<LocationMatch "^/setup/completeRecovery/.*\.json">
        SecRuleRemoveById 980130 911100 949110
</LocationMatch>

SSLCertificateFile /etc/letsencrypt/live/pass.dimspace.xyz/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/pass.dimspace.xyz/privkey.pem
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
  ServerName REMOVED
  DocumentRoot /var/www/passbolt/webroot/

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  <Directory />
    Options FollowSymLinks
    AllowOverride All
  </Directory>

  <Directory /var/www/passbolt/>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>

RewriteEngine on
# Some rewrite rules in this file were disabled on your HTTPS site,
# because they have the potential to create redirection loops.

# RewriteCond %{SERVER_NAME} =pass.dimspace.xyz
# RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

        SecRuleEngine DetectionOnly

</VirtualHost>
</IfModule>

Apache Test

dim@ubuntu:/etc/apache2/sites-available$ sudo apachectl configtest
Syntax OK

SSL Test

Checklist
[x ] I have read intro post: About the Installation Issues category
[x ] I have read the tutorials, help and searched for similar issues
[x ] I provide relevant information about my server (component names and versions, etc.)
[x ] I provide a copy of my logs and healthcheck
[x ] I describe the steps I have taken to trouble shoot the problem
[ x] I describe the steps on how to reproduce the issue

As an alternative I tried manually generating keys

openssl req -x509 \
    -newkey rsa:4096 \
    -days 120 \
    -subj "/C=LU/ST=Luxembourg/L=Esch-Sur-Alzette/O=Passbolt SA/OU=Passbolt IT Team/CN=pass.dimspace.xyz/" \
    -nodes \
    -addext "subjectAltName = DNS:pass.dimspace.xyz" \
    -keyout key.pem \
    -out cert.pem

Which creates

-rw-r–r-- 1 root root 2171 Sep 13 13:59 cert.pem
-rw------- 1 root root 3272 Sep 13 13:59 key.pem

(i chmod those to www-data)

Then changed my apache config

<LocationMatch "^/setup/completeRecovery/.*\.json">
        SecRuleRemoveById 980130 911100 949110
</LocationMatch>

#SSLCertificateFile /etc/letsencrypt/live/pass.dimspace.xyz/fullchain.pem
#SSLCertificateKeyFile /etc/letsencrypt/live/pass.dimspace.xyz/privkey.pem

SSLCertificateFile /var/www/passbolt/cert/cert.pem
SSLCertificateKeyFile /var/www/passbolt/cert/key.pem

But now I have invalid certificate with cloudflare, and no https if i turn proxy off

And in a final attempt, i rebuild a new apache.conf for passbolt, and generated new letencrypt certs.

copied those over to my phone, but they still insist “a security key is required to install this certificate”

So in conclusion.

Certbot generated - cannot import to my android phone

openssl generated - cloudflare and apache say i dont have a valid ssl certiicate

stumped :frowning:

might be making progress.

cloudflare was set to strict which was fine for letsencrypt certificates, but not for self signed.

generated key pair

root@ubuntu:/var/www/passbolt/cert# openssl req -x509 \
>     -newkey rsa:4096 \
>     -days 120 \
>     -subj "/C=GB/ST=England/L=Newcastle/O=Passbolt@Dimspace/OU=Dimspace/CN=pass.dimspace.xyz/" \
>     -nodes \
>     -addext "subjectAltName = DNS:pass.dimspace.xyz" \
>     -keyout key.pem \
>     -out cert.pem
Generating a RSA private key
..........................................................................................................++++
...................................................................++++
writing new private key to 'key.pem'
-rw-r--r-- 1 www-data www-data 2134 Sep 13 20:17 cert.pem
-rw------- 1 www-data www-data 3272 Sep 13 20:17 key.pem

FULL APACHE.CONF

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName pass.dimspace.xyz
  DocumentRoot /var/www/passbolt/webroot/

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
        ErrorDocument 403 /403.html
        ErrorDocument 404 /404.html
        ErrorDocument 500 /500.html
        ErrorDocument 502 /502.html
        ErrorDocument 503 /503.html
        ErrorDocument 504 /504.html
  <Directory />
    Options FollowSymLinks
    AllowOverride All
  </Directory>

  <Directory /var/www/passbolt/>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>


#Include /etc/letsencrypt/options-ssl-apache.conf

        <Location "/auth/verify.json">
        SecRuleRemoveById 200004 942100
</Location>

<Location "/import/resources.json">
        SecRuleRemoveById 942100
</Location>

<Location "/resources.json">
        SecRuleRemoveById 942100
</Location>

<LocationMatch "^/resources/.*">
        SecRuleRemoveById 911100 980130 942100
</LocationMatch>

<LocationMatch "^/users/.*">
        SecRuleRemoveById 911100
</LocationMatch>

<LocationMatch "^/setup/completeRecovery/.*\.json">
        SecRuleRemoveById 980130 911100 949110
</LocationMatch>


SSLCertificateFile /var/www/passbolt/cert/cert.pem
SSLCertificateKeyFile /var/www/passbolt/cert/key.pem

#SSLCertificateFile /etc/letsencrypt/live/pass.dimspace.xyz/fullchain.pem
#SSLCertificateKeyFile /etc/letsencrypt/live/pass.dimspace.xyz/privkey.pem

</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
  ServerName pass.dimspace.xyz
  DocumentRoot /var/www/passbolt/webroot/

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  <Directory />
    Options FollowSymLinks
    AllowOverride All
  </Directory>

  <Directory /var/www/passbolt/>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>

RewriteEngine on
# Some rewrite rules in this file were disabled on your HTTPS site,
# because they have the potential to create redirection loops.

# RewriteCond %{SERVER_NAME} =pass.dimspace.xyz
# RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

        SecRuleEngine DetectionOnly

</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
  ServerName pass.dimspace.xyz
  DocumentRoot /var/www/passbolt/webroot/

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  <Directory />
    Options FollowSymLinks
    AllowOverride All
  </Directory>

  <Directory /var/www/passbolt/>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>

RewriteEngine on
# Some rewrite rules in this file were disabled on your HTTPS site,
# because they have the potential to create redirection loops.

# RewriteCond %{SERVER_NAME} =pass.dimspace.xyz
# RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

        SecRuleEngine DetectionOnly

</VirtualHost>
</IfModule>

RESULT
======

  • Can now connect to the site and cloudflare doesn’t throw invalid certificate at me (But if i set cloudflareto dns only firefox throws a self-signed warning at me)

  • have successfully imported the key into my android device

+ still get “error during transfer” error :frowning:

oh and

dim@ubuntu:/var/www/passbolt$ sudo su -s /bin/bash -c "/var/www/passbolt/bin/cake passbolt version" www-data
[sudo] password for dim: 

     ____                  __          ____  
    / __ \____  _____ ____/ /_  ____  / / /_ 
   / /_/ / __ `/ ___/ ___/ __ \/ __ \/ / __/ 
  / ____/ /_/ (__  |__  ) /_/ / /_/ / / /    
 /_/    \__,_/____/____/_.___/\____/_/\__/   

 Open source password manager for teams
-------------------------------------------------------------------------------
Passbolt CE 4.2.0
Cakephp 4.4.15

and the log from my phone:

Device: HONOR WDY-LX1
Android 13 (33)
Passbolt 1.15.0-24

20:38:09 → PUT https://pass.dimspace.xyz/mobile/transfers/91371003-21d7-405d-bb40-36c9a1f6ecb8/6c8c0da7-793e-4f27-b772-b2bc37432ecc.json h2 (41-byte body)
20:38:09 ← 404 https://pass.dimspace.xyz/mobile/transfers/91371003-21d7-405d-bb40-36c9a1f6ecb8/6c8c0da7-793e-4f27-b772-b2bc37432ecc.json (181ms, unknown-length body)
20:38:09 retrofit2.HttpException: HTTP 404
at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:53)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:161)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)

retrofit2.HttpException: HTTP 404
at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:53)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:161)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)
20:38:09 Encountered a non-standard backend error response
20:38:09 There was an error during checking if MFA is required
java.lang.NullPointerException: null cannot be cast to non-null type kotlin.collections.Map<kotlin.String, kotlin.collections.List<kotlin.String>>
at com.passbolt.mobile.android.core.networking.ErrorHeaderMapper.checkMfaRequired(ErrorHeaderMapper.kt:68)
at com.passbolt.mobile.android.core.networking.ResponseHandler.checkIfMfaRequired(ResponseHandler.kt:76)
at com.passbolt.mobile.android.core.networking.ResponseHandler.handleException(ResponseHandler.kt:50)
at com.passbolt.mobile.android.passboltapi.registration.MobileTransferRepository.turnPage(MobileTransferRepository.kt:97)
at com.passbolt.mobile.android.passboltapi.registration.MobileTransferRepository$turnPage$1.invokeSuspend(Unknown Source:16)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

java.lang.NullPointerException: null cannot be cast to non-null type kotlin.collections.Map<kotlin.String, kotlin.collections.List<kotlin.String>>
at com.passbolt.mobile.android.core.networking.ErrorHeaderMapper.checkMfaRequired(ErrorHeaderMapper.kt:68)
at com.passbolt.mobile.android.core.networking.ResponseHandler.checkIfMfaRequired(ResponseHandler.kt:76)
at com.passbolt.mobile.android.core.networking.ResponseHandler.handleException(ResponseHandler.kt:50)
at com.passbolt.mobile.android.passboltapi.registration.MobileTransferRepository.turnPage(MobileTransferRepository.kt:97)
at com.passbolt.mobile.android.passboltapi.registration.MobileTransferRepository$turnPage$1.invokeSuspend(Unknown Source:16)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
20:38:09 There was an error during transfer update
retrofit2.HttpException: HTTP 404
at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:53)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:161)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)

retrofit2.HttpException: HTTP 404
at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:53)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:161)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)

Exact same problem here : the https request to /mobile/transfers returns a 404.

Any idea ?