'use strict'; const { spawn } = require('child_process'); // Sets a user's password via PowerShell/ADSI (IADsUser.SetPassword). // On a domain-joined machine ADSI negotiates a Kerberos signed/sealed // connection, which Active Directory accepts as a "protected channel" // for unicodePwd — unlike a plain LDAP bind over TCP (AD error 53). // // The DN and password are passed via environment variables so they never // appear in the process command line, and the script body is pure ASCII // (no encoding issues with Windows PowerShell 5.1). The script itself is // sent over stdin to avoid temp files. function setPasswordViaPowerShell(userDN, password, { exe = 'powershell.exe', timeoutMs = 15000 } = {}) { return new Promise((resolve, reject) => { const script = [ '$ErrorActionPreference = "Stop"', '$dn = [Environment]::GetEnvironmentVariable("LDAP_PW_DN")', '$pw = [Environment]::GetEnvironmentVariable("LDAP_PW_VALUE")', '$user = [adsi]("LDAP://" + $dn)', '$user.SetPassword($pw)' ].join('; '); let child; try { child = spawn(exe, ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', '-'], { env: { ...process.env, LDAP_PW_DN: userDN, LDAP_PW_VALUE: password }, windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); } catch (err) { reject(new Error(`Не удалось запустить PowerShell для установки пароля: ${err.message}`)); return; } let stdout = ''; let stderr = ''; let timedOut = false; const timer = setTimeout(() => { timedOut = true; try { child.kill(); } catch (_) { /* ignore */ } }, timeoutMs); child.stdout.on('data', (d) => { stdout += d; }); child.stderr.on('data', (d) => { stderr += d; }); child.on('error', (err) => { clearTimeout(timer); reject(new Error(`Не удалось запустить PowerShell для установки пароля: ${err.message}`)); }); child.on('close', (code) => { clearTimeout(timer); if (timedOut) { reject(new Error('Таймаут при установке пароля через PowerShell')); return; } if (code === 0) { resolve(); return; } const detail = String(stderr || stdout || '').trim(); reject(new Error(`Ошибка установки пароля через PowerShell (код ${code})${detail ? ': ' + detail : ''}`)); }); child.stdin.end(script); }); } module.exports = setPasswordViaPowerShell;