Skip to content

Commit

Permalink
We should be able to re-patch composer now without having to re-certi…
Browse files Browse the repository at this point in the history
…ficate the director
  • Loading branch information
garrynewman committed Aug 21, 2020
1 parent 7715e4a commit 0c622f8
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 11 deletions.
4 changes: 2 additions & 2 deletions Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Garry.Control4.Jailbreak
{
public static class Constants
{
public const int Version = 2;
public const int Version = 3;

/// <summary>
/// The cert for composer needs to be named cacert-*.pem
Expand Down Expand Up @@ -39,7 +39,7 @@ public static class Constants
/// <summary>
/// Where OpenSSL's Config is located (it's installed with Composer)
/// </summary>
public const string OpenSslConfig = @"C:\Program Files (x86)\Control4\Composer\Pro\RemoteAccess\config\openssl.cfg";
public const string OpenSslConfig = @"Certs\openssl.cfg";

/// <summary>
/// What version of Director/Composer we're aiming at
Expand Down
1 change: 1 addition & 0 deletions Control4.Jailbreak.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
<None Include="Resources\download.png" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\openssl.cfg" />
<None Include="Resources\patch.png" />
</ItemGroup>
<ItemGroup>
Expand Down
10 changes: 10 additions & 0 deletions Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,7 @@
<data name="database" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\database.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="openssl" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\openssl.cfg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
150 changes: 150 additions & 0 deletions Resources/openssl.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
HOME = .
RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids
[ new_oids ]

tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7

####################################################################
[ ca ]
default_ca = CA_default # The default ca section

####################################################################
[ CA_default ]

dir = ./ca # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.

certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file

x509_extensions = usr_cert # The extentions to add to the cert

# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options

# Extension copying option: use with caution.
# copy_extensions = copy

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext

default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match

# For the CA policy
[ policy_match ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = optional
emailAddress = optional

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = optional
emailAddress = optional

####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
string_mask = utf8only

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2

stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State

localityName = Locality Name (eg, city)

0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd

# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd

organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64

emailAddress = Email Address
emailAddress_max = 64

# SET-ex3 = SET extension number 3

[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20

unstructuredName = An optional company name

[ usr_cert ]

basicConstraints=CA:FALSE

nsComment = "OpenSSL Generated Certificate"

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

[ v3_req ]

basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:true

[ crl_ext ]
authorityKeyIdentifier=keyid:always

[ proxy_cert_ext ]
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

109 changes: 104 additions & 5 deletions UI/Composer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,80 @@ private void UpdateCertificates( object sender, EventArgs e )
{
var log = new LogWindow( MainWindow );

log.WriteNormal( "Copying To Composer\n" );
if ( !PatchComposer( log ) )
try
{
return;
log.WriteNormal( "Copying To Composer\n" );
UpdateComposerCertificate( log );
}
log.WriteNormal( "\n\n" );
catch ( System.Exception ex )
{
log.WriteError( ex );
}
}


bool PatchComposer( LogWindow log )
bool UpdateComposerCertificate( LogWindow log )
{
var configFolder = $"{Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData )}\\Control4\\Composer";

log.WriteNormal( "\nCreating new Composer Key\n" );
var exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"genrsa -out Certs/composer.key 1024 -config \"{Constants.OpenSslConfig}\"" );

if ( exitCode != 0 )
{
log.WriteError( $"Failed." );
return false;
}

log.WriteNormal( "\nCreating Signing Request\n" );
exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"req -new -nodes -key Certs/composer.key -subj /C=US/ST=Utah/L=Draper/CN={Constants.CertificateCN}/ -out Certs/composer.csr -config \"{Constants.OpenSslConfig}\"" );

if ( exitCode != 0 )
{
log.WriteError( $"Failed." );
return false;
}

System.IO.Directory.CreateDirectory( "ca" );
System.IO.Directory.CreateDirectory( "ca/newcerts" );
System.IO.File.WriteAllText( "ca/index.txt", "" );

log.WriteNormal( "\nSigning Request\n" );
exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"ca -subj /C=US/ST=Utah/L=Draper/CN={Constants.CertificateCN}/ -preserveDN -days 365 -batch -create_serial -cert Certs/public.pem -keyfile Certs/private.key -out Certs/composer.pem -in Certs/composer.csr -config \"{Constants.OpenSslConfig}\"" );

if ( exitCode != 0 )
{
log.WriteError( $"Failed." );
return false;
}

//
// Create the composer.p12 (public key) which sits in your composer config folder
//
log.WriteNormal( "Creating composer.p12\n" );
exitCode = RunProcessPrintOutput( log, Constants.OpenSslExe, $"pkcs12 -export -out \"Certs/composer.p12\" -inkey \"Certs/composer.key\" -in \"Certs/composer.pem\" -passout pass:{Constants.CertPassword}" );

if ( exitCode != 0 )
{
log.WriteError( $"Failed." );
return false;
}

//
// Get the text for the composer cacert-*.pem
//
log.WriteNormal( $"Creating {Constants.ComposerCertName}\n" );
var output = RunProcessGetOutput( Constants.OpenSslExe, $"x509 -in \"Certs/public.pem\" -text" );
System.IO.File.WriteAllText( $"Certs/{Constants.ComposerCertName}", output );

CopyFile( log, $"Certs/{Constants.ComposerCertName}", $"{configFolder}\\{Constants.ComposerCertName}" );
CopyFile( log, $"Certs/composer.p12", $"{configFolder}\\composer.p12" );

log.WriteNormal( "\n\n" );
log.WriteSuccess( "Success - composer should be good for 30 days\n\n" );
log.WriteSuccess( "Once it starts complaining that you had x days left to renew, just run this step again\n\n" );
log.WriteSuccess( "You shouldn't need to patch your Director again unless you update to a new version or delete the Certs folder next to this exe.\n\n" );

return true;
}

Expand All @@ -116,5 +174,46 @@ private void CopyFile( LogWindow log, string a, string b )

System.IO.File.Copy( a, b, true );
}

