From c1bc96da0125666ca30cda40516cec789a226084 Mon Sep 17 00:00:00 2001 From: Thomas Nordquist Date: Tue, 26 Mar 2019 14:42:28 +0100 Subject: [PATCH] Add support to validate self-signed certificates --- app/src/actions/ConnectionManager.ts | 55 ++++++++++++++++++- .../AdvancedConnectionSettings.tsx | 51 ++++++++++++++++- app/src/model/ConnectionOptions.ts | 11 +++- backend/src/DataSource/MqttSource.ts | 2 + package.json | 2 +- 5 files changed, 115 insertions(+), 6 deletions(-) diff --git a/app/src/actions/ConnectionManager.ts b/app/src/actions/ConnectionManager.ts index 0a687d9..4230f54 100644 --- a/app/src/actions/ConnectionManager.ts +++ b/app/src/actions/ConnectionManager.ts @@ -1,9 +1,13 @@ import { AppState } from '../reducers' import { clearLegacyConnectionOptions, loadLegacyConnectionOptions } from '../model/LegacyConnectionSettings' -import { ConnectionOptions, createEmptyConnection, makeDefaultConnections } from '../model/ConnectionOptions' +import { ConnectionOptions, createEmptyConnection, makeDefaultConnections, CertificateParameters } from '../model/ConnectionOptions' import { default as persistantStorage, StorageIdentifier } from '../PersistantStorage' import { Dispatch } from 'redux' import { showError } from './Global' +import { remote } from 'electron' +import * as fs from 'fs' +import * as path from 'path' + import { ActionTypes, Action, @@ -33,6 +37,53 @@ export const loadConnectionSettings = () => async (dispatch: Dispatch, getS } } +export const selectCertificate = (connectionId: string) => async (dispatch: Dispatch, getState: () => AppState) => { + try { + const certificate = await openCertificate() + console.log(certificate) + dispatch(updateConnection(connectionId, { + selfSignedCertificate: certificate, + })) + } catch (error) { + console.log(error) + dispatch(showError(error)) + } +} + +async function openCertificate(): Promise { + const rejectReasons = { + noCertificateSelected: 'No certificate selected', + certificateSizeDoesNotMatch: 'Certificate size larger/smaller then expected.', + } + + return new Promise((resolve, reject) => { + remote.dialog.showOpenDialog({ properties: ['openFile'], securityScopedBookmarks: true }, (filePaths?: string[]) => { + const selectedFile = filePaths && filePaths[0] + if (!selectedFile) { + reject(rejectReasons.noCertificateSelected) + return + } + + fs.readFile(selectedFile, (error, data) => { + if (error) { + reject(error) + return + } + + if (data.length > 16_384 || data.length < 128) { + reject(rejectReasons.certificateSizeDoesNotMatch) + return + } + + resolve({ + data: data.toString('base64'), + name: path.basename(selectedFile), + }) + }) + }) + }) +} + export const saveConnectionSettings = () => async (dispatch: Dispatch, getState: () => AppState) => { try { console.log('store settings') @@ -42,7 +93,7 @@ export const saveConnectionSettings = () => async (dispatch: Dispatch, getS } } -export const updateConnection = (connectionId: string, changeSet: any): Action => ({ +export const updateConnection = (connectionId: string, changeSet: Partial): Action => ({ connectionId, changeSet, type: ActionTypes.CONNECTION_MANAGER_UPDATE_CONNECTION, diff --git a/app/src/components/ConnectionSetup/AdvancedConnectionSettings.tsx b/app/src/components/ConnectionSetup/AdvancedConnectionSettings.tsx index 8590a7c..378353d 100644 --- a/app/src/components/ConnectionSetup/AdvancedConnectionSettings.tsx +++ b/app/src/components/ConnectionSetup/AdvancedConnectionSettings.tsx @@ -2,6 +2,7 @@ import * as React from 'react' import Add from '@material-ui/icons/Add' import Delete from '@material-ui/icons/Delete' import Undo from '@material-ui/icons/Undo' +import Lock from '@material-ui/icons/Lock' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' import { connectionManagerActions } from '../../actions' @@ -16,7 +17,10 @@ import { List, ListItem, ListItemText, + Tooltip, + Typography, } from '@material-ui/core' +import ClearAdornment from '../helper/ClearAdornment'; interface Props { connection: ConnectionOptions @@ -74,7 +78,7 @@ class ConnectionSettings extends React.Component { - + { /> +
+ + + + {this.renderCertificateInfo()} +
+
+