Skip to content

Commit

Permalink
fixes #1
Browse files Browse the repository at this point in the history
  • Loading branch information
t3mi committed Jul 1, 2019
1 parent 2e5623d commit 584ea4f
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -442,12 +442,13 @@ function Set-TargetResource
if ($PSBoundParameters.ContainsKey('Authentication'))
{
# Default Authentication is Anonymous so it's absent in the selection.
switch($Authentication)
switch ($Authentication)
{
'Basic'
{
$mailServer.SetAccount($SMTPAccount.UserName, $SMTPAccount.Password)
}

'Windows'
{
$mailServer.UseDefaultCredentials = $true
Expand Down Expand Up @@ -605,10 +606,17 @@ function Set-TargetResource
)
)

$mailServer.UseDefaultCredentials = switch($Authentication)
$mailServer.UseDefaultCredentials = switch ($Authentication)
{
'Windows' { $true }
Default { $false }
'Windows'
{
$true
}

Default
{
$false
}
}

if ($Authentication -ne 'Basic' -and $currentSMTPAccount.UserName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ $ConfigurationData = @{
Description = 'Default mail account and profile.'
LoggingLevel = 'Normal'
TcpPort = 25
EnableSsl = $true
Authentication = 'Basic'
}
)
}
Expand All @@ -31,12 +29,7 @@ Configuration Example
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$SqlInstallCredential,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$SMTPAccountCredential
$SqlInstallCredential
)

Import-DscResource -ModuleName 'SqlServerDsc'
Expand Down Expand Up @@ -66,9 +59,6 @@ Configuration Example
Description = $Node.Description
LoggingLevel = $Node.LoggingLevel
TcpPort = $Node.TcpPort
EnableSsl = $Node.EnableSsl
Authentication = $Node.Authentication
SMTPAccount = $SMTPAccountCredential

PsDscRunAsCredential = $SqlInstallCredential
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<#
.EXAMPLE
This example will enable Database Mail on a SQL Server instance and
create a mail account with a default public profile.
#>
$ConfigurationData = @{
AllNodes = @(
@{
NodeName = 'localhost'
ServerName = $env:COMPUTERNAME
InstanceName = 'DSCSQLTEST'

MailServerName = 'mail.company.local'
AccountName = 'MyMail'
ProfileName = 'MyMailProfile'
EmailAddress = '[email protected]'
Description = 'Default mail account and profile.'
LoggingLevel = 'Normal'
TcpPort = 25
EnableSsl = $true
}
)
}

Configuration Example
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$SqlInstallCredential
)

Import-DscResource -ModuleName 'SqlServerDsc'

