Commit 91ea9bbd authored by Hirsch Singhal's avatar Hirsch Singhal
Browse files

Merge remote-tracking branch 'refs/remotes/Microsoft/master'

parents 87d2bb72 7f707bc6
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -24,6 +24,17 @@ portal.Connect().Wait(); // The ConnectionStatus event will tell you if it succe
```
For complete examples and stepping off points see the SampleWdpClients.  A UWP version and WPF version of the sample app are included in the solution.

### Verifying your connection
There are several different ways to verify your connection for using secure HTTPS communication with a device. Any of these methods can be used to secure your connection against a Man in the Middle attack or to allow your own proxy for debugging your communication.

1. If the certificate generated by your device is in your Trusted Root Certification Authorities certificate store then the connection will be automatically verified when connecting. No additional work is necessary.
2. You can manually provide the certificate object to the Connect method on the DevicePortal object to use for verification. This certificate could have been retrieved earlier via USB, or downloaded via a call to \<address\>/config/rootcertificate and then manually verified as being the proper certificate. This is a good method to use if using a web proxy such as Fiddler, as those proxies generally let you export their certificate.
3. Add your own logic for certificate checking. This works differently in Win32 and UWP
   - For UWP, you can make a call to the GetRootDeviceCertificate method on your DevicePortal object with the acceptUntrustedCerts parameter set to true. This will allow untrusted connections to your device for subsequent calls. **You should warn your user that they are making an untrusted connection or otherwise verify your connection is secure if using this method.**
   - For Win32, you can add a handler to the UnvalidatedCert event on your DevicePortal object which gives you a chance to perform custom handling such as presenting the thumbprint for the certificate to the user and asking them if they trust the connection, or using a prior cached decision about this connection. This is similar to how a web browser handles untrusted certificates.
   
The SampleWdpClients show examples of using all of these methods of establishing trust in an application.

## Using the DevicePortal object
Each REST API exposed by Device Portal is represented as a method off of the DevicePortal object. Most methods are a task that return an object representing the JSON return value.  

+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ To start contributing, see [Contributing](https://github.com/Microsoft/WindowsDe
---
---

For source code documentation, see https://Microsoft.github.io/WindowsDevicePortalWrapper
For source code documentation, see https://microsoft.github.io/WindowsDevicePortalWrapper/annotated.html

---
---
+2 −1
Original line number Diff line number Diff line
@@ -23,7 +23,8 @@
        <Button x:Name="rebootDevice" Content="Reboot" Grid.Column="0" HorizontalAlignment="Left" Margin="114,123,0,0" VerticalAlignment="Top" Width="93" Click="RebootDevice_Click" IsEnabled="False" Height="32"/>
        <Button x:Name="shutdownDevice" Content="Shutdown" Grid.Column="0" HorizontalAlignment="Left" Margin="212,123,0,0" VerticalAlignment="Top" Width="93" Click="ShutdownDevice_Click" IsEnabled="False" Height="32"/>

        <TextBlock x:Name="UnsecureCertWarning" Grid.Column="0" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" FontWeight="Bold" FontSize="16" Margin="12,231,0,0" Height="60" Text="Note: The UWP Sample App does not currently support certificate validation for HTTPS communication" />
        <Button x:Name="loadCert" Content="Add Trusted Certificate" Grid.Column="0" HorizontalAlignment="Left" Margin="12,225,0,0" VerticalAlignment="Top" Width="175" Click="LoadCertificate_Click" Height="32"/>
        <CheckBox x:Name="allowUntrustedCheckbox" Content="Allow Untrusted Connections (Not Recommended)" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="27,257,0,0"></CheckBox>

        <Border Grid.Column="0" BorderBrush="Black" BorderThickness="1" Height="1" Margin="15,160,15,0" VerticalAlignment="Top"/>

+97 −46
Original line number Diff line number Diff line
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Security.Cryptography.Certificates;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Microsoft.Tools.WindowsDevicePortal;
using static Microsoft.Tools.WindowsDevicePortal.DevicePortal;
using System.Runtime.CompilerServices;
using Windows.UI.Core;

namespace SampleWdpClient.UniversalWindows
{
@@ -29,6 +24,8 @@ namespace SampleWdpClient.UniversalWindows
        /// </summary>
        private DevicePortal portal;

        private Certificate certificate;

        /// <summary>
        /// The main page constructor.
        /// </summary>
@@ -72,6 +69,8 @@ namespace SampleWdpClient.UniversalWindows

            this.ClearOutput();

            bool allowUntrusted = this.allowUntrustedCheckbox.IsChecked.Value;

            portal = new DevicePortal(
                new DefaultDevicePortalConnection(
                    this.address.Text,
@@ -107,9 +106,21 @@ namespace SampleWdpClient.UniversalWindows
                        }
                    };

                        // TODO: Support proper certificate validation instead of blindly trusting this cert (Issue #154/#145).
                    try
                    {
                        // If the user wants to allow untrusted connections, make a call to GetRootDeviceCertificate
                        // with acceptUntrustedCerts set to true. This will enable untrusted connections for the
                        // remainder of this session.
                        if (allowUntrusted)
                        {
                            await portal.GetRootDeviceCertificate(true);
                        await portal.Connect();
                        }
                        await portal.Connect(manualCertificate: this.certificate);
                    }
                    catch (Exception exception)
                    {
                        sb.AppendLine(exception.Message);
                    }

                    this.MarshalUpdateCommandOutput(sb.ToString());
                });
@@ -457,5 +468,45 @@ namespace SampleWdpClient.UniversalWindows
        {
            EnableConnectButton();
        }

        /// <summary>
        /// Loads a cert file for cert validation.
        /// </summary>
        /// <param name="sender">The caller of this method.</param>
        /// <param name="e">The arguments associated with this event.</param>
        private async void LoadCertificate_Click(object sender, RoutedEventArgs e)
        {
            await LoadCertificate();
        }

        /// <summary>
        /// Loads a certificates asynchronously (runs on the UI thread).
        /// </summary>
        /// <returns></returns>
        private async Task LoadCertificate()
        {
            try
            {
                FileOpenPicker filePicker = new FileOpenPicker();
                filePicker.SuggestedStartLocation = PickerLocationId.Downloads;
                filePicker.FileTypeFilter.Add(".cer");

                StorageFile file = await filePicker.PickSingleFileAsync();

                if (file != null)
                {
                    IBuffer cerBlob = await FileIO.ReadBufferAsync(file);

                    if (cerBlob != null)
                    {
                        certificate = new Certificate(cerBlob);
                    }
                }
            }
            catch (Exception exception)
            {
                this.commandOutput.Text = "Failed to get cert file: " + exception.Message;
            }
        }
    }
}
 No newline at end of file
+17 −2
Original line number Diff line number Diff line
@@ -220,6 +220,8 @@ namespace XboxWdpDriver
                    }
                }

                X509Certificate2 cert = null;

                IDevicePortalConnection connection = new DefaultDevicePortalConnection(finalConnectionAddress, userName, password);

                DevicePortal portal = new DevicePortal(connection);
@@ -230,7 +232,7 @@ namespace XboxWdpDriver

                    try
                    {
                        connection.SetDeviceCertificate(new System.Security.Cryptography.X509Certificates.X509Certificate2(certFile));
                        cert = new X509Certificate2(certFile);
                    }
                    catch (Exception e)
                    {
@@ -257,7 +259,7 @@ namespace XboxWdpDriver
                    }
                }

                Task connectTask = portal.Connect(updateConnection: false);
                Task connectTask = portal.Connect(updateConnection: false, manualCertificate: cert);
                connectTask.Wait();

                if (portal.ConnectionHttpStatusCode != HttpStatusCode.OK)
@@ -377,6 +379,19 @@ namespace XboxWdpDriver
                    }
                }
            }
            catch (AggregateException e)
            {
                if (e.InnerException is DevicePortalException)
                {
                    DevicePortalException innerException = e.InnerException as DevicePortalException;

                    Console.WriteLine(string.Format("Exception encountered: {0}, hr = 0x{1:X} : {2}", innerException.StatusCode, innerException.HResult, innerException.Reason));
                }
                else
                {
                    Console.WriteLine(string.Format("Unexpected exception encountered: {0}", e.Message));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
Loading