Added certificate dialog.
authorArmin Novak <armin.novak@thincast.com>
Thu, 29 Nov 2018 16:23:09 +0000 (17:23 +0100)
committerArmin Novak <armin.novak@thincast.com>
Thu, 6 Dec 2018 09:17:05 +0000 (10:17 +0100)
client/Mac/CMakeLists.txt
client/Mac/CertificateDialog.h [new file with mode: 0644]
client/Mac/CertificateDialog.m [new file with mode: 0644]
client/Mac/CertificateDialog.xib [new file with mode: 0644]
client/Mac/MRDPView.m
client/Mac/PasswordDialog.m

index 29f98b3..94d7775 100644 (file)
@@ -41,6 +41,7 @@ set(${MODULE_PREFIX}_OBJECTIVE_SOURCES
        MRDPView.m
        Keyboard.m
        Clipboard.m
+       CertificateDialog.m
        PasswordDialog.m)
 
 list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES})
@@ -52,6 +53,7 @@ set(${MODULE_PREFIX}_HEADERS
        MRDPView.h
        Keyboard.h
        Clipboard.h
+       CertificateDialog.h
        PasswordDialog.h)
 
 set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings")
diff --git a/client/Mac/CertificateDialog.h b/client/Mac/CertificateDialog.h
new file mode 100644 (file)
index 0000000..d89cf25
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * MacFreeRDP
+ *
+ * Copyright 2018 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2018 Thicast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface CertificateDialog : NSWindowController
+{
+@public
+       NSTextField* textCommonName;
+       NSTextField* textSubject;
+       NSTextField* textIssuer;
+       NSTextField* textFingerprint;
+       NSTextField* messageLabel;
+       NSString* serverHostname;
+
+       BOOL hostMismatch;
+       int result;
+}
+@property(retain) IBOutlet NSTextField* textCommonName;
+@property(retain) IBOutlet NSTextField* textSubject;
+@property(retain) IBOutlet NSTextField* textIssuer;
+@property(retain) IBOutlet NSTextField* textFingerprint;
+@property(retain) IBOutlet NSTextField* messageLabel;
+
+- (IBAction)onAccept:(NSObject*)sender;
+- (IBAction)onTemporary:(NSObject*)sender;
+- (IBAction)onCancel:(NSObject*)sender;
+
+@property(retain) NSString* serverHostname;
+@property(retain) NSString* commonName;
+@property(retain) NSString* subject;
+@property(retain) NSString* issuer;
+@property(retain) NSString* fingerprint;
+@property BOOL hostMismatch;
+@property(readonly) int result;
+
+- (int) runModal:(NSWindow*)mainWindow;
+
+@end
diff --git a/client/Mac/CertificateDialog.m b/client/Mac/CertificateDialog.m
new file mode 100644 (file)
index 0000000..2495405
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * MacFreeRDP
+ *
+ * Copyright 2018 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2018 Thicast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#import "CertificateDialog.h"
+#import <freerdp/client/cmdline.h>
+
+#import <CoreGraphics/CoreGraphics.h>
+
+@interface CertificateDialog()
+
+       @property int result;
+
+@end
+
+@implementation CertificateDialog
+
+@synthesize textCommonName;
+@synthesize textFingerprint;
+@synthesize textIssuer;
+@synthesize textSubject;
+@synthesize messageLabel;
+@synthesize serverHostname;
+@synthesize commonName;
+@synthesize fingerprint;
+@synthesize issuer;
+@synthesize subject;
+@synthesize hostMismatch;
+
+- (id)init
+{
+       return [self initWithWindowNibName:@"CertificateDialog"];
+}
+
+- (void)windowDidLoad
+{
+       [super windowDidLoad];
+       // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+       [self.window setTitle:self.serverHostname];
+       [self.messageLabel setStringValue:[NSString stringWithFormat:@"Certificate for %@",
+                                     self.serverHostname]];
+
+       [self.textCommonName setStringValue:self.commonName];
+       [self.textFingerprint setStringValue:self.fingerprint];
+       [self.textIssuer setStringValue:self.issuer];
+       [self.textSubject setStringValue:self.subject];
+}
+
+- (IBAction)onAccept:(NSObject*)sender
+{
+       [NSApp stopModalWithCode:1];
+}
+
+- (IBAction)onTemporary:(NSObject*)sender
+{
+       [NSApp stopModalWithCode:2];
+}
+
+- (IBAction)onCancel:(NSObject*)sender
+{
+       [NSApp stopModalWithCode:0];
+}
+
+- (int)runModal:(NSWindow*)mainWindow
+{
+       if ([mainWindow respondsToSelector:@selector(beginSheet:completionHandler:)])
+       {
+               [mainWindow beginSheet:self.window completionHandler:nil];
+               self.result = [NSApp runModalForWindow: self.window];
+               [mainWindow endSheet: self.window];
+       }
+       else
+       {
+               [NSApp beginSheet: self.window
+                modalForWindow: mainWindow
+                modalDelegate: nil
+                didEndSelector: nil
+                contextInfo: nil];
+               self.result = [NSApp runModalForWindow: self.window];
+               [NSApp endSheet: self.window];
+       }
+
+       [self.window orderOut:nil];
+       return self.result;
+}
+
+- (void)dealloc
+{
+       [textCommonName release];
+       [textFingerprint release];
+       [textIssuer release];
+       [textSubject release];
+       [messageLabel release];
+       [serverHostname release];
+       [commonName release];
+       [fingerprint release];
+       [issuer release];
+       [subject release];
+       [super dealloc];
+}
+
+@end
diff --git a/client/Mac/CertificateDialog.xib b/client/Mac/CertificateDialog.xib
new file mode 100644 (file)
index 0000000..27f215d
--- /dev/null
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="CertificateDialog">
+            <connections>
+                <outlet property="messageLabel" destination="7" id="50"/>
+                <outlet property="window" destination="1" id="3"/>
+                <outlet property="textCommonName" destination="2HW-of-a4n" id="4442"/>
+                <outlet property="textSubject" destination="R9r-82-XAH" id="4443"/>
+                <outlet property="textIssuer" destination="kHA-F4-dxw" id="4444"/>
+                <outlet property="textFingerprint" destination="cLB-ZO-jvx" id="4445"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" visibleAtLaunch="NO" animationBehavior="default" id="1">
+            <windowStyleMask key="styleMask" titled="YES" texturedBackground="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="196" y="240" width="480" height="270"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
+            <view key="contentView" id="2">
+                <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <textField verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5">
+                        <rect key="frame" x="47" y="134" width="51" height="17"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Subject" id="22">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vA4-qf-QuW">
+                        <rect key="frame" x="47" y="109" width="41" height="17"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Issuer" id="tAl-Qh-OR9">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VLG-f9-Gcl">
+                        <rect key="frame" x="47" y="84" width="71" height="17"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Fingerprint" id="49l-Xk-MUH">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7">
+                        <rect key="frame" x="47" y="206" width="344" height="17"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="340" id="19"/>
+                        </constraints>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Certificate for SERVER_NAME" placeholderString="" id="20">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8">
+                        <rect key="frame" x="384" y="13" width="82" height="32"/>
+                        <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="18">
+                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                            <font key="font" metaFont="system"/>
+                            <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+                        </buttonCell>
+                        <connections>
+                            <action selector="onCancel:" target="-2" id="52"/>
+                        </connections>
+                    </button>
+                    <button verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9">
+                        <rect key="frame" x="199" y="13" width="82" height="32"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="70" id="16"/>
+                        </constraints>
+                        <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="17">
+                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                            <font key="font" metaFont="system"/>
+                            <string key="keyEquivalent" base64-UTF8="YES">
+DQ
+</string>
+                        </buttonCell>
+                        <connections>
+                            <action selector="onAccept:" target="-2" id="522"/>
+                        </connections>
+                    </button>
+                    <textField verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="10">
+                        <rect key="frame" x="47" y="159" width="106" height="17"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="102" id="14"/>
+                        </constraints>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Common" id="15">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2HW-of-a4n">
+                        <rect key="frame" x="140" y="159" width="305" height="17"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="COMMON NAME" id="N48-2i-W6H">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="R9r-82-XAH">
+                        <rect key="frame" x="140" y="134" width="305" height="17"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="SUBJECT" id="iGw-oh-i3p">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kHA-F4-dxw">
+                        <rect key="frame" x="140" y="109" width="305" height="17"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="ISSUER" id="daP-a0-hI1">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cLB-ZO-jvx">
+                        <rect key="frame" x="140" y="84" width="305" height="17"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="FINGERPRINT" id="VqU-vO-noG">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7I5-a2-h65">
+                        <rect key="frame" x="281" y="13" width="105" height="32"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <buttonCell key="cell" type="push" title="Temporary" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="i6y-0u-COa">
+                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                            <font key="font" metaFont="system"/>
+                            <string key="keyEquivalent" base64-UTF8="YES">
+Gw
+</string>
+                        </buttonCell>
+                        <connections>
+                            <action selector="onTemporary:" target="-2" id="BWk-o1-tug"/>
+                        </connections>
+                    </button>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="8" firstAttribute="leading" secondItem="9" secondAttribute="trailing" id="32"/>
+                    <constraint firstItem="10" firstAttribute="leading" secondItem="5" secondAttribute="leading" id="34"/>
+                    <constraint firstItem="10" firstAttribute="leading" secondItem="7" secondAttribute="leading" id="37"/>
+                    <constraint firstAttribute="bottom" secondItem="9" secondAttribute="bottom" constant="20" symbolic="YES" id="39"/>
+                    <constraint firstItem="5" firstAttribute="centerY" secondItem="2" secondAttribute="centerY" id="41"/>
+                    <constraint firstAttribute="bottom" secondItem="8" secondAttribute="bottom" constant="20" symbolic="YES" id="42"/>
+                    <constraint firstAttribute="trailing" secondItem="8" secondAttribute="trailing" constant="20" symbolic="YES" id="43"/>
+                    <constraint firstItem="7" firstAttribute="leading" secondItem="2" secondAttribute="leading" constant="49" id="44"/>
+                    <constraint firstItem="7" firstAttribute="top" secondItem="2" secondAttribute="top" constant="47" id="45"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="4"/>
+            </connections>
+            <point key="canvasLocation" x="148" y="68"/>
+        </window>
+    </objects>
+</document>
index 8cd643a..52b333b 100644 (file)
@@ -25,6 +25,7 @@
 #import "MRDPCursor.h"
 #import "Clipboard.h"
 #import "PasswordDialog.h"
