Search in sources :

Example 1 with OlmPkEncryption

use of org.matrix.olm.OlmPkEncryption in project matrix-android-sdk by matrix-org.

the class MediaScanRestClient method scanEncryptedFile.

/**
 * Scan an encrypted file.
 *
 * @param encryptedMediaScanBody the encryption information required to decrypt the content before scanning it.
 * @param callback               on success callback containing a MediaScanResult object
 */
public void scanEncryptedFile(final EncryptedMediaScanBody encryptedMediaScanBody, final ApiCallback<MediaScanResult> callback) {
    // Encrypt encryptedMediaScanBody if the server support it
    getServerPublicKey(new SimpleApiCallback<String>(callback) {

        @Override
        public void onSuccess(String serverPublicKey) {
            Call<MediaScanResult> request;
            // Encrypt the data, if antivirus server supports it
            if (!TextUtils.isEmpty(serverPublicKey)) {
                try {
                    OlmPkEncryption olmPkEncryption = new OlmPkEncryption();
                    olmPkEncryption.setRecipientKey(serverPublicKey);
                    String data = JsonUtility.getCanonicalizedJsonString(encryptedMediaScanBody);
                    OlmPkMessage message = olmPkEncryption.encrypt(data);
                    EncryptedMediaScanEncryptedBody encryptedMediaScanEncryptedBody = new EncryptedMediaScanEncryptedBody();
                    encryptedMediaScanEncryptedBody.encryptedBodyFileInfo = new EncryptedBodyFileInfo(message);
                    request = mApi.scanEncrypted(encryptedMediaScanEncryptedBody);
                } catch (OlmException e) {
                    // should not happen. Send the error to the caller
                    request = null;
                    callback.onUnexpectedError(e);
                }
            } else {
                // No public key on this server, do not encrypt data
                request = mApi.scanEncrypted(encryptedMediaScanBody);
            }
            if (request != null) {
                request.enqueue(new RestAdapterCallback<>("scanEncryptedFile", null, new SimpleApiCallback<MediaScanResult>(callback) {

                    @Override
                    public void onSuccess(MediaScanResult scanResult) {
                        callback.onSuccess(scanResult);
                    }

                    @Override
                    public void onMatrixError(MatrixError e) {
                        // Check whether the provided encrypted_body could not be decrypted.
                        if (e.mStatus == HttpURLConnection.HTTP_FORBIDDEN) {
                            MediaScanError mcsError;
                            try {
                                mcsError = JsonUtils.getGson(false).fromJson(e.mErrorBodyAsString, MediaScanError.class);
                            } catch (Exception exc) {
                                mcsError = null;
                            }
                            if (mcsError != null && MediaScanError.MCS_BAD_DECRYPTION.equals(mcsError.reason)) {
                                // The client should request again the public key of the server.
                                resetServerPublicKey();
                            }
                        }
                        super.onMatrixError(e);
                    }
                }, null));
            }
        }
    });
}
Also used : Call(retrofit2.Call) EncryptedBodyFileInfo(org.matrix.androidsdk.crypto.model.crypto.EncryptedBodyFileInfo) MediaScanError(org.matrix.androidsdk.rest.model.MediaScanError) RestAdapterCallback(org.matrix.androidsdk.rest.callback.RestAdapterCallback) OlmPkMessage(org.matrix.olm.OlmPkMessage) EncryptedMediaScanEncryptedBody(org.matrix.androidsdk.rest.model.EncryptedMediaScanEncryptedBody) OlmException(org.matrix.olm.OlmException) OlmException(org.matrix.olm.OlmException) MediaScanResult(org.matrix.androidsdk.rest.model.MediaScanResult) MatrixError(org.matrix.androidsdk.core.model.MatrixError) OlmPkEncryption(org.matrix.olm.OlmPkEncryption)

Example 2 with OlmPkEncryption

use of org.matrix.olm.OlmPkEncryption in project matrix-android-sdk by matrix-org.

