Merge branch 'master' into patch-1

This commit is contained in:
Jim Grisham 2021-11-04 16:08:33 -04:00
commit dc6ddbc246
246 changed files with 3408 additions and 2257 deletions

View File

@ -1,36 +0,0 @@
---
name: Bug report
about: Please fill in this template as much as you can, to help us, help you.
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
Please do not link to image hosting sites, as these can be ephemeral. Instead, attach them to the issue.
**Desktop (please complete the following information):**
- OS: [e.g. Windows]
- Barrier version [e.g 2.3.3]
**Additional context**
Add any other context about the problem here.

79
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,79 @@
name: Bug Report
description: File a bug report (for questions, ideas & support, use the Discussions tab, or IRC for quick answers, but make sure to stay on the channel!)
labels: [bug, triage]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see! Screenshots are also helpful - please attach to the issue (when created), rather than linking to image hosting sites.
validations:
required: true
- type: dropdown
id: version
attributes:
label: Version
description: What version of Barrier are you running?
options:
- v2.0.0-RC1
- v2.0.0-RC2
- v2.0.0
- v2.1.1
- v2.1.2
- v2.3.0
- v2.3.1
- v2.3.2-alpha
- v2.3.2
- v2.3.3
- From Git HEAD or commit (specify below)
validations:
required: true
- type: input
id: git-commit-if
attributes:
label: Git commit hash (if applicable)
description: "When building Barrier from Git, what commit hash did you checkout from?"
placeholder: b0c0b42b
validations:
required: false
- type: textarea
id: pkg-mgr-origin
attributes:
label: If applicable, where did you install Barrier from?
description: This includes Snaps, Flatpaks, and self-built executables.
validations:
required: false
- type: dropdown
id: os
attributes:
label: What OSes are you seeing the problem on? (Check all that apply)
multiple: true
options:
- Linux
- Windows
- macOS
validations:
required: true
- type: textarea
id: os-version
attributes:
label: What OS versions are you using?
description: This applies to both client(s) and the server.
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: textarea
id: misc-info
attributes:
label: Any other information
description: Please enter any other information we should know, if applicable.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

3
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,3 @@
## Contributor Checklist:
* [ ] I have created a file in the `doc/newsfragments` directory (and read the `README.md` in that directory)

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "ext/gmock"] [submodule "ext/gmock"]
path = ext/gmock path = ext/gmock
url = https://github.com/google/googlemock.git url = https://github.com/google/googlemock.git
[submodule "ext/gulrak-filesystem"]
path = ext/gulrak-filesystem
url = https://github.com/gulrak/filesystem

View File

@ -2,6 +2,6 @@
# Barrier build parameters # Barrier build parameters
# #
BARRIER_VERSION_MAJOR = 2 BARRIER_VERSION_MAJOR = 2
BARRIER_VERSION_MINOR = 3 BARRIER_VERSION_MINOR = 4
BARRIER_VERSION_PATCH = 3 BARRIER_VERSION_PATCH = 0
BARRIER_VERSION_STAGE = release BARRIER_VERSION_STAGE = release

View File