node localhost {

SqlServerConfiguration 'EnableDatabaseMailXPs'
{
ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
OptionName = 'Database Mail XPs'
OptionValue = 1
RestartService = $false
}

SqlServerDatabaseMail 'EnableDatabaseMail'
{
Ensure = 'Present'
ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
AccountName = $Node.AccountName
ProfileName = $Node.ProfileName
EmailAddress = $Node.EmailAddress
ReplyToAddress = $Node.EmailAddress
DisplayName = $Node.MailServerName
MailServerName = $Node.MailServerName
Description = $Node.Description
LoggingLevel = $Node.LoggingLevel
TcpPort = $Node.TcpPort
EnableSsl = $Node.EnableSsl

PsDscRunAsCredential = $SqlInstallCredential
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<#
.EXAMPLE
This example will enable Database Mail on a SQL Server instance and
create a mail account with a default public profile.
#>
$ConfigurationData = @{
AllNodes = @(
@{
NodeName = 'localhost'
ServerName = $env:COMPUTERNAME
InstanceName = 'DSCSQLTEST'

MailServerName = 'mail.company.local'
AccountName = 'MyMail'
ProfileName = 'MyMailProfile'
EmailAddress = '[email protected]'
Description = 'Default mail account and profile.'
LoggingLevel = 'Normal'
TcpPort = 25
Authentication = 'Basic'
}
)
}

Configuration Example
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$SqlInstallCredential,

[Parameter()]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$SMTPAccountCredential
)

Import-DscResource -ModuleName 'SqlServerDsc'

node localhost {

SqlServerConfiguration 'EnableDatabaseMailXPs'
{
ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
OptionName = 'Database Mail XPs'
OptionValue = 1
RestartService = $false
}

SqlServerDatabaseMail 'EnableDatabaseMail'
{
Ensure = 'Present'
ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
AccountName = $Node.AccountName
ProfileName = $Node.ProfileName
EmailAddress = $Node.EmailAddress
ReplyToAddress = $Node.EmailAddress
DisplayName = $Node.MailServerName
MailServerName = $Node.MailServerName
Description = $Node.Description
LoggingLevel = $Node.LoggingLevel
TcpPort = $Node.TcpPort
Authentication = $Node.Authentication
SMTPAccount = $SMTPAccountCredential

PsDscRunAsCredential = $SqlInstallCredential
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ $ConfigurationData = @{
AccountName = 'MyMail'
ProfileName = 'MyMailProfile'
EmailAddress = '[email protected]'
Description = 'Default mail account and profile.'
LoggingLevel = 'Normal'
TcpPort = 25
}
)
}
Expand All @@ -34,7 +31,8 @@ Configuration Example

Import-DscResource -ModuleName 'SqlServerDsc'

node localhost {
Node localhost {

SqlServerDatabaseMail 'DisableDatabaseMail'
{
Ensure = 'Absent'
Expand All @@ -54,7 +52,6 @@ Configuration Example
#>
SqlServerConfiguration 'DisableDatabaseMailXPs'
{

ServerName = $Node.ServerName
InstanceName = $Node.InstanceName
OptionName = 'Database Mail XPs'
Expand Down
80 changes: 41 additions & 39 deletions Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2548,9 +2548,8 @@ function Get-MailServerCredentialId
String containing the SQL Server Database Engine instance to connect to.
.NOTES
This function is based on Antti Rantasaari's script at https://github.com/NetSPI/Powershell-Modules/blob/master/Get-MSSQLCredentialPasswords.psm1
Antti Rantasaari 2014, NetSPI
License: BSD 3-Clause http://opensource.org/licenses/BSD-3-Clause
Details on Service Master Key protection could be found at
https://blogs.msdn.microsoft.com/stuartpa/2005/09/25/protecting-the-sql-server-2005-service-master-key-the-root-of-all-encryption/
#>
function Get-ServiceMasterKey
{
Expand Down Expand Up @@ -2578,20 +2577,19 @@ function Get-ServiceMasterKey
}

$queryToGetServiceMasterKey = "
SELECT substring(crypt_property,9,len(crypt_property)-8) AS ServiceMasterKey
SELECT crypt_property AS 'key'
FROM sys.key_encryptions
WHERE key_id=102 and (thumbprint=0x03 or thumbprint=0x0300000001)
WHERE key_id=102 and thumbprint<>0x01
"

Write-Verbose -Message ($script:localizedData.GetServiceMasterKey -f $SQLInstanceName) -Verbose
$smkEncryptedBytes = (Invoke-Query @invokeQueryParameters -Query $queryToGetServiceMasterKey).Tables[0].ServiceMasterKey
$encryptedServiceMasterKey = (Invoke-Query @invokeQueryParameters -Query $queryToGetServiceMasterKey).Tables[0].key | Select-Object -Skip 8

Write-Verbose -Message ($script:localizedData.GetEntropyForSqlInstance -f $SQLInstanceName) -Verbose
$sqlInstanceId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' -ErrorAction Stop).$SQLInstanceName
[byte[]]$entropy = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$sqlInstanceId\Security" -ErrorAction Stop).Entropy
$instanceId = Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' -Name $SQLInstanceName
$entropy = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$instanceId\Security" -Name 'Entropy'

# Decrypt the service master key
$serviceMasterKey = [System.Security.Cryptography.ProtectedData]::Unprotect($smkEncryptedBytes, $entropy, 'LocalMachine')
$serviceMasterKey = [System.Security.Cryptography.ProtectedData]::Unprotect($encryptedServiceMasterKey, $entropy, [System.Security.Cryptography.DataProtectionScope]::LocalMachine)

return $serviceMasterKey
}
Expand All @@ -2608,9 +2606,9 @@ function Get-ServiceMasterKey
.PARAMETER CredentialId
Specifies Id of the credential for which MSFT_Credential should be returned.
.NOTES
This function is partialy based on Antti Rantasaari's script at https://github.com/NetSPI/Powershell-Modules/blob/master/Get-MSSQLCredentialPasswords.psm1
Details on cryptographic message description could be found at
https://blogs.msdn.microsoft.com/sqlsecurity/2009/03/30/sql-server-encryptbykey-cryptographic-message-description/
#>
function Get-SqlPSCredential
{
Expand Down Expand Up @@ -2643,56 +2641,60 @@ function Get-SqlPSCredential

$smk = Get-ServiceMasterKey -SQLServer $SQLServer -SQLInstanceName $SQLInstanceName

<#
Choose the encryption algorithm based on the Service Master Key length - 3DES for 2008, AES for 2012+
Choose initialization vector (IV) length based on the algorithm
#>
switch($smk.Length)
switch ($smk.Length)
{
16 { $cryptoProvider = New-Object System.Security.Cryptography.TripleDESCryptoServiceProvider }
16
{
$typeName = 'System.Security.Cryptography.TripleDESCryptoServiceProvider'
}

32 { $cryptoProvider = New-Object System.Security.Cryptography.AESCryptoServiceProvider }
32
{
$typeName = 'System.Security.Cryptography.AESCryptoServiceProvider'
}

default
{
$errorMessage = $script:localizedData.UnknownSmkSize -f $smk.Length, $SQLInstanceName
$errorMessage = $script:localizedData.SmkSizeNotImplemented -f $smk.Length, $SQLInstanceName
New-InvalidResultException -Message $errorMessage
}
}

$cryptoProvider.Padding = 'PKCS7'
$cryptoProvider.Mode = 'CBC'
$ivLen = $cryptoProvider.IV.length

$queryToGetEncryptedCredential = "
SELECT credential_identity AS username,substring(imageval,5,$ivLen) AS iv, substring(imageval,$($ivLen + 5),len(imageval)-$($ivLen + 4)) AS enc_message
FROM sys.credentials as cred
INNER JOIN sys.sysobjvalues AS obj
ON cred.credential_id = obj.objid
# Get encrypted message without encryption header which is 4 bytes
$queryToGetEncryptedMessage = "
SELECT credential_identity AS username, substring(imageval, 5, len(imageval)-4) AS enc_message
FROM sys.credentials as c
INNER JOIN sys.sysobjvalues AS o
ON c.credential_id = o.objid
WHERE valclass=28 and valnum=2 and objid=$CredentialId
"

Write-Verbose -Message ($script:localizedData.GetEncryptedCredential -f $CredentialId, $SQLInstanceName) -Verbose
$credInfo = (Invoke-Query @invokeQueryParameters -Query $queryToGetEncryptedCredential).Tables[0]
Write-Verbose -Message ($script:localizedData.GetEncryptedMessage -f $CredentialId, $SQLInstanceName) -Verbose
$credInfo = (Invoke-Query @invokeQueryParameters -Query $queryToGetEncryptedMessage).Tables[0]

$message = New-Object Byte[]($credInfo.enc_message.Length)
$decryptor = $cryptoProvider.CreateDecryptor($smk, $credInfo.iv)
$memoryStream = New-Object System.IO.MemoryStream (,$credInfo.enc_message)
$cryptoProvider = New-Object -TypeName $typeName
$cryptoProvider.Key = $smk
# Extract and set Initialization Vector (IV)
$cryptoProvider.IV = $credInfo.enc_message[0..$($cryptoProvider.IV.Length - 1)]
$cryptoProvider.Padding = 'PKCS7'
$cryptoProvider.Mode = 'CBC'

# Set length of the inner message
$message = New-Object Byte[]($credInfo.enc_message.Length - $cryptoProvider.IV.Length)
$decryptor = $cryptoProvider.CreateDecryptor()
$memoryStream = New-Object System.IO.MemoryStream (,$credInfo.enc_message[$cryptoProvider.IV.Length..($credInfo.enc_message.Length - 1)])
$cryptoStream = New-Object System.Security.Cryptography.CryptoStream ($memoryStream, $decryptor, [System.Security.Cryptography.CryptoStreamMode]::Read)
$messageLength = $cryptoStream.Read($message, 0, $message.Length)
$cryptoStream.Close()
$memoryStream.Close()
$cryptoProvider.Clear()

<#
verifying magic number using bytes from 0 to 3
according to https://blogs.msdn.microsoft.com/sqlsecurity/2009/03/30/sql-server-encryptbykey-cryptographic-message-description/
#>
# Verifying magic number using bytes from 0 to 3
if ([System.BitConverter]::ToString($message[3..0]) -ne 'BA-AD-F0-0D')
{
Write-Warning -Message $script:localizedData.FailedCredentialDecryption
}
# getting password length using bytes at 6 and 7
# Getting password length using bytes 6 and 7
$len = [System.BitConverter]::ToInt16($message[6..7],0)

# Convert password to secure string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ ConvertFrom-StringData @'
GetMailServerCredentialId = Getting credential Id used by SMTP mail server '{0}' on instance '{1}'. (SQLCOMMON0057)
GetServiceMasterKey = Getting service master key on instance '{0}'. (SQLCOMMON0058)
GetEntropyForSqlInstance = Getting entropy information from the registry for instance '{0}'. (SQLCOMMON0059)
GetEncryptedCredential = Getting encrypted password for credential with id '{0}' on instance '{1}'. (SQLCOMMON0060)
UnknownSmkSize = Unknown size '{0}' of Service Master Key for instance '{1}'. Valid values are '16' and '32'. (SQLCOMMON0061)
GetEncryptedMessage = Getting encrypted message for credential with id '{0}' on instance '{1}'. (SQLCOMMON0060)
SmkSizeNotImplemented = Unknown size '{0}' of Service Master Key for instance '{1}'. Valid values are '16' and '32'. (SQLCOMMON0061)
FailedCredentialDecryption = Decryption possibly failed or encrypted string was modfiied as magic number doesn't match. (SQLCOMMON0062)
'@
Loading

0 comments on commit 584ea4f

Please sign in to comment.