+#import "CertificateDialog.h"
 
 #include <winpr/crt.h>
 #include <winpr/input.h>
@@ -1026,8 +1027,24 @@ BOOL mac_gw_authenticate(freerdp* instance, char** username, char** password,
 
 DWORD mac_verify_certificate(freerdp* instance, const char* common_name, const char* subject, const char* issuer, const char* fingerprint, BOOL host_mismatch)
 {
-       WLog_WARN(TAG, "TODO: Implement %s, accepting everything", __FUNCTION__);
-       return 2;
+       mfContext* mfc = (mfContext*) instance->context;
+       MRDPView* view = (MRDPView*) mfc->view;
+       CertificateDialog* dialog = [CertificateDialog new];
+       dialog.serverHostname = [NSString stringWithCString:subject encoding:
+                       NSUTF8StringEncoding];;
+       dialog.commonName = [NSString stringWithCString:common_name encoding:
+                       NSUTF8StringEncoding];;
+       dialog.subject = [NSString stringWithCString:subject encoding:
+                       NSUTF8StringEncoding];;
+       dialog.issuer = [NSString stringWithCString:issuer encoding:
+                       NSUTF8StringEncoding];;
+       dialog.fingerprint = [NSString stringWithCString:fingerprint encoding:
+                       NSUTF8StringEncoding];;
+       dialog.hostMismatch = host_mismatch;
+       [dialog performSelectorOnMainThread:@selector(runModal:) withObject:[view
+               window] waitUntilDone:TRUE];
+
+       return dialog.result;
 }
 
 DWORD mac_verify_changed_certificate(freerdp* instance, const char* common_name, const char* subject, const char* issuer, const char* fingerprint, const char* old_subject, const char* old_issuer, const char* old_fingerprint)
index ab73699..2eecea4 100644 (file)
@@ -49,7 +49,7 @@
        [super windowDidLoad];
        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
        [self.window setTitle:self.serverHostname];
-       [messageLabel setStringValue:[NSString stringWithFormat:@"Authenticate to %@",
+       [self.messageLabel setStringValue:[NSString stringWithFormat:@"Authenticate to %@",
                                      self.serverHostname]];
        NSMutableString* domainUser = [[NSMutableString alloc] initWithString:@""];
 
        if (self.username != nil)
        {
                [domainUser appendString:self.username];
-               [self.window makeFirstResponder:passwordText];
+               [self.window makeFirstResponder:self.passwordText];
        }
 
-       [usernameText setStringValue:domainUser];
+       [self.usernameText setStringValue:domainUser];
 }
 
 - (IBAction)onOK:(NSObject*)sender