the class MXMediaDownloadWorkerTask method doInBackground.

/**
 * Download and decode media in background.
 *
 * @param params
 * @return JsonElement if an error occurs
 */
@Override
protected JsonElement doInBackground(Void... params) {
    JsonElement jsonElementResult = null;
    MatrixError defaultError = new MatrixError();
    defaultError.errcode = MatrixError.UNKNOWN;
    try {
        URL url = new URL(mUrl);
        Log.d(LOG_TAG, "MXMediaDownloadWorkerTask " + this + " starts");
        mDownloadStats = new IMXMediaDownloadListener.DownloadStats();
        // don't known yet
        mDownloadStats.mEstimatedRemainingTime = -1;
        InputStream stream = null;
        int filelen = -1;
        HttpURLConnection connection = null;
        try {
            Proxy proxyConfig = mHsConfig.getProxyConfig();
            if (proxyConfig == null) {
                proxyConfig = Proxy.NO_PROXY;
            }
            connection = (HttpURLConnection) url.openConnection(proxyConfig);
            if (RestClient.getUserAgent() != null) {
                connection.setRequestProperty("User-Agent", RestClient.getUserAgent());
            }
            if (mHsConfig != null && connection instanceof HttpsURLConnection) {
                // Add SSL Socket factory.
                HttpsURLConnection sslConn = (HttpsURLConnection) connection;
                try {
                    Pair<SSLSocketFactory, X509TrustManager> pair = CertUtil.newPinnedSSLSocketFactory(mHsConfig);
                    sslConn.setSSLSocketFactory(pair.first);
                    sslConn.setHostnameVerifier(CertUtil.newHostnameVerifier(mHsConfig));
                } catch (Exception e) {
                    Log.e(LOG_TAG, "doInBackground SSL exception " + e.getMessage(), e);
                }
            }
            // add a timeout to avoid infinite loading display.
            float scale = (null != mNetworkConnectivityReceiver) ? mNetworkConnectivityReceiver.getTimeoutScale() : 1.0f;
            connection.setReadTimeout((int) (DOWNLOAD_TIME_OUT * scale));
            if (mIsAvScannerEnabled && null != mEncryptedFileInfo) {
                // POST the encryption info to let the av scanner decrypt and scan the content.
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
                connection.setDoOutput(true);
                connection.setUseCaches(false);
                EncryptedMediaScanBody encryptedMediaScanBody = new EncryptedMediaScanBody();
                encryptedMediaScanBody.encryptedFileInfo = mEncryptedFileInfo;
                String data = JsonUtility.getCanonicalizedJsonString(encryptedMediaScanBody);
                // Encrypt the data, if antivirus server supports it
                String publicServerKey = getAntivirusServerPublicKey();
                if (publicServerKey == null) {
                    // Error
                    throw new Exception("Unable to get public key");
                } else if (!TextUtils.isEmpty(publicServerKey)) {
                    OlmPkEncryption olmPkEncryption = new OlmPkEncryption();
                    olmPkEncryption.setRecipientKey(publicServerKey);
                    OlmPkMessage message = olmPkEncryption.encrypt(data);
                    EncryptedMediaScanEncryptedBody encryptedMediaScanEncryptedBody = new EncryptedMediaScanEncryptedBody();
                    encryptedMediaScanEncryptedBody.encryptedBodyFileInfo = new EncryptedBodyFileInfo(message);
                    data = JsonUtility.getCanonicalizedJsonString(encryptedMediaScanEncryptedBody);
                }
                // Else: no public key on this server, do not encrypt data
                OutputStream outputStream = connection.getOutputStream();
                try {
                    outputStream.write(data.getBytes("UTF-8"));
                } catch (Exception e) {
                    Log.e(LOG_TAG, "doInBackground Failed to serialize encryption info " + e.getMessage(), e);
                } finally {
                    outputStream.close();
                }
            }
            filelen = connection.getContentLength();
            stream = connection.getInputStream();
        } catch (Exception e) {
            Log.e(LOG_TAG, "bitmapForURL : fail to open the connection " + e.getMessage(), e);
            defaultError.error = e.getLocalizedMessage();
            // In case of 403, revert the key
            if (connection.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN && mMediaScanRestClient != null) {
                mMediaScanRestClient.resetServerPublicKey();
            }
            InputStream errorStream = connection.getErrorStream();
            if (null != errorStream) {
                try {
                    BufferedReader streamReader = new BufferedReader(new InputStreamReader(errorStream, "UTF-8"));
                    StringBuilder responseStrBuilder = new StringBuilder();
                    String inputStr;
                    while ((inputStr = streamReader.readLine()) != null) {
                        responseStrBuilder.append(inputStr);
                    }
                    jsonElementResult = new JsonParser().parse(responseStrBuilder.toString());
                } catch (Exception ee) {
                    Log.e(LOG_TAG, "bitmapForURL : Error parsing error " + ee.getMessage(), ee);
                }
            }
            // privacy
            // Log.d(LOG_TAG, "MediaWorkerTask " + mUrl + " does not exist");
            Log.d(LOG_TAG, "MediaWorkerTask an url does not exist");
            // (because the same url is used for all encrypted media when the av scanner is enabled).
            if (!mIsAvScannerEnabled || null == mEncryptedFileInfo) {
                synchronized (sUnreachableUrls) {
                    sUnreachableUrls.add(mUrl);
                }
            }
        }
        dispatchDownloadStart();
        // failed to open the remote stream without having exception
        if ((null == stream) && (null == jsonElementResult)) {
            jsonElementResult = new JsonParser().parse("Cannot open " + mUrl);
            // (because the same url is used for all encrypted media when the av scanner is enabled).
            if (!mIsAvScannerEnabled || null == mEncryptedFileInfo) {
                synchronized (sUnreachableUrls) {
                    sUnreachableUrls.add(mUrl);
                }
            }
        }
        // test if the download has not been cancelled
        if (!isDownloadCancelled() && (null == jsonElementResult)) {
            final long startDownloadTime = System.currentTimeMillis();
            String filename = buildFileName(mDownloadId, mMimeType) + ".tmp";
            FileOutputStream fos = new FileOutputStream(new File(mDirectoryFile, filename));
            mDownloadStats.mDownloadId = mDownloadId;
            mDownloadStats.mProgress = 0;
            mDownloadStats.mDownloadedSize = 0;
            mDownloadStats.mFileSize = filelen;
            mDownloadStats.mElapsedTime = 0;
            mDownloadStats.mEstimatedRemainingTime = -1;
            mDownloadStats.mBitRate = 0;
            // Publish progress every 100ms
            final Timer refreshTimer = new Timer();
            refreshTimer.scheduleAtFixedRate(new TimerTask() {

                @Override
                public void run() {
                    if (!mIsDone) {
                        updateAndPublishProgress(startDownloadTime);
                    }
                }
            }, new Date(), 100);
            try {
                byte[] buf = new byte[DOWNLOAD_BUFFER_READ_SIZE];
                int len;
                while (!isDownloadCancelled() && (len = stream.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                    mDownloadStats.mDownloadedSize += len;
                }
                if (!isDownloadCancelled()) {
                    mDownloadStats.mProgress = 100;
                }
            } catch (OutOfMemoryError outOfMemoryError) {
                Log.e(LOG_TAG, "doInBackground: out of memory", outOfMemoryError);
                defaultError.error = outOfMemoryError.getLocalizedMessage();
            } catch (Exception e) {
                Log.e(LOG_TAG, "doInBackground fail to read image " + e.getMessage(), e);
                defaultError.error = e.getLocalizedMessage();
            }
            mIsDone = true;
            close(stream);
            fos.flush();
            fos.close();
            refreshTimer.cancel();
            if ((null != connection) && (connection instanceof HttpsURLConnection)) {
                connection.disconnect();
            }
            // the file has been successfully downloaded
            if (mDownloadStats.mProgress == 100) {
                try {
                    File originalFile = new File(mDirectoryFile, filename);
                    String newFileName = buildFileName(mDownloadId, mMimeType);
                    File newFile = new File(mDirectoryFile, newFileName);
                    if (newFile.exists()) {
                        // Or you could throw here.
                        mApplicationContext.deleteFile(newFileName);
                    }
                    originalFile.renameTo(newFile);
                } catch (Exception e) {
                    Log.e(LOG_TAG, "doInBackground : renaming error " + e.getMessage(), e);
                    defaultError.error = e.getLocalizedMessage();
                }
            }
        }
        if (mDownloadStats.mProgress == 100) {
            Log.d(LOG_TAG, "The download " + this + " is done.");
        } else {
            if (null != jsonElementResult) {
                Log.d(LOG_TAG, "The download " + this + " failed : mErrorAsJsonElement " + jsonElementResult.toString());
            } else {
                Log.d(LOG_TAG, "The download " + this + " failed.");
            }
        }
    } catch (Exception e) {
        Log.e(LOG_TAG, "Unable to download media " + this, e);
        defaultError.error = e.getMessage();
    }
    // build a JSON from the error
    if (!TextUtils.isEmpty(defaultError.error)) {
        jsonElementResult = JsonUtils.getGson(false).toJsonTree(defaultError);
    }
    // remove the task from the loading one
    synchronized (sPendingDownloadById) {
        sPendingDownloadById.remove(mDownloadId);
    }
    return jsonElementResult;
}
Also used : EncryptedBodyFileInfo(org.matrix.androidsdk.crypto.model.crypto.EncryptedBodyFileInfo) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) EncryptedMediaScanEncryptedBody(org.matrix.androidsdk.rest.model.EncryptedMediaScanEncryptedBody) URL(java.net.URL) Proxy(java.net.Proxy) HttpURLConnection(java.net.HttpURLConnection) EncryptedMediaScanBody(org.matrix.androidsdk.rest.model.EncryptedMediaScanBody) TimerTask(java.util.TimerTask) SSLSocketFactory(javax.net.ssl.SSLSocketFactory) OlmPkEncryption(org.matrix.olm.OlmPkEncryption) JsonParser(com.google.gson.JsonParser) InputStreamReader(java.io.InputStreamReader) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) OlmPkMessage(org.matrix.olm.OlmPkMessage) FileNotFoundException(java.io.FileNotFoundException) Date(java.util.Date) Timer(java.util.Timer) JsonElement(com.google.gson.JsonElement) IMXMediaDownloadListener(org.matrix.androidsdk.listeners.IMXMediaDownloadListener) X509TrustManager(javax.net.ssl.X509TrustManager) FileOutputStream(java.io.FileOutputStream) BufferedReader(java.io.BufferedReader) MatrixError(org.matrix.androidsdk.core.model.MatrixError) File(java.io.File) HttpsURLConnection(javax.net.ssl.HttpsURLConnection)

Aggregations

MatrixError (org.matrix.androidsdk.core.model.MatrixError)2 EncryptedBodyFileInfo (org.matrix.androidsdk.crypto.model.crypto.EncryptedBodyFileInfo)2 EncryptedMediaScanEncryptedBody (org.matrix.androidsdk.rest.model.EncryptedMediaScanEncryptedBody)2 OlmPkEncryption (org.matrix.olm.OlmPkEncryption)2 OlmPkMessage (org.matrix.olm.OlmPkMessage)2 JsonElement (com.google.gson.JsonElement)1 JsonParser (com.google.gson.JsonParser)1 BufferedReader (java.io.BufferedReader)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1 FileOutputStream (java.io.FileOutputStream)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 OutputStream (java.io.OutputStream)1 HttpURLConnection (java.net.HttpURLConnection)1 Proxy (java.net.Proxy)1 URL (java.net.URL)1 Date (java.util.Date)1 Timer (java.util.Timer)1