int RunProcessPrintOutput( LogWindow log, string exe, string arguments )
{
log.WriteNormal( System.IO.Path.GetFileName( exe ) );
log.WriteNormal( " " );
log.WriteHighlight( arguments );
log.WriteNormal( "\n" );

ProcessStartInfo startInfo = new ProcessStartInfo( exe, arguments );
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;

var process = System.Diagnostics.Process.Start( startInfo );

log.WriteTrace( process.StandardOutput.ReadToEnd() );
log.WriteTrace( process.StandardError.ReadToEnd() );

process.WaitForExit();

log.WriteTrace( process.StandardError.ReadToEnd() );
log.WriteTrace( process.StandardOutput.ReadToEnd() );

log.WriteNormal( "\n" );

return process.ExitCode;
}

string RunProcessGetOutput( string exe, string arguments )
{
ProcessStartInfo startInfo = new ProcessStartInfo( exe, arguments );
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;

var process = System.Diagnostics.Process.Start( startInfo );

return process.StandardOutput.ReadToEnd();
}
}
}
6 changes: 3 additions & 3 deletions UI/MainWindow.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion UI/MainWindow.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Garry.Control4.Jailbreak.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
Expand All @@ -24,6 +25,13 @@ public MainWindow()
{
InitializeComponent();

if ( !System.IO.Directory.Exists( "Certs" ) )
{
System.IO.Directory.CreateDirectory( "Certs" );
}

System.IO.File.WriteAllBytes( "Certs/openssl.cfg", Resources.openssl );

this.Text += $" - v{Constants.Version} - For C4 v{Constants.TargetDirectorVersion}";

TabControl.TabPages.Clear();
Expand Down

0 comments on commit 0c622f8

Please sign in to comment.