@ -91,7 +91,6 @@ if (UNIX)
check_function_exists (poll HAVE_POLL) check_function_exists (poll HAVE_POLL)
check_function_exists (sigwait HAVE_POSIX_SIGWAIT) check_function_exists (sigwait HAVE_POSIX_SIGWAIT)
check_function_exists (strftime HAVE_STRFTIME) check_function_exists (strftime HAVE_STRFTIME)
check_function_exists (vsnprintf HAVE_VSNPRINTF)
check_function_exists (inet_aton HAVE_INET_ATON) check_function_exists (inet_aton HAVE_INET_ATON)
# For some reason, the check_function_exists macro doesn't detect # For some reason, the check_function_exists macro doesn't detect
@ -292,6 +291,9 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
list (APPEND libs Wtsapi32 Userenv Wininet comsuppw Shlwapi) list (APPEND libs Wtsapi32 Userenv Wininet comsuppw Shlwapi)
add_definitions ( add_definitions (
/DSYSAPI_WIN32=1
/DWINAPI_MSWINDOWS=1
/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING=1 # tr1 is used from gtest and gmock
/DWIN32 /DWIN32
/D_WINDOWS /D_WINDOWS
/D_CRT_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS
@ -300,6 +302,8 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
) )
endif() endif()
include_directories("${CMAKE_SOURCE_DIR}/ext/gulrak-filesystem/include")
# #
# OpenSSL # OpenSSL
# #
@ -317,10 +321,21 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
${OPENSSL_ROOT}/lib/ssleay32.lib ${OPENSSL_ROOT}/lib/ssleay32.lib
) )
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_program(APT_PROGRAM "apt")
find_program(BREW_PROGRAM "brew") find_program(BREW_PROGRAM "brew")
find_program(PORT_PROGRAM "port") find_program(PORT_PROGRAM "port")
if (IS_DIRECTORY /opt/local AND PORT_PROGRAM) if (IS_DIRECTORY /opt/procursus AND APT_PROGRAM)
# procursus/apt
set (OPENSSL_ROOT /opt/procursus)
include_directories (BEFORE SYSTEM ${OPENSSL_ROOT}/include)
set (OPENSSL_LIBS
${OPENSSL_ROOT}/lib/libssl.a
${OPENSSL_ROOT}/lib/libcrypto.a
)
elseif (IS_DIRECTORY /opt/local AND PORT_PROGRAM)
# macports # macports
set (OPENSSL_ROOT /opt/local) set (OPENSSL_ROOT /opt/local)
@ -335,6 +350,16 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
include_directories (BEFORE SYSTEM ${OPENSSL_ROOT}/include) include_directories (BEFORE SYSTEM ${OPENSSL_ROOT}/include)
set (OPENSSL_LIBS
${OPENSSL_ROOT}/lib/libssl.a
${OPENSSL_ROOT}/lib/libcrypto.a
)
elseif (IS_DIRECTORY /opt/homebrew/opt/openssl AND BREW_PROGRAM)
# brew
set (OPENSSL_ROOT /opt/homebrew/opt/openssl)
include_directories (BEFORE SYSTEM ${OPENSSL_ROOT}/include)
set (OPENSSL_LIBS set (OPENSSL_LIBS
${OPENSSL_ROOT}/lib/libssl.a ${OPENSSL_ROOT}/lib/libssl.a
${OPENSSL_ROOT}/lib/libcrypto.a ${OPENSSL_ROOT}/lib/libcrypto.a

59
LICENSE
View File

@ -286,3 +286,62 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -123,7 +123,7 @@ __Q: Is it possible to use Barrier on Mac OS X / OS X versions prior to 10.12?__
**Q: After loading my configuration on the client the field 'Server IP' is still empty!** **Q: After loading my configuration on the client the field 'Server IP' is still empty!**
> A: Edit your configuration to include the servers ip adress manually with > A: Edit your configuration to include the server's ip address manually with
> >
>``` >```
>(...) >(...)

59
RELEASING.md Normal file
View File

@ -0,0 +1,59 @@
Creating a release
==================
This document is documentation intednded for maintainers of Barrier.
It documents the release process of Barrier.
Step 1: Setup environment variables
-----------------------------------
Setup the following environment variable that will be used throughout the rest of the steps.
export VERSION=X.Y.Z
Step 2: Release notes PR
------------------------
Open a new branch (e.g. `release`) and run the following:
towncrier --version ${VERSION} --date `date -u +%F`
This collects the release notes using the `towncrier` tool. Please commit the collected release
notes afterwards.
Certain file names are not properly supported by the `towncrier` tool and it ignores them.
Check `newsfragments` directory for any forgotten release notes
Step 3: Merge the release notes PR
----------------------------------
Step 4: Push git tag
--------------------
Pull the merge commit created on the `master` branch during the step 2.
Create a tag:
git tag -s v${VERSION} -m v${VERSION}
Push the tag:
git push origin master --tags
Step 5: Draft a new release on Github
-------------------------------------
Go to https://github.com/buildbot/buildbot/releases and draft a new release.
Use git tag as the title of the release: `vX.Y.Z`.
Use the release notes generated by the `towncrier` tool as the description of the releases.
Upload the artifacts created by Azure pipelines as the binaries of the release. The following
artifacts should be uploaded to Github:
- the Barrier-X.Y.Z-release.dmg created by the oldest Mac OS task (artifact name is
"Mac Release Disk Image and App XYZ").
- the BarrierSetup-X.Y.Z-release.exe (artifact name is Windows Release Installer).

View File

@ -65,8 +65,6 @@ jobs:
- job: LinuxBuild - job: LinuxBuild
strategy: strategy:
matrix: matrix:
ubuntu-16.04:
imageName: 'ubuntu-16.04'
ubuntu-18.04: ubuntu-18.04:
imageName: 'ubuntu-18.04' imageName: 'ubuntu-18.04'
ubuntu-20.04: ubuntu-20.04:
@ -83,13 +81,22 @@ jobs:
- job: MacBuild - job: MacBuild
displayName: Mac Build displayName: Mac Build
pool:
vmImage: 'macOS-10.14'
strategy: strategy:
matrix: matrix:
Release: big-sur-Release:
imageName: "macOS-11"
B_BUILD_TYPE: Release B_BUILD_TYPE: Release
BARRIER_VERSION_STAGE: Release BARRIER_VERSION_STAGE: Release
catalina-Release:
imageName: "macOS-10.15"
B_BUILD_TYPE: Release
BARRIER_VERSION_STAGE: Release
mojave-Release:
imageName: "macOS-10.14"
B_BUILD_TYPE: Release
BARRIER_VERSION_STAGE: Release
pool:
vmImage: $(imageName)
variables: variables:
VERBOSE: 1 VERBOSE: 1
TERM: xterm-256color TERM: xterm-256color
@ -107,4 +114,4 @@ jobs:
condition: eq(variables['B_BUILD_TYPE'], 'Release') condition: eq(variables['B_BUILD_TYPE'], 'Release')
inputs: inputs:
pathtoPublish: build/bundle pathtoPublish: build/bundle
artifactName: Mac Release Disk Image and App artifactName: Mac Release Disk Image and App $(imageName)

View File

@ -1,8 +1,7 @@
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
New-Item -Force -ItemType Directory -Path ".\deps\" New-Item -Force -ItemType Directory -Path ".\deps\"
$Wc = New-Object System.Net.WebClient Invoke-WebRequest 'https://github.com/nelsonjchen/mDNSResponder/releases/download/v2019.05.08.1/x64_RelWithDebInfo.zip' -OutFile 'deps\BonjourSDKLike.zip' ;
$Wc.DownloadFile('https://github.com/nelsonjchen/mDNSResponder/releases/download/v2019.05.08.1/x64_RelWithDebInfo.zip', 'deps\BonjourSDKLike.zip') ;
Write-Output 'Downloaded BonjourSDKLike Zip' Write-Output 'Downloaded BonjourSDKLike Zip'
Write-Output 'Unzipping BonjourSDKLike Zip' Write-Output 'Unzipping BonjourSDKLike Zip'
Remove-Item -Recurse -Force -ErrorAction Ignore .\deps\BonjourSDKLike Remove-Item -Recurse -Force -ErrorAction Ignore .\deps\BonjourSDKLike

View File

@ -6,8 +6,7 @@ $qt_version = '5.13.0'
New-Item -Force -ItemType Directory -Path ".\deps\" New-Item -Force -ItemType Directory -Path ".\deps\"
Write-Output 'Downloading QLI Installer' Write-Output 'Downloading QLI Installer'
$Wc = New-Object System.Net.WebClient Invoke-WebRequest "https://github.com/nelsonjchen/qli-installer/archive/v$qli_install_version.zip" -OutFile '.\deps\qli-installer.zip' ;
$Wc.DownloadFile("https://github.com/nelsonjchen/qli-installer/archive/v$qli_install_version.zip", '.\deps\qli-installer.zip') ;
Write-Output 'Downloaded QLI Installer' Write-Output 'Downloaded QLI Installer'
Write-Output 'Extracting QLI Installer' Write-Output 'Extracting QLI Installer'

View File

@ -41,8 +41,7 @@ if ERRORLEVEL 1 goto failed
cd build cd build
cmake -G "%cmake_gen%" -A x64 -D CMAKE_BUILD_TYPE=%B_BUILD_TYPE% -D CMAKE_PREFIX_PATH="%B_QT_FULLPATH%" -D DNSSD_LIB="%B_BONJOUR%\Lib\x64\dnssd.lib" -D QT_VERSION=%B_QT_VER% .. cmake -G "%cmake_gen%" -A x64 -D CMAKE_BUILD_TYPE=%B_BUILD_TYPE% -D CMAKE_PREFIX_PATH="%B_QT_FULLPATH%" -D DNSSD_LIB="%B_BONJOUR%\Lib\x64\dnssd.lib" -D QT_VERSION=%B_QT_VER% ..
if ERRORLEVEL 1 goto failed if ERRORLEVEL 1 goto failed
echo @msbuild barrier.sln /p:Platform="x64" /p:Configuration=%B_BUILD_TYPE% /m %B_BUILD_OPTIONS% > make.bat cmake --build . --config %B_BUILD_TYPE%
call make.bat
if ERRORLEVEL 1 goto failed if ERRORLEVEL 1 goto failed
if exist bin\Debug ( if exist bin\Debug (
copy %B_QT_FULLPATH%\bin\Qt5Cored.dll bin\Debug\ > NUL copy %B_QT_FULLPATH%\bin\Qt5Cored.dll bin\Debug\ > NUL
@ -65,7 +64,7 @@ if exist bin\Debug (
mkdir bin\Release\platforms mkdir bin\Release\platforms
copy %B_QT_FULLPATH%\plugins\platforms\qwindows.dll bin\Release\platforms\ > NUL copy %B_QT_FULLPATH%\plugins\platforms\qwindows.dll bin\Release\platforms\ > NUL
) else ( ) else (
echo Remember to copy supporting binaries and confiuration files! echo Remember to copy supporting binaries and configuration files!
) )
echo Build completed successfully echo Build completed successfully

View File

@ -1,10 +1,10 @@
#!/bin/sh #!/bin/sh
cd "$(dirname $0)" || exit 1 cd "$(dirname "$0")" || exit 1
# some environments have cmake v2 as 'cmake' and v3 as 'cmake3' # some environments have cmake v2 as 'cmake' and v3 as 'cmake3'
# check for cmake3 first then fallback to just cmake # check for cmake3 first then fallback to just cmake
B_CMAKE=`type cmake3 2>/dev/null` B_CMAKE=`type cmake3 2>/dev/null`
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
B_CMAKE=`echo $B_CMAKE | cut -d' ' -f3` B_CMAKE=`echo "$B_CMAKE" | cut -d' ' -f3`
else else
B_CMAKE=cmake B_CMAKE=cmake
fi fi
@ -26,7 +26,7 @@ B_CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=$B_BUILD_TYPE $B_CMAKE_FLAGS"
rm -rf build rm -rf build
mkdir build || exit 1 mkdir build || exit 1
cd build || exit 1 cd build || exit 1
echo Starting Barrier $B_BUILD_TYPE build... echo "Starting Barrier $B_BUILD_TYPE build..."
$B_CMAKE $B_CMAKE_FLAGS .. || exit 1 $B_CMAKE $B_CMAKE_FLAGS .. || exit 1
make || exit 1 make || exit 1
echo "Build completed successfully" echo "Build completed successfully"

View File

@ -1,8 +1,8 @@
cmake_minimum_required (VERSION 3.4) cmake_minimum_required (VERSION 3.4)
set (BARRIER_VERSION_MAJOR 2) set (BARRIER_VERSION_MAJOR 2)
set (BARRIER_VERSION_MINOR 3) set (BARRIER_VERSION_MINOR 4)
set (BARRIER_VERSION_PATCH 3) set (BARRIER_VERSION_PATCH 0)
set (BARRIER_VERSION_STAGE "release") set (BARRIER_VERSION_STAGE "release")
# #

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# Use the same verbose variable as CMake # Use the same verbose variable as CMake
[ "$VERBOSE" == "1" ] && set -x [ "$VERBOSE" = "1" ] && set -x
# Exit on unset variables or pipe errors # Exit on unset variables or pipe errors
set -uo pipefail set -uo pipefail
@ -14,10 +14,10 @@ B_BARRIERC="Barrier.app/Contents/MacOS/barrierc"
B_BARRIERS="Barrier.app/Contents/MacOS/barriers" B_BARRIERS="Barrier.app/Contents/MacOS/barriers"
# Colorized output # Colorized output
function info() { tput bold; echo "$@" ; tput sgr0 ;} info() { tput bold; echo "$@"; tput sgr0 ; }
function error() { tput bold; tput setaf 1; echo "$@"; tput sgr0 ; } error() { tput bold; tput setaf 1; echo "$@"; tput sgr0 ; }
function success() { tput bold; tput setaf 2; echo "$@"; tput sgr0 ; } success() { tput bold; tput setaf 2; echo "$@"; tput sgr0 ; }
function warn() { tput bold; tput setaf 3; echo "$@"; tput sgr0 ; } warn() { tput bold; tput setaf 3; echo "$@"; tput sgr0 ; }
info "Checking for bundle contents" info "Checking for bundle contents"
if [ ! -d "Barrier.app/Contents" ]; then if [ ! -d "Barrier.app/Contents" ]; then
@ -40,7 +40,7 @@ if which -s port ; then
info "MacPorts found, searching for macdeployqt" info "MacPorts found, searching for macdeployqt"
DEPLOYQT="$(port contents qt5-qttools | grep --only --max-count 1 '/.*macdeployqt')" DEPLOYQT="$(port contents qt5-qttools | grep --only --max-count 1 '/.*macdeployqt')"
if [ ! -x "$DEPLOYQT" ]; then if [ ! -x "$DEPLOYQT" ]; then
error Please install package qt5-qttools error "Please install package qt5-qttools"
exit 1 exit 1
fi fi
fi fi
@ -50,13 +50,13 @@ if which -s brew ; then
info "Homebrew found, searching for macdeployqt" info "Homebrew found, searching for macdeployqt"
DEPLOYQT="$(brew list qt@5 | grep --only '/.*macdeployqt' | head -1)" DEPLOYQT="$(brew list qt@5 | grep --only '/.*macdeployqt' | head -1)"
if [ ! -x "$DEPLOYQT" ]; then if [ ! -x "$DEPLOYQT" ]; then
error Please install package qt error "Please install package qt"
exit 1 exit 1
fi fi
fi fi
# Use macdeployqt to include libraries and create dmg # Use macdeployqt to include libraries and create dmg
if [ "$B_BUILDTYPE" == "Release" ]; then if [ "$B_BUILDTYPE" = "Release" ]; then
info "Building Release disk image (dmg)" info "Building Release disk image (dmg)"
"$DEPLOYQT" Barrier.app -dmg \ "$DEPLOYQT" Barrier.app -dmg \
-executable="$B_BARRIERC" \ -executable="$B_BARRIERC" \

View File

@ -1,30 +1,30 @@
#!/bin/sh #!/bin/sh
# add warning for users running manually # add warning for users running manually
function warn() { tput bold; tput setaf 3; echo "$@"; tput sgr0 ; } warn() { tput bold; tput setaf 3; echo "$@"; tput sgr0 ; }
warn "The scripts build_installer.sh and reref_dylibs.sh have been deprecated." warn "The scripts build_installer.sh and reref_dylibs.sh have been deprecated."
warn "Please use build_dist.sh instead to deploy using macdeployqt" warn "Please use build_dist.sh instead to deploy using macdeployqt"
# change this to rename the installer package # change this to rename the installer package
B_DMG="Barrier-@BARRIER_VERSION@.dmg" B_DMG="Barrier-@BARRIER_VERSION@.dmg"
cd "$( dirname '$0' )" cd "$( dirname "$0" )"
OWNDIR="$( pwd )" OWNDIR="$( pwd )"
B_REREF_SCRIPT="$OWNDIR/reref_dylibs.sh" B_REREF_SCRIPT="$OWNDIR/reref_dylibs.sh"
if [ ! -x $B_REREF_SCRIPT ]; then if [ ! -x "$B_REREF_SCRIPT" ]; then
echo Missing script: $B_REREF_SCRIPT echo "Missing script: $B_REREF_SCRIPT"
exit 1 exit 1
fi fi
# remove any old copies so there's no confusion about whether this # remove any old copies so there's no confusion about whether this
# process completes successfully or not # process completes successfully or not
rm -rf temp.dmg $B_DMG rm -rf temp.dmg "$B_DMG"
cd Barrier.app/Contents 2>/dev/null cd Barrier.app/Contents 2>/dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo Please make sure that the build completed successfully echo "Please make sure that the build completed successfully"
echo before trying to create the installer. echo "before trying to create the installer."
exit 1 exit 1
fi fi
@ -77,7 +77,7 @@ hdiutil create -size 64m -fs HFS+ -volname "Barrier" temp.dmg || exit 1
hdiutil attach temp.dmg -mountpoint mnt || exit 1 hdiutil attach temp.dmg -mountpoint mnt || exit 1
cp -r Barrier.app mnt/ || exit 1 cp -r Barrier.app mnt/ || exit 1
hdiutil detach mnt || exit 1 hdiutil detach mnt || exit 1
hdiutil convert temp.dmg -format UDZO -o $B_DMG || exit 1 hdiutil convert temp.dmg -format UDZO -o "$B_DMG" || exit 1
rm temp.dmg rm temp.dmg
echo "dmg $B_DMB created successfully" echo "dmg $B_DMG created successfully"

View File

@ -5,28 +5,28 @@ B_TARGET=$1
if [ "x$B_TARGET" = "x" ]; then if [ "x$B_TARGET" = "x" ]; then
# add warning for users running manually # add warning for users running manually
function warn() { tput bold; tput setaf 3; echo "$@"; tput sgr0 ; } warn() { tput bold; tput setaf 3; echo "$@"; tput sgr0 ; }
warn "The scripts build_installer.sh and reref_dylibs.sh have been deprecated." warn "The scripts build_installer.sh and reref_dylibs.sh have been deprecated."
warn "Please use build_dist.sh instead to deploy using macdeployqt" warn "Please use build_dist.sh instead to deploy using macdeployqt"
echo Which binary needs to be re-referenced? echo "Which binary needs to be re-referenced?"
exit 1 exit 1
fi fi
cd $(dirname $B_TARGET) || exit 1 cd "$(dirname "$B_TARGET")" || exit 1
# where to find non-system libraries relative to target's directory. # where to find non-system libraries relative to target's directory.
# the vast majority of the time this should be empty # the vast majority of the time this should be empty
B_REL_PATH=$2 B_REL_PATH=$2
# we're in target's directory now. trim off the path # we're in target's directory now. trim off the path
B_TARGET=$(basename $B_TARGET) B_TARGET=$(basename "$B_TARGET")
# get a list of non-system libraries and make local copies # get a list of non-system libraries and make local copies
B_LIBS=$(otool -XL $B_TARGET | awk '{ print $1 }' | grep -Ev '^(/usr/lib|/System)') B_LIBS=$(otool -XL "$B_TARGET" | awk '{ print $1 }' | grep -Ev '^(/usr/lib|/System)')
[ $? -ne 0 ] && exit 1 [ $? -ne 0 ] && exit 1
for B_LIB in $B_LIBS; do for B_LIB in $B_LIBS; do
B_LIB_NAME=$(basename $B_LIB) B_LIB_NAME=$(basename "$B_LIB")
# otool reports barrier as "barrier:" which fails self-reference test below # otool reports barrier as "barrier:" which fails self-reference test below
B_LIB_NAME=${B_LIB_NAME//:} B_LIB_NAME=${B_LIB_NAME//:}
@ -34,16 +34,16 @@ for B_LIB in $B_LIBS; do
[ "$B_TARGET" = "$B_LIB_NAME" ] && continue [ "$B_TARGET" = "$B_LIB_NAME" ] && continue
B_DST=${B_REL_PATH}${B_LIB_NAME} B_DST=${B_REL_PATH}${B_LIB_NAME}
if [ ! -e $B_DST ]; then if [ ! -e "$B_DST" ]; then
cp $B_LIB $B_DST || exit 1 cp "$B_LIB" "$B_DST" || exit 1
chmod u+rw $B_DST || exit 1 chmod u+rw "$B_DST" || exit 1
# recursively call this script on libraries purposefully not passing # recursively call this script on libraries purposefully not passing
# $B_REL_PATH so that it is only used explicitly # $B_REL_PATH so that it is only used explicitly
$0 $B_DST $0 "$B_DST"
fi fi
# adjust the target's metadata to point to the local copy # adjust the target's metadata to point to the local copy
# rather than the system-wide copy which would only exist on # rather than the system-wide copy which would only exist on
# a development machine # a development machine
install_name_tool -change $B_LIB @loader_path/$B_DST $B_TARGET || exit 1 install_name_tool -change "$B_LIB" "@loader_path/$B_DST" "$B_TARGET" || exit 1
done done

View File

@ -47,7 +47,7 @@ section: links
end end
# The aliases section is to map the full names of the computers to their logical names used in the screens section # The aliases section is to map the full names of the computers to their logical names used in the screens section
# One way to find the actual name of a comptuer is to run hostname from a command window # One way to find the actual name of a computer is to run hostname from a command window
section: aliases section: aliases
# Laptop is actually known as John-Smiths-MacBook-3.local # Laptop is actually known as John-Smiths-MacBook-3.local
John-Smiths-MacBook-3.local: John-Smiths-MacBook-3.local:

View File

@ -1,5 +1,5 @@
.\" See UpdateManpages.txt about modification of this file. Most of it was generated by help2man 1.47.8. .\" See UpdateManpages.txt about modification of this file. Most of it was generated by help2man 1.47.8.
.TH BARRIERC "1" "November 2019" "barrierc 2.3.3-release" "User Commands" .TH BARRIERC "1" "November 2019" "barrierc 2.4.0-release" "User Commands"
.SH NAME .SH NAME
barrierc \- Barrier Keyboard/Mouse Client barrierc \- Barrier Keyboard/Mouse Client
.SH SYNOPSIS .SH SYNOPSIS

View File

@ -1,5 +1,5 @@
.\" See UpdateManpages.txt about modification of this file. Most of it was generated by help2man 1.47.8. .\" See UpdateManpages.txt about modification of this file. Most of it was generated by help2man 1.47.8.
.TH BARRIERS "1" "November 2019" "barriers 2.3.3-release" "User Commands" .TH BARRIERS "1" "November 2019" "barriers 2.4.0-release" "User Commands"
.SH NAME .SH NAME
barriers \- Barrier Keyboard/Mouse Server barriers \- Barrier Keyboard/Mouse Server
.SH SYNOPSIS .SH SYNOPSIS

View File

@ -1,12 +1,13 @@
This is the directory for news snippets used by towncrier: https://github.com/twisted/towncrier This is the directory for release note fragments processed by
[towncrier](https://github.com/hawkowl/towncrier).
When changing code in a way that's visible to an end user please make a new file in this directory. When making a user-visible change create a file in this directory and it will be automatically be
It will be removed and integrated into release notes document upon a release of a new version of included into the release note document when the next release is published.
Barrier.
towncrier has a few standard types of news fragments, signified by the file extension. These are: The file extension specifies the type of a change. The following are currently supported:
.feature: Signifying a new feature. - .feature: a new feature.
.bugfix: Signifying a bug fix. - .bugfix: a bug fix.
.doc: Signifying a documentation improvement. - .security: a fix for security issue.
.removal: Signifying a deprecation or removal of public API. - .doc: a documentation improvement.
- .removal: a deprecation or removal of functionality.

View File

@ -1 +0,0 @@
Fix build failure on mips*el and riscv64 architecture.

View File

@ -1 +0,0 @@
Fixed reading of configuration on Windows when the paths contain non-ASCII characters (https://github.com/debauchee/barrier/issues/976, https://github.com/debauchee/barrier/issues/974, https://github.com/debauchee/barrier/issues/444).

View File

@ -1 +0,0 @@
Added `--drop-target` option that improves drag and drop support on Windows when Barrier is being run as a portable app.

View File

@ -0,0 +1,2 @@
Fix wrong encoding for text copied between Linux and Windows
(https://github.com/debauchee/barrier/issues/1037, https://github.com/debauchee/barrier/issues/1137).

View File

@ -1 +0,0 @@
Map more X11 clipboard MIME types to corresponding converters (https://github.com/debauchee/barrier/issues/344).

View File

@ -0,0 +1 @@
Fixed build on GCC 11.2 (https://github.com/debauchee/barrier/issues/1366).

View File

@ -1 +0,0 @@
Implemented a configuration option for Server GUI auto-start.

View File

@ -1 +0,0 @@
Fixed setup of multiple actions associated with a hotkey.

View File

@ -1 +0,0 @@
Fixed setup of hotkeys with special characters such as comma and semicolon (https://github.com/debauchee/barrier/issues/778).

View File

@ -1 +0,0 @@
Made it possible to use keyboard instead of mouse to modify screen layout.

View File

@ -1 +0,0 @@
Added support for keyboard backlight media keys

View File

@ -1 +0,0 @@
Added support for Eisu_toggle and Muhenkan keys

View File

@ -1 +0,0 @@
Fixed transfer of non-ASCII characters coming from a Windows server in certain cases (https://github.com/debauchee/barrier/issues/527).

View File

@ -1 +0,0 @@
Added `--profile-dir` option that allows to select custom profile directory.

View File

@ -1 +0,0 @@
Barrier will now regenerate server certificate if it's invalid instead of failing to launch (https://github.com/debauchee/barrier/issues/802)

View File

@ -1 +0,0 @@
Added support for additional keys on Sun Microsystems USB keyboards (https://github.com/debauchee/barrier/issues/784).

View File

@ -1 +0,0 @@
Updated Chinese translation.

View File

@ -1 +0,0 @@
Updated Slovak translation.

View File

@ -1 +0,0 @@
Theme icons are now preferred to icons distributed together with Barrier (https://github.com/debauchee/barrier/issues/471).

View File

@ -1 +0,0 @@
Fixed incorrect setup of Barrier service path on Windows.

View File

@ -0,0 +1,98 @@
Release notes
=============
[comment]: <> (towncrier release notes start)
Barrier `2.4.0` ( `2021-11-01` )
================================
Security fixes
--------------
- Barrier now supports client identity verification (fixes CVE-2021-42072, CVE-2021-42073).
Previously a malicious client could connect to Barrier server without any authentication and
send application-level messages. This made the attack surface of Barrier significantly larger.
Additionally, in case the malicious client got possession of a valid screen name by brute forcing
or other means it could modify the clipboard contents of the server.
To support seamless upgrades from older versions of Barrier this is currently disabled by default.
The feature can be enabled in the settings dialog. If enabled, older clients of Barrier will be
rejected.
- Barrier now uses SHA256 fingerprints for establishing security of encrypted SSL connections.
After upgrading client to new version the existing server fingerprint will need to be approved
again. Client and server will show both SHA1 and SHA256 server fingerprints to allow
interoperability with older versions of Barrier.
All of the above security issues have been reported by Matthias Gerstner who was really helpful
resolving them.
Bug fixes
---------
- Fixed build failure on mips*el and riscv64 architecture.
- Fixed reading of configuration on Windows when the paths contain non-ASCII characters
(https://github.com/debauchee/barrier/issues/976, https://github.com/debauchee/barrier/issues/974,
https://github.com/debauchee/barrier/issues/444).
- Barrier no longer uses openssl CLI tool for any operations and hooks into the openssl library directly.
- More X11 clipboard MIME types have been mapped to corresponding converters (https://github.com/debauchee/barrier/issues/344).
- Fixed setup of multiple actions associated with a hotkey.
- Fixed setup of hotkeys with special characters such as comma and semicolon
(https://github.com/debauchee/barrier/issues/778).
- Fixed transfer of non-ASCII characters coming from a Windows server in certain cases
(https://github.com/debauchee/barrier/issues/527).
- Barrier will now regenerate server certificate if it's invalid instead of failing to launch
(https://github.com/debauchee/barrier/issues/802)
- Added support for additional keys on Sun Microsystems USB keyboards
(https://github.com/debauchee/barrier/issues/784).
- Updated Chinese translation.
- Updated Slovak translation.
- Theme icons are now preferred to icons distributed together with Barrier
(https://github.com/debauchee/barrier/issues/471).
- Fixed incorrect setup of Barrier service path on Windows.
Features
--------
- Added `--drop-target` option that improves drag and drop support on Windows when Barrier is
being run as a portable app.
- The `--enable-crypto` command line option has been made the default to reduce chances of
accidental security mishaps when configuring Barrier from command line.
A new `--disable-crypto` command line option has been added to explicitly disable encryption.
- Added support for randomart images for easier comparison of SSL certificate fingerprints.
The algorithm is identical to what OpenSSH uses.
- Implemented a configuration option for Server GUI auto-start.
- Made it possible to use keyboard instead of mouse to modify screen layout.
- Added support for keyboard backlight media keys
- Added support for Eisu_toggle and Muhenkan keys
- Added `--profile-dir` option that allows to select custom profile directory.
Barrier `2.3.4` ( `2021-11-01` )
================================
Security fixes
--------------
- Barrier will now correctly close connections when the app-level handshake fails (fixes CVE-2021-42075).
Previously repeated failing connections would leak file descriptors leading to Barrier being unable
to receive new connections from clients.
- Barrier will now enforce a maximum length of input messages (fixes CVE-2021-42076).
Previously it was possible for a malicious client or server to send excessive length messages
leading to denial of service by resource exhaustion.
- Fixed a bug which caused Barrier to crash when disconnecting a TCP session just after sending
Hello message (fixes CVE-2021-42074).
This bug allowed an unauthenticated attacker to crash Barrier with only network access.
All of the above security issues have been reported by Matthias Gerstner who was really helpful
resolving them.
Bug fixes
---------
- Fixed a bug in SSL implementation that caused invalid data occasionally being sent to clients
under heavy load.

View File

@ -0,0 +1,37 @@
{% for section, _ in sections|dictsort(by='key') %}
{% set underline = "-" %}
{% if section %}
{{section}}
{{ underline * section|length }}{% set underline = "-" %}
{% endif %}
{% if sections[section] %}
{% for category, val in definitions|dictsort if category in sections[section]%}
{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category]|dictsort(by='value') %}
- {{ text }}
{% endfor %}
{% else %}
- {{ sections[section][category]['']|sort|join(', ') }}
{% endif %}
{% if sections[section][category]|length == 0 %}
No significant changes.
{% else %}
{% endif %}
{% endfor %}
{% else %}
No significant changes.
{% endif %}
{% endfor %}

1
ext/gulrak-filesystem Submodule

@ -0,0 +1 @@
Subproject commit 614bbe87b80435d87ab8791564370e0c1d13627d

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Checks if directory exists, otherwise asks to install package. # Checks if directory exists, otherwise asks to install package.
function check_dir_exists() { check_dir_exists() {
local path=$1 local path=$1
local package=$2 local package=$2
@ -11,7 +11,7 @@ function check_dir_exists() {
fi fi
} }
if [ ! $BARRIER_BUILD_ENV ]; then if [ -z "$BARRIER_BUILD_ENV" ]; then
check_dir_exists '/Applications/Xcode.app' 'Xcode' check_dir_exists '/Applications/Xcode.app' 'Xcode'
printf "Modifying environment for Barrier build...\n" printf "Modifying environment for Barrier build...\n"
@ -30,17 +30,14 @@ if [ ! $BARRIER_BUILD_ENV ]; then
elif command -v brew; then elif command -v brew; then
printf "Detected Homebrew\n" printf "Detected Homebrew\n"
QT_PATH=$(brew --prefix qt@5) QT_PATH=$(brew --prefix qt@5)
OPENSSL_PATH=$(brew --prefix openssl)
check_dir_exists "$QT_PATH" 'qt' check_dir_exists "$QT_PATH" 'qt5'
check_dir_exists "$OPENSSL_PATH" 'openssl'
export BARRIER_BUILD_BREW=1 export BARRIER_BUILD_BREW=1
export CMAKE_PREFIX_PATH="$QT_PATH:$CMAKE_PREFIX_PATH" export CMAKE_PREFIX_PATH="/opt/procursus:$QT_PATH:$CMAKE_PREFIX_PATH"
export LD_LIBRARY_PATH="$OPENSSL_PATH/lib:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH="/opt/procursus/lib:$LD_LIBRARY_PATH"
export CPATH="$OPENSSL_PATH/include:$CPATH" export CPATH="/opt/procursus/include:$CPATH"
export PKG_CONFIG_PATH="$OPENSSL_PATH/lib/pkgconfig:$PKG_CONFIG_PATH" export PKG_CONFIG_PATH="/opt/procursus/lib/pkgconfig:$PKG_CONFIG_PATH"
else else
printf "Neither Homebrew nor Macports is installed. Can't get dependency paths\n" printf "Neither Homebrew nor Macports is installed. Can't get dependency paths\n"
exit 1 exit 1

View File

@ -1,4 +1,4 @@
Thank you for chosing Barrier! Thank you for choosing Barrier!
https://github.com/debauchee/barrier/ https://github.com/debauchee/barrier/
Barrier allows you to share your keyboard and mouse between computers over a network. Barrier allows you to share your keyboard and mouse between computers over a network.

View File

@ -5,6 +5,5 @@ Comment=Keyboard and mouse sharing solution
Exec=barrier Exec=barrier
Icon=barrier Icon=barrier
Terminal=false Terminal=false
Categories=Utility;DesktopUtility; Categories=Utility;RemoteAccess;
Keywords=keyboard;mouse;sharing;network;share; Keywords=keyboard;mouse;sharing;network;share;

View File

@ -94,9 +94,6 @@
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} #cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
/* Define to 1 if you have the `vsnprintf` function. */
#cmakedefine HAVE_VSNPRINTF ${HAVE_VSNPRINTF}
/* Define to 1 if you have the <wchar.h> header file. */ /* Define to 1 if you have the <wchar.h> header file. */
#cmakedefine HAVE_WCHAR_H ${HAVE_WCHAR_H} #cmakedefine HAVE_WCHAR_H ${HAVE_WCHAR_H}

View File

@ -1,10 +1,10 @@
#!/bin/sh #!/bin/sh
ICNS_BASE=../dist/macos/bundle/Barrier.app/Contents/Resources ICNS_BASE=../dist/macos/bundle/Barrier.app/Contents/Resources
if ! which magick >/dev/null 2>&1; then if ! which magick >/dev/null 2>&1; then
echo "Need ImageMagic for this" echo "Need ImageMagick for this"
exit 10 exit 10
fi fi
cd $(dirname $0) || exit $? cd "$(dirname "$0")" || exit $?
if [ ! -r barrier.png ]; then if [ ! -r barrier.png ]; then
echo "Use inkscape (or another vector graphics editor) to create barrier.png from barrier.svg first" echo "Use inkscape (or another vector graphics editor) to create barrier.png from barrier.svg first"
exit 10 exit 10
@ -12,11 +12,11 @@ fi
rm -rf work || exit $? rm -rf work || exit $?
mkdir -p work || exit $? mkdir -p work || exit $?
for s in 16 24 32 48 64 128 256 512 1024; do for s in 16 24 32 48 64 128 256 512 1024; do
magick convert barrier.png -resize ${s}x${s} -depth 8 work/${s}.png || exit $? magick convert barrier.png -resize "${s}x${s}" -depth 8 "work/${s}.png" || exit $?
done done
# windows icon # windows icon
magick convert work/{16,24,32,48,64,128}.png barrier.png barrier.ico || exit $? magick convert work/{16,24,32,48,64,128}.png barrier.png barrier.ico || exit $?
# macos icon # macos icon
png2icns $ICNS_BASE/Barrier.icns work/{16,32,256,512,1024}.png || exit $? png2icns "$ICNS_BASE/Barrier.icns" work/{16,32,256,512,1024}.png || exit $?
rm -rf work rm -rf work
echo Done echo Done

View File

@ -1,65 +0,0 @@
#
# Barrier OpenSSL configuration file.
# Used for generation of certificate requests.
#
dir = .
[ca]
default_ca = CA_default
[CA_default]
serial = $dir/serial
database = $dir/certindex.txt
new_certs_dir = $dir/certs
certificate = $dir/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match
[policy_match]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[req]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = md5 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
0.organizationName_default = My Company
localityName_default = My Town
stateOrProvinceName_default = State or Providence
countryName_default = US
[v3_ca]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[v3_req]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash

View File

@ -20,4 +20,3 @@ add_subdirectory(barriers)
if (WIN32) if (WIN32)
add_subdirectory(barrierd) add_subdirectory(barrierd)
endif() endif()

View File

@ -46,4 +46,3 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install (TARGETS barrierc DESTINATION bin) install (TARGETS barrierc DESTINATION bin)
endif() endif()

View File

@ -66,4 +66,3 @@ createTaskBarReceiver(const BufferedLogOutputter* logBuffer, IEventQueue* events
{ {
return new OSXClientTaskBarReceiver(logBuffer, events); return new OSXClientTaskBarReceiver(logBuffer, events);
} }

View File

@ -73,7 +73,7 @@ BEGIN
VALUE "ProductName", "Barrier" VALUE "ProductName", "Barrier"
VALUE "ProductVersion", BARRIER_VERSION VALUE "ProductVersion", BARRIER_VERSION
VALUE "OriginalFilename", "barrierd.exe" VALUE "OriginalFilename", "barrierd.exe"
VALUE "FileDescription", "Open source KVM software deamon" VALUE "FileDescription", "Open source KVM software daemon"
VALUE "InternalName", "barrierd" VALUE "InternalName", "barrierd"
END END
END END

View File

@ -46,5 +46,3 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install (TARGETS barriers DESTINATION bin) install (TARGETS barriers DESTINATION bin)
endif() endif()

View File

@ -29,7 +29,7 @@ set(GUI_SOURCE_FILES
src/CommandProcess.cpp src/CommandProcess.cpp
src/DataDownloader.cpp src/DataDownloader.cpp
src/DisplayIsValid.cpp src/DisplayIsValid.cpp
src/Fingerprint.cpp src/FingerprintAcceptDialog.cpp
src/HotkeyDialog.cpp src/HotkeyDialog.cpp
src/IpcClient.cpp src/IpcClient.cpp
src/Ipc.cpp src/Ipc.cpp
@ -70,7 +70,6 @@ set(GUI_HEADER_FILES
src/DataDownloader.h src/DataDownloader.h
src/DisplayIsValid.h src/DisplayIsValid.h
src/ElevateMode.h src/ElevateMode.h
src/Fingerprint.h
src/HotkeyDialog.h src/HotkeyDialog.h
src/IpcClient.h src/IpcClient.h
src/Ipc.h src/Ipc.h
@ -106,6 +105,7 @@ set(GUI_UI_FILES
src/AboutDialogBase.ui src/AboutDialogBase.ui
src/ActionDialogBase.ui src/ActionDialogBase.ui
src/AddClientDialogBase.ui src/AddClientDialogBase.ui
src/FingerprintAcceptDialog.ui
src/HotkeyDialogBase.ui src/HotkeyDialogBase.ui
src/LogWindowBase.ui src/LogWindowBase.ui
src/MainWindowBase.ui src/MainWindowBase.ui
@ -131,7 +131,7 @@ add_executable (barrier WIN32
include_directories (./src) include_directories (./src)
target_link_libraries (barrier Qt5::Core Qt5::Widgets Qt5::Network ${OPENSSL_LIBS}) target_link_libraries(barrier net base io Qt5::Core Qt5::Widgets Qt5::Network ${OPENSSL_LIBS})
target_compile_definitions (barrier PRIVATE -DBARRIER_VERSION_STAGE="${BARRIER_VERSION_STAGE}") target_compile_definitions (barrier PRIVATE -DBARRIER_VERSION_STAGE="${BARRIER_VERSION_STAGE}")
target_compile_definitions (barrier PRIVATE -DBARRIER_REVISION="${BARRIER_REVISION}") target_compile_definitions (barrier PRIVATE -DBARRIER_REVISION="${BARRIER_REVISION}")

View File

@ -40,4 +40,3 @@ class AboutDialog : public QDialog, public Ui::AboutDialogBase
}; };
#endif #endif

View File

@ -164,4 +164,3 @@ QTextStream& operator<<(QTextStream& outStream, const Action& action)
return outStream; return outStream;
} }

View File

@ -158,6 +158,8 @@ void AppConfig::loadSettings()
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt()); m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool(); m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool();
m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool(); m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool();
// TODO: set default value of requireClientCertificate to true on Barrier 2.5.0
m_RequireClientCertificate = settings().value("requireClientCertificate", false).toBool();
m_AutoHide = settings().value("autoHide", false).toBool(); m_AutoHide = settings().value("autoHide", false).toBool();
m_AutoStart = settings().value("autoStart", false).toBool(); m_AutoStart = settings().value("autoStart", false).toBool();
m_MinimizeToTray = settings().value("minimizeToTray", false).toBool(); m_MinimizeToTray = settings().value("minimizeToTray", false).toBool();
@ -181,6 +183,7 @@ void AppConfig::saveSettings()
settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode)); settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode));
settings().setValue("autoConfigPrompted", m_AutoConfigPrompted); settings().setValue("autoConfigPrompted", m_AutoConfigPrompted);
settings().setValue("cryptoEnabled", m_CryptoEnabled); settings().setValue("cryptoEnabled", m_CryptoEnabled);
settings().setValue("requireClientCertificate", m_RequireClientCertificate);
settings().setValue("autoHide", m_AutoHide); settings().setValue("autoHide", m_AutoHide);
settings().setValue("autoStart", m_AutoStart); settings().setValue("autoStart", m_AutoStart);
settings().setValue("minimizeToTray", m_MinimizeToTray); settings().setValue("minimizeToTray", m_MinimizeToTray);
@ -225,6 +228,10 @@ void AppConfig::setCryptoEnabled(bool e) { m_CryptoEnabled = e; }
bool AppConfig::getCryptoEnabled() const { return m_CryptoEnabled; } bool AppConfig::getCryptoEnabled() const { return m_CryptoEnabled; }
void AppConfig::setRequireClientCertificate(bool e) { m_RequireClientCertificate = e; }
bool AppConfig::getRequireClientCertificate() const { return m_RequireClientCertificate; }
void AppConfig::setAutoHide(bool b) { m_AutoHide = b; } void AppConfig::setAutoHide(bool b) { m_AutoHide = b; }
bool AppConfig::getAutoHide() { return m_AutoHide; } bool AppConfig::getAutoHide() { return m_AutoHide; }

View File

@ -91,6 +91,9 @@ class AppConfig: public QObject
void setCryptoEnabled(bool e); void setCryptoEnabled(bool e);
bool getCryptoEnabled() const; bool getCryptoEnabled() const;
void setRequireClientCertificate(bool e);
bool getRequireClientCertificate() const;
void setAutoHide(bool b); void setAutoHide(bool b);
bool getAutoHide(); bool getAutoHide();
@ -132,6 +135,7 @@ protected:
ElevateMode m_ElevateMode; ElevateMode m_ElevateMode;
bool m_AutoConfigPrompted; bool m_AutoConfigPrompted;
bool m_CryptoEnabled; bool m_CryptoEnabled;
bool m_RequireClientCertificate = false;
bool m_AutoHide; bool m_AutoHide;
bool m_AutoStart; bool m_AutoStart;
bool m_MinimizeToTray; bool m_MinimizeToTray;

View File

@ -44,4 +44,3 @@ const char* BaseConfig::m_SwitchCornerNames[] =
"bottom-left", "bottom-left",
"bottom-right" "bottom-right"
}; };

View File

@ -30,35 +30,34 @@ CommandProcess::CommandProcess(QString cmd, QStringList arguments, QString input
QString CommandProcess::run() QString CommandProcess::run()
{ {
QProcess process; QProcess process;
QString standardOutput, standardError;
process.setReadChannel(QProcess::StandardOutput); process.setReadChannel(QProcess::StandardOutput);
process.start(m_Command, m_Arguments); process.start(m_Command, m_Arguments);
bool success = process.waitForStarted(); bool success = process.waitForStarted();
QString output, error;
if (success) if (success)
{ {
if (!m_Input.isEmpty()) { if (!m_Input.isEmpty()) {
process.write(m_Input.toLocal8Bit()); process.write(m_Input.toStdString().c_str());
} }
if (process.waitForFinished()) { if (process.waitForFinished()) {
standardOutput = QString::fromLocal8Bit(process.readAllStandardOutput().trimmed()); output = process.readAllStandardOutput().trimmed();
standardError = QString::fromLocal8Bit(process.readAllStandardError().trimmed()); error = process.readAllStandardError().trimmed();
} }
} }
int code = process.exitCode(); int code = process.exitCode();
if (!standardError.isEmpty() || !success || code != 0) if (!error.isEmpty() || !success || code != 0)
{ {
throw std::runtime_error( throw std::runtime_error(
std::string(
QString("Code: %1\nError: %2") QString("Code: %1\nError: %2")
.arg(process.exitCode()) .arg(process.exitCode())
.arg(standardError.isEmpty() ? "Unknown" : standardError) .arg(error.isEmpty() ? "Unknown" : error)
.toLocal8Bit().constData())); .toStdString());
} }
emit finished(); emit finished();
return standardOutput; return output;
} }

View File

@ -1,144 +0,0 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2015-2016 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Fingerprint.h"
#include "QUtility.h"
#include <QDir>
#include <QTextStream>
static const char kDirName[] = "SSL/Fingerprints";
static const char kLocalFilename[] = "Local.txt";
static const char kTrustedServersFilename[] = "TrustedServers.txt";
static const char kTrustedClientsFilename[] = "TrustedClients.txt";
Fingerprint::Fingerprint(const QString& filename)
{
m_Filename = filename;
}
void Fingerprint::trust(const QString& fingerprintText, bool append)
{
Fingerprint::persistDirectory();
QIODevice::OpenMode openMode;
if (append) {
openMode = QIODevice::Append;
}
else {
openMode = QIODevice::WriteOnly;
}
QFile file(filePath());
if (file.open(openMode))
{
QTextStream out(&file);
out << fingerprintText << "\n";
file.close();
}
}
bool Fingerprint::fileExists() const
{
QString dirName = Fingerprint::directoryPath();
if (!QDir(dirName).exists()) {
return false;
}
QFile file(filePath());
return file.exists();
}
bool Fingerprint::isTrusted(const QString& fingerprintText)
{
QStringList list = readList();
for (QString trusted : list) {
if (trusted == fingerprintText) {
return true;
}
}
return false;
}
QStringList Fingerprint::readList(const int readTo)
{
QStringList list;
QString dirName = Fingerprint::directoryPath();
if (!QDir(dirName).exists()) {
return list;
}
QFile file(filePath());
if (file.open(QIODevice::ReadOnly))
{
QTextStream in(&file);
while (!in.atEnd())
{
list.append(in.readLine());
if (list.size() == readTo) {
break;
}
}
file.close();
}
return list;
}
QString Fingerprint::readFirst()
{
QStringList list = readList(1);
return list.at(0);
}
QString Fingerprint::filePath() const
{
QString dir = Fingerprint::directoryPath();
return QString("%1/%2").arg(dir).arg(m_Filename);
}
void Fingerprint::persistDirectory()
{
QDir dir(Fingerprint::directoryPath());
if (!dir.exists()) {
dir.mkpath(".");
}
}
QString Fingerprint::directoryPath()
{
return QString("%1/%2")
.arg(profilePath())
.arg(kDirName);
}
Fingerprint Fingerprint::local()
{
return Fingerprint(kLocalFilename);
}
Fingerprint Fingerprint::trustedServers()
{
return Fingerprint(kTrustedServersFilename);
}
Fingerprint Fingerprint::trustedClients()
{
return Fingerprint(kTrustedClientsFilename);
}

View File

@ -1,42 +0,0 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2015-2016 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
class Fingerprint
{
public:
void trust(const QString& fingerprintText, bool append = true);
bool isTrusted(const QString& fingerprintText);
QStringList readList(const int readTo = -1);
QString readFirst();
QString filePath() const;
bool fileExists() const;
static Fingerprint local();
static Fingerprint trustedServers();
static Fingerprint trustedClients();
static QString directoryPath();
static void persistDirectory();
private:
Fingerprint(const QString& filename);
QString m_Filename;
};

View File

@ -0,0 +1,65 @@
/*
barrier -- mouse and keyboard sharing utility
Copyright (C) Barrier contributors
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
found in the file LICENSE that should have accompanied this file.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FingerprintAcceptDialog.h"
#include "ui_FingerprintAcceptDialog.h"
#include "net/SecureUtils.h"
FingerprintAcceptDialog::FingerprintAcceptDialog(QWidget *parent,
BarrierType type,
const barrier::FingerprintData& fingerprint_sha1,
const barrier::FingerprintData& fingerprint_sha256) :
QDialog(parent),
ui_{std::make_unique<Ui::FingerprintAcceptDialog>()}
{
ui_->setupUi(this);
if (type == BarrierType::Server) {
ui_->label_sha1->hide();
ui_->label_sha1_fingerprint_full->hide();
} else {
ui_->label_sha1_fingerprint_full->setText(
QString::fromStdString(barrier::format_ssl_fingerprint(fingerprint_sha1.data)));
}
ui_->label_sha256_fingerprint_full->setText(
QString::fromStdString(barrier::format_ssl_fingerprint_columns(fingerprint_sha256.data)));
ui_->label_sha256_fingerprint_randomart->setText(
QString::fromStdString(barrier::create_fingerprint_randomart(fingerprint_sha256.data)));
QString explanation;
if (type == BarrierType::Server) {
explanation = tr("This is a client fingerprint. You should compare this "
"fingerprint to the one on your client's screen. If the "
"two don't match exactly, then it's probably not the client "
"you're expecting (it could be a malicious user).\n\n"
"To automatically trust this fingerprint for future "
"connections, click Yes. To reject this fingerprint and "
"disconnect the client, click No.");
} else {
explanation = tr("This is a server fingerprint. You should compare this "
"fingerprint to the one on your server's screen. If the "
"two don't match exactly, then it's probably not the server "
"you're expecting (it could be a malicious user).\n\n"
"To automatically trust this fingerprint for future "
"connections, click Yes. To reject this fingerprint and "
"disconnect from the server, click No.");
}
ui_->label_explanation->setText(explanation);
}
FingerprintAcceptDialog::~FingerprintAcceptDialog() = default;

View File

@ -0,0 +1,45 @@
/*
barrier -- mouse and keyboard sharing utility
Copyright (C) Barrier contributors
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
found in the file LICENSE that should have accompanied this file.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BARRIER_GUI_FINGERPRINT_ACCEPT_DIALOG_H
#define BARRIER_GUI_FINGERPRINT_ACCEPT_DIALOG_H
#include "net/FingerprintData.h"
#include "barrier/BarrierType.h"
#include <QDialog>
#include <memory>
namespace Ui {
class FingerprintAcceptDialog;
}
class FingerprintAcceptDialog : public QDialog
{
Q_OBJECT
public:
explicit FingerprintAcceptDialog(QWidget* parent,
BarrierType type,
const barrier::FingerprintData& fingerprint_sha1,
const barrier::FingerprintData& fingerprint_sha256);
~FingerprintAcceptDialog() override;
private:
std::unique_ptr<Ui::FingerprintAcceptDialog> ui_;
};
#endif // BARRIER_GUI_FINGERPRINT_ACCEPT_DIALOG_H

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FingerprintAcceptDialog</class>
<widget class="QDialog" name="FingerprintAcceptDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Security question</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item row="6" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::No|QDialogButtonBox::Yes</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_sha1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SHA1 (deprecated, compare to old servers only)</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_explanation">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>10</number>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_sha1_fingerprint_full">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_title">
<property name="text">
<string>Do you trust this fingerprint?</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_sha256_fingerprint_randomart">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Courier</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_sha256_fingerprint_full">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_sha256">
<property name="text">
<string>SHA256:</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FingerprintAcceptDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FingerprintAcceptDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -104,12 +104,14 @@ void IpcClient::sendCommand(const QString& command, ElevateMode const elevate)
stream.writeRawData(kIpcMsgCommand, 4); stream.writeRawData(kIpcMsgCommand, 4);
QByteArray utf8Command = command.toUtf8(); std::string stdStringCommand = command.toStdString();
const char* charCommand = stdStringCommand.c_str();
int length = (int)strlen(charCommand);
char lenBuf[4]; char lenBuf[4];
intToBytes(utf8Command.size(), lenBuf, 4); intToBytes(length, lenBuf, 4);
stream.writeRawData(lenBuf, 4); stream.writeRawData(lenBuf, 4);
stream.writeRawData(utf8Command.constData(), utf8Command.size()); stream.writeRawData(charCommand, length);
char elevateBuf[1]; char elevateBuf[1];
// Refer to enum ElevateMode documentation for why this flag is mapped this way // Refer to enum ElevateMode documentation for why this flag is mapped this way

View File

@ -54,4 +54,3 @@ class KeySequence
}; };
#endif #endif

View File

@ -78,4 +78,3 @@ class KeySequenceWidget : public QPushButton
}; };
#endif #endif

View File

@ -20,17 +20,21 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "Fingerprint.h"
#include "AboutDialog.h" #include "AboutDialog.h"
#include "ServerConfigDialog.h" #include "ServerConfigDialog.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include "ZeroconfService.h" #include "ZeroconfService.h"
#include "DataDownloader.h" #include "DataDownloader.h"
#include "CommandProcess.h" #include "CommandProcess.h"
#include "FingerprintAcceptDialog.h"
#include "QUtility.h" #include "QUtility.h"
#include "ProcessorArch.h" #include "ProcessorArch.h"
#include "SslCertificate.h" #include "SslCertificate.h"
#include "ShutdownCh.h" #include "ShutdownCh.h"
#include "base/String.h"
#include "common/DataDirectories.h"
#include "net/FingerprintDatabase.h"
#include "net/SecureUtils.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -155,9 +159,22 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_pComboServerList->hide(); m_pComboServerList->hide();
m_pLabelPadlock->hide(); m_pLabelPadlock->hide();
frame_fingerprint_details->hide();
updateSSLFingerprint(); updateSSLFingerprint();
connect(toolbutton_show_fingerprint, &QToolButton::clicked, [this](bool checked)
{
m_fingerprint_expanded = !m_fingerprint_expanded;
if (m_fingerprint_expanded) {
frame_fingerprint_details->show();
toolbutton_show_fingerprint->setArrowType(Qt::ArrowType::UpArrow);
} else {
frame_fingerprint_details->hide();
toolbutton_show_fingerprint->setArrowType(Qt::ArrowType::DownArrow);
}
});
// resize window to smallest reasonable size // resize window to smallest reasonable size
resize(0, 0); resize(0, 0);
} }
@ -411,42 +428,58 @@ void MainWindow::checkConnected(const QString& line)
void MainWindow::checkFingerprint(const QString& line) void MainWindow::checkFingerprint(const QString& line)
{ {
QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)"); QRegExp fingerprintRegex(".*peer fingerprint \\(SHA1\\): ([A-F0-9:]+) \\(SHA256\\): ([A-F0-9:]+)");
if (!fingerprintRegex.exactMatch(line)) { if (!fingerprintRegex.exactMatch(line)) {
return; return;
} }
QString fingerprint = fingerprintRegex.cap(1); barrier::FingerprintData fingerprint_sha1 = {
if (Fingerprint::trustedServers().isTrusted(fingerprint)) { barrier::fingerprint_type_to_string(barrier::FingerprintType::SHA1),
barrier::string::from_hex(fingerprintRegex.cap(1).toStdString())
};
barrier::FingerprintData fingerprint_sha256 = {
barrier::fingerprint_type_to_string(barrier::FingerprintType::SHA256),
barrier::string::from_hex(fingerprintRegex.cap(2).toStdString())
};
bool is_client = barrier_type() == BarrierType::Client;
auto db_path = is_client
? barrier::DataDirectories::trusted_servers_ssl_fingerprints_path()
: barrier::DataDirectories::trusted_clients_ssl_fingerprints_path();
auto db_dir = db_path.parent_path();
if (!barrier::fs::exists(db_dir)) {
barrier::fs::create_directories(db_dir);
}
// We compare only SHA256 fingerprints, but show both SHA1 and SHA256 so that the users can
// still verify fingerprints on old Barrier servers. This way the only time when we are exposed
// to SHA1 vulnerabilities is when the user is reconnecting again.
barrier::FingerprintDatabase db;
db.read(db_path);
if (db.is_trusted(fingerprint_sha256)) {
return; return;
} }
static bool messageBoxAlreadyShown = false; static bool messageBoxAlreadyShown = false;
if (!messageBoxAlreadyShown) { if (!messageBoxAlreadyShown) {
if (is_client) {
stopBarrier(); stopBarrier();
}
messageBoxAlreadyShown = true; messageBoxAlreadyShown = true;
QMessageBox::StandardButton fingerprintReply = FingerprintAcceptDialog dialog{this, barrier_type(), fingerprint_sha1, fingerprint_sha256};
QMessageBox::information( if (dialog.exec() == QDialog::Accepted) {
this, tr("Security question"),
tr("Do you trust this fingerprint?\n\n"
"%1\n\n"
"This is a server fingerprint. You should compare this "
"fingerprint to the one on your server's screen. If the "
"two don't match exactly, then it's probably not the server "
"you're expecting (it could be a malicious user).\n\n"
"To automatically trust this fingerprint for future "
"connections, click Yes. To reject this fingerprint and "
"disconnect from the server, click No.")
.arg(fingerprint),
QMessageBox::Yes | QMessageBox::No);
if (fingerprintReply == QMessageBox::Yes) {
// restart core process after trusting fingerprint. // restart core process after trusting fingerprint.
Fingerprint::trustedServers().trust(fingerprint); db.add_trusted(fingerprint_sha256);
db.write(db_path);
if (is_client) {
startBarrier(); startBarrier();
} }
}
messageBoxAlreadyShown = false; messageBoxAlreadyShown = false;
} }
@ -515,8 +548,8 @@ void MainWindow::startBarrier()
#endif #endif
if (m_AppConfig->getCryptoEnabled()) { if (!m_AppConfig->getCryptoEnabled()) {
args << "--enable-crypto"; args << "--disable-crypto";
} }
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
@ -524,11 +557,11 @@ void MainWindow::startBarrier()
// launched the process (e.g. when launched with elevation). setting the // launched the process (e.g. when launched with elevation). setting the
// profile dir on launch ensures it uses the same profile dir is used // profile dir on launch ensures it uses the same profile dir is used
// no matter how its relaunched. // no matter how its relaunched.
args << "--profile-dir" << QString("\"%1\"").arg(profilePath()); args << "--profile-dir" << QString::fromStdString("\"" + barrier::DataDirectories::profile().u8string() + "\"");
#endif #endif
if ((barrierType() == barrierClient && !clientArgs(args, app)) if ((barrier_type() == BarrierType::Client && !clientArgs(args, app))
|| (barrierType() == barrierServer && !serverArgs(args, app))) || (barrier_type() == BarrierType::Server && !serverArgs(args, app)))
{ {
stopBarrier(); stopBarrier();
return; return;
@ -543,7 +576,7 @@ void MainWindow::startBarrier()
m_pLogWindow->startNewInstance(); m_pLogWindow->startNewInstance();
appendLogInfo("starting " + QString(barrierType() == barrierServer ? "server" : "client")); appendLogInfo("starting " + QString(barrier_type() == BarrierType::Server ? "server" : "client"));
qDebug() << args; qDebug() << args;
@ -624,7 +657,7 @@ QString MainWindow::configFilename()
if (m_pRadioInternalConfig->isChecked()) if (m_pRadioInternalConfig->isChecked())
{ {
// TODO: no need to use a temporary file, since we need it to // TODO: no need to use a temporary file, since we need it to
// be permenant (since it'll be used for Windows services, etc). // be permanent (since it'll be used for Windows services, etc).
m_pTempConfigFile = new QTemporaryFile(); m_pTempConfigFile = new QTemporaryFile();
if (!m_pTempConfigFile->open()) if (!m_pTempConfigFile->open())
{ {
@ -653,6 +686,11 @@ QString MainWindow::configFilename()
return filename; return filename;
} }
BarrierType MainWindow::barrier_type() const
{
return m_pGroupClient->isChecked() ? BarrierType::Client : BarrierType::Server;
}
QString MainWindow::address() QString MainWindow::address()
{ {
QString address = appConfig().networkInterface(); QString address = appConfig().networkInterface();
@ -689,6 +727,10 @@ bool MainWindow::serverArgs(QStringList& args, QString& app)
args << "--log" << appConfig().logFilenameCmd(); args << "--log" << appConfig().logFilenameCmd();
} }
if (!appConfig().getRequireClientCertificate()) {
args << "--disable-client-cert-checking";
}
QString configFilename = this->configFilename(); QString configFilename = this->configFilename();
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// wrap in quotes in case username contains spaces. // wrap in quotes in case username contains spaces.
@ -729,7 +771,7 @@ void MainWindow::stopBarrier()
void MainWindow::stopService() void MainWindow::stopService()
{ {
// send empty command to stop service from laucning anything. // send empty command to stop service from launching anything.
m_IpcClient.sendCommand("", appConfig().elevateMode()); m_IpcClient.sendCommand("", appConfig().elevateMode());
} }
@ -924,6 +966,14 @@ void MainWindow::changeEvent(QEvent* event)
QMainWindow::changeEvent(event); QMainWindow::changeEvent(event);
} }
bool MainWindow::event(QEvent* event)
{
if (event->type() == QEvent::LayoutRequest) {
setFixedSize(sizeHint());
}
return QMainWindow::event(event);
}
void MainWindow::updateZeroconfService() void MainWindow::updateZeroconfService()
{ {
QMutexLocker locker(&m_UpdateZeroconfMutex); QMutexLocker locker(&m_UpdateZeroconfMutex);
@ -935,7 +985,7 @@ void MainWindow::updateZeroconfService()
m_pZeroconfService = NULL; m_pZeroconfService = NULL;
} }
if (m_AppConfig->autoConfig() || barrierType() == barrierServer) { if (m_AppConfig->autoConfig() || barrier_type() == BarrierType::Server) {
m_pZeroconfService = new ZeroconfService(this); m_pZeroconfService = new ZeroconfService(this);
} }
} }
@ -964,12 +1014,47 @@ void MainWindow::updateSSLFingerprint()
}); });
m_pSslCertificate->generateCertificate(); m_pSslCertificate->generateCertificate();
} }
if (m_AppConfig->getCryptoEnabled() && Fingerprint::local().fileExists()) {
m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst()); toolbutton_show_fingerprint->setEnabled(false);
m_pLabelLocalFingerprint->setTextInteractionFlags(Qt::TextSelectableByMouse);
} else {
m_pLabelLocalFingerprint->setText("Disabled"); m_pLabelLocalFingerprint->setText("Disabled");
if (!m_AppConfig->getCryptoEnabled()) {
return;
} }
auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path();
if (!barrier::fs::exists(local_path)) {
return;
}
barrier::FingerprintDatabase db;
db.read(local_path);
if (db.fingerprints().size() != 2) {
return;
}
for (const auto& fingerprint : db.fingerprints()) {
if (fingerprint.algorithm == "sha1") {
auto fingerprint_str = barrier::format_ssl_fingerprint(fingerprint.data);
label_sha1_fingerprint_full->setText(QString::fromStdString(fingerprint_str));
continue;
}
if (fingerprint.algorithm == "sha256") {
auto fingerprint_str = barrier::format_ssl_fingerprint(fingerprint.data);
fingerprint_str.resize(40);
fingerprint_str += " ...";
auto fingerprint_str_cols = barrier::format_ssl_fingerprint_columns(fingerprint.data);
auto fingerprint_randomart = barrier::create_fingerprint_randomart(fingerprint.data);
m_pLabelLocalFingerprint->setText(QString::fromStdString(fingerprint_str));
label_sha256_fingerprint_full->setText(QString::fromStdString(fingerprint_str_cols));
label_sha256_randomart->setText(QString::fromStdString(fingerprint_randomart));
}
}
toolbutton_show_fingerprint->setEnabled(true);
} }
void MainWindow::on_m_pGroupClient_toggled(bool on) void MainWindow::on_m_pGroupClient_toggled(bool on)

View File

@ -20,6 +20,8 @@
#define MAINWINDOW__H #define MAINWINDOW__H
#include "barrier/BarrierType.h"
#include <QMainWindow> #include <QMainWindow>
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QSettings> #include <QSettings>
@ -76,12 +78,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
barrierTransfering barrierTransfering
}; };
enum qBarrierType
{
barrierClient,
barrierServer
};
enum qLevel { enum qLevel {
Error, Error,
Info Info
@ -98,7 +94,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
public: public:
void setVisible(bool visible); void setVisible(bool visible);
int barrierType() const { return m_pGroupClient->isChecked() ? barrierClient : barrierServer; } BarrierType barrier_type() const;
int barrierState() const { return m_BarrierState; } int barrierState() const { return m_BarrierState; }
QString hostname() const { return m_pLineEditHostname->text(); } QString hostname() const { return m_pLineEditHostname->text(); }
QString configFilename(); QString configFilename();
@ -157,6 +153,7 @@ public slots:
void stopService(); void stopService();
void stopDesktop(); void stopDesktop();
void changeEvent(QEvent* event); void changeEvent(QEvent* event);
bool event(QEvent* event);
void retranslateMenuBar(); void retranslateMenuBar();
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
bool isServiceRunning(QString name); bool isServiceRunning(QString name);
@ -202,6 +199,8 @@ public slots:
QStringList m_PendingClientNames; QStringList m_PendingClientNames;
LogWindow *m_pLogWindow; LogWindow *m_pLogWindow;
bool m_fingerprint_expanded = false;
private slots: private slots:
void on_m_pCheckBoxAutoConfig_toggled(bool checked); void on_m_pCheckBoxAutoConfig_toggled(bool checked);
void on_m_pComboServerList_currentIndexChanged(QString ); void on_m_pComboServerList_currentIndexChanged(QString );
@ -211,4 +210,3 @@ private slots:
}; };
#endif #endif

View File

@ -2,31 +2,20 @@
<ui version="4.0"> <ui version="4.0">
<class>MainWindowBase</class> <class>MainWindowBase</class>
<widget class="QMainWindow" name="MainWindowBase"> <widget class="QMainWindow" name="MainWindowBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>550</height>
</rect>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>600</width>
<height>0</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Barrier</string> <string>Barrier</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item> <item>
<widget class="QGroupBox" name="m_pGroupServer"> <widget class="QGroupBox" name="m_pGroupServer">
<property name="sizePolicy"> <property name="sizePolicy">
@ -66,30 +55,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="m_pLabelFingerprint">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SSL Fingerprint:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pLabelLocalFingerprint">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QRadioButton" name="m_pRadioInternalConfig"> <widget class="QRadioButton" name="m_pRadioInternalConfig">
<property name="text"> <property name="text">
@ -239,6 +204,107 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="m_pLabelFingerprint">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>SSL Fingerprint:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_pLabelLocalFingerprint">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolbutton_show_fingerprint">
<property name="text">
<string>...</string>
</property>
<property name="arrowType">
<enum>Qt::DownArrow</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="frame_fingerprint_details">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item row="1" column="1">
<widget class="QLabel" name="label_sha256_randomart">
<property name="font">
<font>
<family>Courier</family>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_sha1">
<property name="text">
<string>SHA1 (deprecated, compare to old clients and servers only):</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_sha1_fingerprint_full">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_sha256">
<property name="text">
<string>SHA256:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_sha256_fingerprint_full">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint"> <property name="sizeConstraint">
@ -253,7 +319,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="Barrier.qrc">:/res/icons/16x16/padlock.png</pixmap> <pixmap resource="../res/Barrier.qrc">:/res/icons/16x16/padlock.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -399,7 +465,7 @@
</action> </action>
</widget> </widget>
<resources> <resources>
<include location="Barrier.qrc"/> <include location="../res/Barrier.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

View File

@ -1,4 +1,4 @@
/* /*
* barrier -- mouse and keyboard sharing utility * barrier -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd. * Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de) * Copyright (C) 2008 Volker Lanz (vl@fidra.de)
@ -45,4 +45,3 @@ void NewScreenWidget::mousePressEvent(QMouseEvent* event)
pDrag->exec(Qt::CopyAction, Qt::CopyAction); pDrag->exec(Qt::CopyAction, Qt::CopyAction);
} }

View File

@ -37,4 +37,3 @@ class NewScreenWidget : public QLabel
}; };
#endif #endif

View File

@ -44,4 +44,3 @@ class QBarrierApplication : public QApplication
}; };
#endif #endif

View File

@ -19,7 +19,6 @@
#include "ProcessorArch.h" #include "ProcessorArch.h"
#include "CommandProcess.h" #include "CommandProcess.h"
#include "common/DataDirectories.h"
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
#include <QProcess> #include <QProcess>
@ -113,11 +112,3 @@ QString getOSInformation()
return result; return result;
} }
QString profilePath()
{
// Get path to current profile directory, properly converted
// from an OS locale std::string to Unicode QString.
auto localePath = DataDirectories::profile();
return QString::fromLocal8Bit(localePath.c_str(), localePath.size());
}

View File

@ -29,4 +29,3 @@ QString hash(const QString& string);
QString getFirstMacAddress(); QString getFirstMacAddress();
qProcessorArch getProcessorArch(); qProcessorArch getProcessorArch();
QString getOSInformation(); QString getOSInformation();
QString profilePath();

View File

@ -105,4 +105,3 @@ QDataStream& operator<<(QDataStream& outStream, const Screen& screen);
QDataStream& operator>>(QDataStream& inStream, Screen& screen); QDataStream& operator>>(QDataStream& inStream, Screen& screen);
#endif #endif

View File

@ -152,4 +152,3 @@ void ScreenSettingsDialog::on_m_pListAliases_itemSelectionChanged()
{ {
m_pButtonRemoveAlias->setEnabled(!m_pListAliases->selectedItems().isEmpty()); m_pButtonRemoveAlias->setEnabled(!m_pListAliases->selectedItems().isEmpty());
} }

View File

@ -50,4 +50,3 @@ class ScreenSettingsDialog : public QDialog, public Ui::ScreenSettingsDialogBase
}; };
#endif #endif

View File

@ -141,4 +141,3 @@ bool ScreenSetupModel::dropMimeData(const QMimeData* data, Qt::DropAction action
return true; return true;
} }

View File

@ -68,4 +68,3 @@ class ScreenSetupModel : public QAbstractTableModel
}; };
#endif #endif

View File

@ -225,4 +225,3 @@ QStyleOptionViewItem ScreenSetupView::viewOptions() const
option.textElideMode = Qt::ElideMiddle; option.textElideMode = Qt::ElideMiddle;
return option; return option;
} }

View File

@ -58,4 +58,3 @@ class ScreenSetupView : public QTableView
}; };
#endif #endif

View File

@ -138,4 +138,3 @@ enum {
}; };
#endif #endif

View File

@ -76,7 +76,7 @@ void ServerConfigDialog::showEvent(QShowEvent* event)
if (!m_Message.isEmpty()) if (!m_Message.isEmpty())
{ {
// TODO: ideally this massage box should pop up after the dialog is shown // TODO: ideally this message box should pop up after the dialog is shown
QMessageBox::information(this, tr("Configure server"), m_Message); QMessageBox::information(this, tr("Configure server"), m_Message);
} }
} }

View File

@ -63,4 +63,3 @@ class ServerConfigDialog : public QDialog, public Ui::ServerConfigDialogBase
}; };
#endif #endif

View File

@ -51,6 +51,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
m_pCheckBoxAutoStart->setChecked(appConfig().getAutoStart()); m_pCheckBoxAutoStart->setChecked(appConfig().getAutoStart());
m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray()); m_pCheckBoxMinimizeToTray->setChecked(appConfig().getMinimizeToTray());
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
checkbox_require_client_certificate->setChecked(m_appConfig.getRequireClientCertificate());
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
m_pComboElevate->setCurrentIndex(static_cast<int>(appConfig().elevateMode())); m_pComboElevate->setCurrentIndex(static_cast<int>(appConfig().elevateMode()));
@ -67,6 +68,7 @@ void SettingsDialog::accept()
m_appConfig.setPort(m_pSpinBoxPort->value()); m_appConfig.setPort(m_pSpinBoxPort->value());
m_appConfig.setNetworkInterface(m_pLineEditInterface->text()); m_appConfig.setNetworkInterface(m_pLineEditInterface->text());
m_appConfig.setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked()); m_appConfig.setCryptoEnabled(m_pCheckBoxEnableCrypto->isChecked());
m_appConfig.setRequireClientCertificate(checkbox_require_client_certificate->isChecked());
m_appConfig.setLogLevel(m_pComboLogLevel->currentIndex()); m_appConfig.setLogLevel(m_pComboLogLevel->currentIndex());
m_appConfig.setLogToFile(m_pCheckBoxLogToFile->isChecked()); m_appConfig.setLogToFile(m_pCheckBoxLogToFile->isChecked());
m_appConfig.setLogFilename(m_pLineEditLogFilename->text()); m_appConfig.setLogFilename(m_pLineEditLogFilename->text());

View File

@ -142,6 +142,16 @@
<string>Networking</string> <string>Networking</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="m_pLabel_21">
<property name="text">
<string>&amp;Address:</string>
</property>
<property name="buddy">
<cstring>m_pLineEditInterface</cstring>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="m_pLabel_20"> <widget class="QLabel" name="m_pLabel_20">
<property name="text"> <property name="text">
@ -171,16 +181,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="m_pLabel_21">
<property name="text">
<string>&amp;Address:</string>
</property>
<property name="buddy">
<cstring>m_pLineEditInterface</cstring>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditInterface"> <widget class="QLineEdit" name="m_pLineEditInterface">
<property name="enabled"> <property name="enabled">
@ -188,13 +188,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="m_pCheckBoxEnableCrypto"> <widget class="QCheckBox" name="m_pCheckBoxEnableCrypto">
<property name="text"> <property name="text">
<string>Enable &amp;SSL</string> <string>Enable &amp;SSL</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkbox_require_client_certificate">
<property name="text">
<string>Require client certificate</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -216,19 +223,20 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0"> <item row="1" column="0">
<widget class="QLabel" name="m_pLabel_3"> <widget class="QCheckBox" name="m_pCheckBoxLogToFile">
<property name="minimumSize"> <property name="text">
<size> <string>Log to file:</string>
<width>75</width> </property>
<height>0</height> </widget>
</size> </item>
<item row="1" column="2">
<widget class="QPushButton" name="m_pButtonBrowseLog">
<property name="enabled">
<bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Logging level:</string> <string>Browse...</string>
</property>
<property name="buddy">
<cstring>m_pComboLogLevel</cstring>
</property> </property>
</widget> </widget>
</item> </item>
@ -271,10 +279,19 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="m_pCheckBoxLogToFile"> <widget class="QLabel" name="m_pLabel_3">
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
<property name="text"> <property name="text">
<string>Log to file:</string> <string>&amp;Logging level:</string>
</property>
<property name="buddy">
<cstring>m_pComboLogLevel</cstring>
</property> </property>
</widget> </widget>
</item> </item>
@ -285,16 +302,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2">
<widget class="QPushButton" name="m_pButtonBrowseLog">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -37,7 +37,7 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) :
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
// when areo is disabled on windows, the next/back buttons // when aero is disabled on windows, the next/back buttons
// are hidden (must be a qt bug) -- resizing the window // are hidden (must be a qt bug) -- resizing the window
// to +1 of the original height seems to fix this. // to +1 of the original height seems to fix this.
// NOTE: calling setMinimumSize after this will break // NOTE: calling setMinimumSize after this will break

View File

@ -19,4 +19,3 @@
// included in both the GUI and the child apps (server & client) // included in both the GUI and the child apps (server & client)
const char ShutdownCh = 'S'; const char ShutdownCh = 'S';

View File

@ -16,12 +16,11 @@
*/ */
#include "SslCertificate.h" #include "SslCertificate.h"
#include "Fingerprint.h" #include "common/DataDirectories.h"
#include "QUtility.h" #include "base/finally.h"
#include "io/filesystem.h"
#include <QProcess> #include "net/FingerprintDatabase.h"
#include <QDir> #include "net/SecureUtils.h"
#include <QCoreApplication>
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
@ -29,198 +28,90 @@
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/x509.h> #include <openssl/x509.h>
static const char kCertificateLifetime[] = "365";
static const char kCertificateSubjectInfo[] = "/CN=Barrier";
static const char kCertificateFilename[] = "Barrier.pem";
static const char kSslDir[] = "SSL";
static const char kUnixOpenSslCommand[] = "openssl";
#if defined(Q_OS_WIN)
static const char kWinOpenSslBinary[] = "openssl.exe";
static const char kConfigFile[] = "barrier.conf";
#endif
SslCertificate::SslCertificate(QObject *parent) : SslCertificate::SslCertificate(QObject *parent) :
QObject(parent) QObject(parent)
{ {
m_ProfileDir = profilePath(); if (barrier::DataDirectories::profile().empty()) {
if (m_ProfileDir.isEmpty()) {
emit error(tr("Failed to get profile directory.")); emit error(tr("Failed to get profile directory."));
} }
} }
std::pair<bool, QString> SslCertificate::runTool(const QStringList& args)
{
QString program;
#if defined(Q_OS_WIN)
program = QCoreApplication::applicationDirPath();
program.append("\\").append(kWinOpenSslBinary);
#else
program = kUnixOpenSslCommand;
#endif
QStringList environment;
#if defined(Q_OS_WIN)
environment << QString("OPENSSL_CONF=%1\\%2")
.arg(QCoreApplication::applicationDirPath())
.arg(kConfigFile);
#endif
QProcess process;
QString standardOutput, standardError;
process.setEnvironment(environment);
process.start(program, args);
bool success = process.waitForStarted();
if (success && process.waitForFinished())
{
standardOutput = QString::fromLocal8Bit(process.readAllStandardOutput().trimmed());
standardError = QString::fromLocal8Bit(process.readAllStandardError().trimmed());
}
int code = process.exitCode();
if (!success || code != 0)
{
emit error(
QString("SSL tool failed: %1\n\nCode: %2\nError: %3")
.arg(program)
.arg(process.exitCode())
.arg(standardError.isEmpty() ? "Unknown" : standardError));
return {false, standardOutput};
}
return {true, standardOutput};
}
void SslCertificate::generateCertificate() void SslCertificate::generateCertificate()
{ {
auto filename = getCertificatePath(); auto cert_path = barrier::DataDirectories::ssl_certificate_path();
QFile file(filename); if (!barrier::fs::exists(cert_path) || !is_certificate_valid(cert_path)) {
if (!file.exists() || !isCertificateValid(filename)) { try {
QStringList arguments; auto cert_dir = cert_path.parent_path();
if (!barrier::fs::exists(cert_dir)) {
// self signed certificate barrier::fs::create_directories(cert_dir);
arguments.append("req");
arguments.append("-x509");
arguments.append("-nodes");
// valide duration
arguments.append("-days");
arguments.append(kCertificateLifetime);
// subject information
arguments.append("-subj");
QString subInfo(kCertificateSubjectInfo);
arguments.append(subInfo);
// private key
arguments.append("-newkey");
arguments.append("rsa:2048");
QDir sslDir(getCertificateDirectory());
if (!sslDir.exists()) {
sslDir.mkpath(".");
} }
// key output filename barrier::generate_pem_self_signed_cert(cert_path.u8string());
arguments.append("-keyout"); } catch (const std::exception& e) {
arguments.append(filename); emit error(QString("SSL tool failed: %1").arg(e.what()));
// certificate output filename
arguments.append("-out");
arguments.append(filename);
if (!runTool(arguments).first) {
return; return;
} }
emit info(tr("SSL certificate generated.")); emit info(tr("SSL certificate generated."));
} }
generateFingerprint(filename); generate_fingerprint(cert_path);
emit generateFinished(); emit generateFinished();
} }
void SslCertificate::generateFingerprint(const QString& certificateFilename) void SslCertificate::generate_fingerprint(const barrier::fs::path& cert_path)
{ {
QStringList arguments; try {
arguments.append("x509"); auto local_path = barrier::DataDirectories::local_ssl_fingerprints_path();
arguments.append("-fingerprint"); auto local_dir = local_path.parent_path();
arguments.append("-sha1"); if (!barrier::fs::exists(local_dir)) {
arguments.append("-noout"); barrier::fs::create_directories(local_dir);
arguments.append("-in");
arguments.append(certificateFilename);
auto ret = runTool(arguments);
bool success = ret.first;
if (!success) {
return;
} }
// find the fingerprint from the tool output barrier::FingerprintDatabase db;
QString fingerprint = ret.second; db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(),
auto i = fingerprint.indexOf('='); barrier::FingerprintType::SHA1));
if (i != -1) { db.add_trusted(barrier::get_pem_file_cert_fingerprint(cert_path.u8string(),
fingerprint.remove(0, i+1); barrier::FingerprintType::SHA256));
db.write(local_path);
Fingerprint::local().trust(fingerprint, false);
emit info(tr("SSL fingerprint generated.")); emit info(tr("SSL fingerprint generated."));
} } catch (const std::exception& e) {
else { emit error(tr("Failed to find SSL fingerprint.") + e.what());
emit error(tr("Failed to find SSL fingerprint."));
} }
} }
QString SslCertificate::getCertificatePath() bool SslCertificate::is_certificate_valid(const barrier::fs::path& path)
{
return getCertificateDirectory() + QDir::separator() + kCertificateFilename;
}
QString SslCertificate::getCertificateDirectory()
{
return m_ProfileDir + QDir::separator() + kSslDir;
}
bool SslCertificate::isCertificateValid(const QString& path)
{ {
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings(); ERR_load_crypto_strings();
BIO* bio = BIO_new(BIO_s_file()); auto fp = barrier::fopen_utf8_path(path, "r");
if (!fp) {
auto ret = BIO_read_filename(bio, path.toLocal8Bit().constData());
if (!ret) {
emit info(tr("Could not read from default certificate file.")); emit info(tr("Could not read from default certificate file."));
BIO_free_all(bio);
return false; return false;
} }
auto file_close = barrier::finally([fp]() { std::fclose(fp); });
X509* cert = PEM_read_bio_X509(bio, NULL, 0, NULL); auto* cert = PEM_read_X509(fp, nullptr, nullptr, nullptr);
if (!cert) { if (!cert) {
emit info(tr("Error loading default certificate file to memory.")); emit info(tr("Error loading default certificate file to memory."));
BIO_free_all(bio);
return false; return false;
} }
auto cert_free = barrier::finally([cert]() { X509_free(cert); });
EVP_PKEY* pubkey = X509_get_pubkey(cert); auto* pubkey = X509_get_pubkey(cert);
if (!pubkey) { if (!pubkey) {
emit info(tr("Default certificate key file does not contain valid public key")); emit info(tr("Default certificate key file does not contain valid public key"));
X509_free(cert);
BIO_free_all(bio);
return false; return false;
} }
auto pubkey_free = barrier::finally([pubkey]() { EVP_PKEY_free(pubkey); });
auto type = EVP_PKEY_type(EVP_PKEY_id(pubkey)); auto type = EVP_PKEY_type(EVP_PKEY_id(pubkey));
if (type != EVP_PKEY_RSA && type != EVP_PKEY_DSA) { if (type != EVP_PKEY_RSA && type != EVP_PKEY_DSA) {
emit info(tr("Public key in default certificate key file is not RSA or DSA")); emit info(tr("Public key in default certificate key file is not RSA or DSA"));
EVP_PKEY_free(pubkey);
X509_free(cert);
BIO_free_all(bio);
return false; return false;
} }
@ -228,14 +119,8 @@ bool SslCertificate::isCertificateValid(const QString& path)
if (bits < 2048) { if (bits < 2048) {
// We could have small keys in old barrier installations // We could have small keys in old barrier installations
emit info(tr("Public key in default certificate key file is too small.")); emit info(tr("Public key in default certificate key file is too small."));
EVP_PKEY_free(pubkey);
X509_free(cert);
BIO_free_all(bio);
return false; return false;
} }
EVP_PKEY_free(pubkey);
X509_free(cert);
BIO_free_all(bio);
return true; return true;
} }

View File

@ -19,6 +19,7 @@
#include <QObject> #include <QObject>
#include <string> #include <string>
#include "io/filesystem.h"
class SslCertificate : public QObject class SslCertificate : public QObject
{ {
@ -36,13 +37,7 @@ signals:
void generateFinished(); void generateFinished();
private: private:
std::pair<bool, QString> runTool(const QStringList& args); void generate_fingerprint(const barrier::fs::path& cert_path);
void generateFingerprint(const QString& certificateFilename);
QString getCertificatePath(); bool is_certificate_valid(const barrier::fs::path& path);
QString getCertificateDirectory();
bool isCertificateValid(const QString& path);
private:
QString m_ProfileDir;
}; };

View File

@ -40,4 +40,3 @@ void TrashScreenWidget::dropEvent(QDropEvent* event)
else else
event->ignore(); event->ignore();
} }

View File

@ -39,4 +39,3 @@ class TrashScreenWidget : public QLabel
}; };
#endif #endif

View File

@ -66,7 +66,7 @@ ZeroconfService::ZeroconfService(MainWindow* mainWindow) :
m_ServiceRegistered(false) m_ServiceRegistered(false)
{ {
silence_avahi_warning(); silence_avahi_warning();
if (m_pMainWindow->barrierType() == MainWindow::barrierServer) { if (m_pMainWindow->barrier_type() == BarrierType::Server) {
if (registerService(true)) { if (registerService(true)) {
m_pZeroconfBrowser = new ZeroconfBrowser(this); m_pZeroconfBrowser = new ZeroconfBrowser(this);
connect(m_pZeroconfBrowser, SIGNAL( connect(m_pZeroconfBrowser, SIGNAL(

View File

@ -97,6 +97,12 @@ int main(int argc, char* argv[])
QApplication::setQuitOnLastWindowClosed(false); QApplication::setQuitOnLastWindowClosed(false);
if (QGuiApplication::platformName() == "wayland") {
QMessageBox::warning(
NULL, "Barrier",
"You are using wayland session, which is currently not fully supported by Barrier.");
}
QSettings settings; QSettings settings;
AppConfig appConfig (&settings); AppConfig appConfig (&settings);

Some files were not shown because too many files have changed in this diff Show More