Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

112 рядки
5.4KB

  1. $ErrorActionPreference = 'Stop'
  2. function Get-MailContext {
  3. param([string]$ConfigPath = (Join-Path (Split-Path -Parent $PSScriptRoot) 'config.ini'))
  4. $settings = @{}
  5. foreach ($line in Get-Content -LiteralPath $ConfigPath -Encoding UTF8) {
  6. $trimmed = $line.Trim()
  7. if (-not $trimmed -or $trimmed.StartsWith('#') -or $trimmed.StartsWith(';')) { continue }
  8. $parts = $trimmed.Split('=', 2)
  9. if ($parts.Count -ne 2) { throw "Invalid configuration line in $ConfigPath" }
  10. $name = $parts[0].Trim().ToUpperInvariant()
  11. if ($settings.ContainsKey($name)) { throw "Duplicate setting: $name" }
  12. $settings[$name] = $parts[1].Trim()
  13. }
  14. foreach ($name in @('DB_PATH', 'DB_PROVIDER', 'DB_BITNESS', 'SMTP_SECRET_ID', 'SMTP_USER')) {
  15. if (-not $settings.ContainsKey($name) -or -not $settings[$name]) {
  16. throw "Missing setting: $name"
  17. }
  18. }
  19. if ($settings['DB_PROVIDER'] -notin @('Microsoft.Jet.OLEDB.4.0',
  20. 'Microsoft.ACE.OLEDB.12.0', 'Microsoft.ACE.OLEDB.16.0')) {
  21. throw 'Unsupported DB_PROVIDER'
  22. }
  23. $actualBitness = if ([IntPtr]::Size -eq 4) { 'x86' } else { 'x64' }
  24. if ($settings['DB_BITNESS'] -ne $actualBitness) {
  25. throw "Run this setup under $($settings['DB_BITNESS']) PowerShell"
  26. }
  27. $databasePath = $settings['DB_PATH']
  28. if ($databasePath.StartsWith('\\')) { throw 'DB_PATH must be on a local drive' }
  29. if (-not [System.IO.Path]::IsPathRooted($databasePath)) {
  30. $databasePath = Join-Path (Split-Path -Parent $PSScriptRoot) $databasePath
  31. }
  32. $databasePath = [System.IO.Path]::GetFullPath($databasePath)
  33. if ([System.IO.Path]::GetExtension($databasePath) -ne '.mdb') { throw 'DB_PATH must end in .mdb' }
  34. if (-not (Test-Path -LiteralPath $databasePath -PathType Leaf)) {
  35. throw "MDB not found: $databasePath"
  36. }
  37. return @{ Settings = $settings; DatabasePath = $databasePath }
  38. }
  39. function Open-MailDatabase {
  40. param($Context)
  41. $builder = New-Object System.Data.OleDb.OleDbConnectionStringBuilder
  42. $builder.Provider = $Context.Settings['DB_PROVIDER']
  43. $builder['Data Source'] = $Context.DatabasePath
  44. $connection = New-Object System.Data.OleDb.OleDbConnection($builder.ConnectionString)
  45. $connection.Open()
  46. return $connection
  47. }
  48. function Save-SmtpPassword {
  49. param($Context, [System.Security.SecureString]$Password)
  50. $encrypted = ConvertFrom-SecureString -SecureString $Password
  51. $bytes = [System.Text.Encoding]::UTF8.GetBytes($encrypted)
  52. $connection = Open-MailDatabase $Context
  53. try {
  54. $check = $connection.CreateCommand()
  55. $check.CommandText = 'SELECT COUNT(*) FROM [ProtectedSecret] WHERE [Id]=?'
  56. $null = $check.Parameters.Add('id', [System.Data.OleDb.OleDbType]::VarWChar, 100)
  57. $check.Parameters[0].Value = $Context.Settings['SMTP_SECRET_ID']
  58. $exists = [int]$check.ExecuteScalar() -gt 0
  59. if ($exists) {
  60. $command = $connection.CreateCommand()
  61. $command.CommandText = 'UPDATE [ProtectedSecret] SET [DpapiCiphertext]=?, [RotatedAtUtc]=? WHERE [Id]=?'
  62. $null = $command.Parameters.Add('ciphertext', [System.Data.OleDb.OleDbType]::LongVarBinary, $bytes.Length)
  63. $command.Parameters[0].Value = $bytes
  64. $null = $command.Parameters.Add('rotated', [System.Data.OleDb.OleDbType]::Date)
  65. $command.Parameters[1].Value = [DateTime]::UtcNow
  66. $null = $command.Parameters.Add('id', [System.Data.OleDb.OleDbType]::VarWChar, 100)
  67. $command.Parameters[2].Value = $Context.Settings['SMTP_SECRET_ID']
  68. }
  69. else {
  70. $command = $connection.CreateCommand()
  71. $command.CommandText = 'INSERT INTO [ProtectedSecret] ([Id],[Purpose],[DpapiCiphertext],[CreatedAtUtc]) VALUES (?,?,?,?)'
  72. $null = $command.Parameters.Add('id', [System.Data.OleDb.OleDbType]::VarWChar, 100)
  73. $command.Parameters[0].Value = $Context.Settings['SMTP_SECRET_ID']
  74. $null = $command.Parameters.Add('purpose', [System.Data.OleDb.OleDbType]::VarWChar, 50)
  75. $command.Parameters[1].Value = 'smtp_password'
  76. $null = $command.Parameters.Add('ciphertext', [System.Data.OleDb.OleDbType]::LongVarBinary, $bytes.Length)
  77. $command.Parameters[2].Value = $bytes
  78. $null = $command.Parameters.Add('created', [System.Data.OleDb.OleDbType]::Date)
  79. $command.Parameters[3].Value = [DateTime]::UtcNow
  80. }
  81. $null = $command.ExecuteNonQuery()
  82. }
  83. finally {
  84. $connection.Dispose()
  85. [Array]::Clear($bytes, 0, $bytes.Length)
  86. }
  87. }
  88. function Load-SmtpPassword {
  89. param($Context)
  90. $connection = Open-MailDatabase $Context
  91. try {
  92. $command = $connection.CreateCommand()
  93. $command.CommandText = 'SELECT [DpapiCiphertext] FROM [ProtectedSecret] WHERE [Id]=? AND [Purpose]=?'
  94. $null = $command.Parameters.Add('id', [System.Data.OleDb.OleDbType]::VarWChar, 100)
  95. $command.Parameters[0].Value = $Context.Settings['SMTP_SECRET_ID']
  96. $null = $command.Parameters.Add('purpose', [System.Data.OleDb.OleDbType]::VarWChar, 50)
  97. $command.Parameters[1].Value = 'smtp_password'
  98. $bytes = $command.ExecuteScalar()
  99. if ($null -eq $bytes -or $bytes -is [DBNull]) { throw 'SMTP password is not configured' }
  100. $encrypted = [System.Text.Encoding]::UTF8.GetString($bytes)
  101. return ConvertTo-SecureString -String $encrypted
  102. }
  103. finally {
  104. $connection.Dispose()
  105. }
  106. }

Powered by TurnKey Linux.