<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://dev.hexed.pw</id>
    <title>flameshikari</title>
    <updated>2026-04-15T08:44:03.737Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <author>
        <name>flameshikari</name>
        <email>mail@hexed.pw</email>
        <uri>https://dev.hexed.pw</uri>
    </author>
    <link rel="alternate" href="https://dev.hexed.pw"/>
    <link rel="self" href="https://dev.hexed.pw/atom"/>
    <subtitle>shitposting agency</subtitle>
    <logo>https://dev.hexed.pw/favicon.png</logo>
    <icon>https://dev.hexed.pw/favicon.ico</icon>
    <rights>© flameshikari 2024–2026</rights>
    <category term="ffmpeg"/>
    <category term="huawei"/>
    <category term="keepass"/>
    <category term="linux"/>
    <category term="ndi"/>
    <category term="proxmox"/>
    <category term="shell"/>
    <category term="ssh"/>
    <category term="testing"/>
    <category term="windows"/>
    <category term="wsl"/>
    <entry>
        <title type="html"><![CDATA[lorem ipsum]]></title>
        <id>0</id>
        <link href="https://dev.hexed.pw/logs/lorem_ipsum/"/>
        <link rel="enclosure" href="https://dev.hexed.pw/logs/lorem_ipsum/header.png" type="image/png"/>
        <updated>2000-01-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[dolor sit amet]]></summary>
        <content type="html"><![CDATA[<p><img src="https://dev.hexed.pw/logs/lorem_ipsum/assets/_header.png" alt=""></p>
<p><em>Lorem ipsum dolor sit amet</em>, <strong>consectetur adipiscing elit</strong>, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
]]></content>
        <author>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </author>
        <contributor>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </contributor>
    </entry>
    <entry>
        <title type="html"><![CDATA[OmniKeePass]]></title>
        <id>1</id>
        <link href="https://dev.hexed.pw/logs/omnikeepass/"/>
        <link rel="enclosure" href="https://dev.hexed.pw/logs/omnikeepass/header.png" type="image/png"/>
        <updated>2024-01-09T07:12:12.000Z</updated>
        <summary type="html"><![CDATA[Making KeePassXC to work with both WSL and Windows envs]]></summary>
        <content type="html"><![CDATA[<p><img src="https://dev.hexed.pw/logs/omnikeepass/assets/_header.png" alt=""></p>
<p>Greetings!</p>
<p>A rather strange first post for my blog, but I have to start somewhere. Sorry in advance for any language mistakes.</p>
<p>But first, a short preface.
Please, don&#39;t be that person who doesn&#39;t care about personal data on the Internet.
Use local/self-hosted password managers (not <a href="https://blog.lastpass.com/2022/12/notice-of-recent-security-incident/">the cloud ones</a>), generate different and strong passwords, use 2FA and make backups.
These words are based on my personal expirience; I used to be the person who doesn&#39;t care, but as I grew up, I realized how vulnerable we are on the Internet, and after several data leaks and hacking attempts, I started using all kinds of safe solutions. 
Don&#39;t be indifferent to your data, otherwise you may regret it.</p>
<p>So, let&#39;s get to the topic.</p>
<p>For a long time I used <a href="https://keepass.info/">KeePass</a> with <a href="https://lechnology.com/software/keeagent/">KeeAgent</a> plugin for forwarding SSH keys from the database to an SSH agent, and it was awesome.
What I liked about this combo:</p>
<ul>
<li><p>If the database is closed and you are trying to connect via SSH, <a href="https://lechnology.com/software/keeagent/">KeeAgent</a> calls <a href="https://keepass.info/">KeePass</a> to open a database for unlocking, and after unlocking the keys will be added to <a href="https://lechnology.com/software/keeagent/">KeeAgent</a>;</p>
</li>
<li><p><a href="https://lechnology.com/software/keeagent/">KeeAgent</a> stores credentials in a non-persist way.</p>
</li>
</ul>
<p>Recently I decided to move to <a href="https://keepassxc.org/">KeePassXC</a> as it has better browser integration and a nicer interface. Since it relies on external agents (<a href="https://github.com/PowerShell/Win32-OpenSSH">Windows OpenSSH</a> or <a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/">Pageant</a>), things I liked don&#39;t work here. I&#39;m used to this, I&#39;ll try to replicate the functionality!</p>
<p>First I started looking for a suitable agent, as supported agents have issues:</p>
<ul>
<li><p><a href="https://github.com/PowerShell/Win32-OpenSSH/issues/1487">Windows OpenSSH stores keys in Windows Registry</a>. For example, if you hard reset a computer keys will remain in the registry (sounds insecure, huh?). Using startup scripts for clearing the agent isn&#39;t the way. Also, there&#39;s <a href="https://github.com/HiFiPhile/openssh-cleaned">a fork of Windows OpenSSH</a> that stores credentials in a non-persist way, but I wanna rely on the upstream version.</p>
</li>
<li><p>Recent versions of <a href="https://the.earth.li/%7Esgtatham/putty/0.78/htmldoc/Chapter9.html#pageant-cmdline-openssh">Pageant can integrate with Windows OpenSSH</a>. Unfortunately, the named pipe path changes each reboot. The issue can be solved with bash/pwsh magic, but I&#39;m trying to make as few dirty hacks as possible (it will sound more ironic when you continue reading that article).</p>
</li>
</ul>
<p>I continued my search for the agent that suits my needs. I found <a href="https://github.com/masahide/OmniSSHAgent">OmniSSHAgent</a>, and it turned out that this is the best solution. It stores keys in a non-persist way and supports all communication interfaces:</p>
<p><img src="https://dev.hexed.pw/logs/omnikeepass/assets/omnisshagent_diagram.svg" alt=""></p>
<p>Isn&#39;t this a dream?</p>
<p>To use the named pipe from Windows in <a href="https://learn.microsoft.com/en-us/windows/wsl/about">WSL2</a> I could use <a href="http://www.dest-unreach.org/socat/">socat</a> utility, but I decided to use <a href="https://github.com/mame/wsl2-ssh-agent">wsl2-ssh-agent</a>, which <a href="https://github.com/mame/wsl2-ssh-agent#how-wsl2-ssh-agent-works">makes a communication bridge between Windows and WSL2 with PowerShell</a>.</p>
<p><img src="https://dev.hexed.pw/logs/omnikeepass/assets/wsl2-ssh-agent_diagram.svg" alt=""></p>
<!-- > 1. [Microsoft Edge WebView2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) is needed to work, but it's like it's available out of the box -->


<p>Alright, I need to place these utilities somewhere.
I thought: what if I put configs and utilities in Windows&#39; <font class="hljs-attribute">%USERPROFILE%/.ssh</font> and just link that path to <a href="https://learn.microsoft.com/en-us/windows/wsl/about">WSL2</a>&#39;s <font class="hljs-attribute">~/.ssh</font> to have the same config for both environments?
Without <a href="https://learn.microsoft.com/en-us/windows/wsl/wsl-config#automount-options">additional WSL2 tuning</a>, it will not work.
The problem is that Windows files inside <a href="https://learn.microsoft.com/en-us/windows/wsl/about">WSL2</a> don&#39;t store Linux permissions by default, so most Windows files will have all <a href="https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation">rwx</a> bits, and this will cause SSH clients to throw permission errors. To fix that, I edited <font class="hljs-attribute">/etc/wsl.conf</font>:</p>
<pre><code class="highlight highlight-ini"><span class="pl-en">[automount]</span>
<span class="pl-k">options</span> = <span class="pl-s"><span class="pl-pds">"</span>metadata<span class="pl-pds">"</span></span>
</code></pre><p>Before linking directories, I moved <font class="hljs-attribute">%USERPROFILE%\.ssh</font> to <font class="hljs-attribute">%USERPROFILE%\.ssh.bak</font>, created <font class="hljs-attribute">%USERPROFILE%\.ssh</font>, also moved <font class="hljs-attribute">~/.ssh</font> to <font class="hljs-attribute">~/.ssh.bak</font>. 
After that ran this command:</p>
<pre><code class="highlight highlight-bash">ln -sTv /mnt/c/Users/<span class="pl-s"><span class="pl-pds">$(</span>pwsh.exe -c <span class="pl-pds">'</span>$env:USERNAME<span class="pl-pds">'</span> <span class="pl-k">|</span> tr -d <span class="pl-pds">'</span>\r<span class="pl-pds">')</span></span>/.ssh <span class="pl-smi">$HOME</span>/.ssh
</code></pre><p>Downloaded utilities were placed in <font class="hljs-attribute">~/.ssh/bin</font>.
I added <font class="hljs-string">Include aliases/*</font> in <font class="hljs-attribute">~/.ssh/config</font> to separate aliases between files.
It&#39;s very handy thing for me.
For example, <font class="hljs-attribute">~/.ssh/aliases/git</font> contains aliases for different repo-based platforms:</p>
<pre><code class="highlight highlight-yaml"><span class="pl-s">Host github</span>
  <span class="pl-s">Hostname github.com</span>
  <span class="pl-s">User git</span>

<span class="pl-s">Host gitlab</span>
  <span class="pl-s">Hostname gitlab.com</span>
  <span class="pl-s">User git</span>
</code></pre><p>Then I wrote <a href="https://dev.hexed.pw/logs/omnikeepass/data/ssh/bin/fix-perms.sh">fix-perms.sh</a> for fixing file permissions (mostly needed to run once after linking directories) and placed it in <font class="hljs-attribute">~/.ssh/bin</font>:</p>
<pre><code class="highlight highlight-sh"><span class="pl-c">#!/usr/bin/env bash</span>
<span class="pl-c1">cd</span> <span class="pl-smi">$HOME</span>/.ssh
chmod 600 authorized_keys config known_hosts<span class="pl-k">*</span> aliases/<span class="pl-k">*</span>
chmod 700 bin/<span class="pl-k">*</span>
</code></pre><p>At this moment I have the next file structure:</p>
<pre><code class="highlight highlight-plaintext">~/.ssh
├── authorized_keys
├── bin
│   ├── init.sh
│   ├── middleware.ps1
│   ├── omni-ssh-agent.exe
│   └── wsl2-ssh-agent
├── config
├── hosts
│   ├── git
│   ├── home
│   └── work
├── known_hosts
└── sockets
    ├── cygwin.socket
    ├── unix.socket
    └── wsl.sock
</code></pre><p>Appended the following command to <font class="hljs-attribute">~/.bashrc</font>:</p>
<pre><code class="highlight highlight-bash"><span class="pl-c1">eval</span> <span class="pl-s"><span class="pl-pds">$(</span><span class="pl-smi">$HOME</span>/.ssh/bin/wsl2-ssh-agent -socket /tmp/wsl.sock<span class="pl-pds">)</span></span>
</code></pre><p>Enabled these options in <a href="https://github.com/masahide/OmniSSHAgent">OmniSSHAgent</a>&#39;s settings:</p>
<p><img src="https://dev.hexed.pw/logs/omnikeepass/assets/omnisshagent_settings.png" alt=""></p>
<p>Made sure that <a href="https://keepassxc.org/">KeePassXC</a> is correctly configured for integration with the agent:</p>
<p><img src="https://dev.hexed.pw/logs/omnikeepass/assets/kpxc_agent_settings.png" alt=""></p>
<p>And entries with a key are configured for adding to the agent:</p>
<p><img src="https://dev.hexed.pw/logs/omnikeepass/assets/kpxc_entry_settings.png" alt=""></p>
<p>Amazing, I got almost everything I need and configured all utilities.
At this moment, the named pipe will be accessible by any program that supports it from both environments.</p>
<p>So, how can I replicate the behavior of <a href="https://lechnology.com/software/keeagent/">KeeAgent</a> when the database is locked?</p>
<p>At first, I decided to write a script that would replicate the behavior of <a href="https://lechnology.com/software/keeagent/">KeeAgent</a>.
Remember what I said about the irony? <a href="https://dev.hexed.pw/logs/omnikeepass/data/ssh/bin/wrapper.ps1">This is it</a>:</p>
<pre><code class="highlight highlight-powershell"><span class="pl-c">#!/usr/bin/env -S pwsh.exe</span>

<span class="pl-smi">$Database</span> <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">"</span>B:\Cloud\Secrets.kdbx<span class="pl-pds">"</span></span>

<span class="pl-smi">$Agent</span> <span class="pl-k">=</span> <span class="pl-c1">Get-ChildItem</span> <span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">$PSScriptRoot</span>\omni-ssh-agent.exe<span class="pl-pds">"</span></span>
<span class="pl-smi">$Keepass</span> <span class="pl-k">=</span> <span class="pl-c1">Get-ChildItem</span> <span class="pl-s"><span class="pl-pds">"</span>B:\Programs\KeePassXC\KeePassXC.exe<span class="pl-pds">"</span></span>

<span class="pl-smi">$KeepassWidth</span> <span class="pl-k">=</span> <span class="pl-c1">1280</span>
<span class="pl-smi">$KeepassHeight</span> <span class="pl-k">=</span> <span class="pl-c1">720</span>
<span class="pl-smi">$KeepassFocused</span> <span class="pl-k">=</span> <span class="pl-c1">$False</span>
<span class="pl-smi">$AgentHasNoKeys</span> <span class="pl-k">=</span> <span class="pl-c1">$False</span>

<span class="pl-c1">Add-Type</span> <span class="pl-k">-</span>AssemblyName System.Windows.Forms

<span class="pl-c1">Add-Type</span> <span class="pl-s"><span class="pl-pds">@"</span></span>
<span class="pl-s">    using System;</span>
<span class="pl-s">    using System.Runtime.InteropServices;</span>
<span class="pl-s">    public class WinAPI {</span>
<span class="pl-s">        [DllImport("user32.dll")]</span>
<span class="pl-s">        public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);</span>
<span class="pl-s">        [DllImport("user32.dll")]</span>
<span class="pl-s">        public static extern IntPtr GetForegroundWindow();</span>
<span class="pl-s">        [DllImport("user32.dll")]</span>
<span class="pl-s">        [return: MarshalAs(UnmanagedType.Bool)]</span>
<span class="pl-s">        public static extern bool IsIconic(IntPtr hWnd);</span>
<span class="pl-s">    }</span>
<span class="pl-s"><span class="pl-pds">"@</span></span>

<span class="pl-k">Function</span> <span class="pl-en">Agent-Start</span> {
    <span class="pl-c1">Start-Process</span> <span class="pl-k">-</span>PassThru <span class="pl-smi">$Agent</span> <span class="pl-k">|</span> <span class="pl-c1">Out-Null</span>
    <span class="pl-c1">Start-Sleep</span> <span class="pl-c1">0.5</span>
}

<span class="pl-k">Function</span> <span class="pl-en">Agent-Status</span> {
	<span class="pl-smi">$Output</span> <span class="pl-k">=</span> (C:\Windows\System32\OpenSSH\ssh<span class="pl-k">-</span>add <span class="pl-k">-</span>l <span class="pl-k">2>&#x26;1</span> <span class="pl-k">|</span> <span class="pl-c1">Out-Null</span>)
	<span class="pl-k">Return</span> <span class="pl-c1">$LastExitCode</span>
}

<span class="pl-k">Function</span> <span class="pl-en">Agent-Isnt-Running</span> {
    <span class="pl-k">Return</span> <span class="pl-k">-Not</span> (<span class="pl-c1">Get-Process</span> <span class="pl-k">-</span>ErrorAction SilentlyContinue <span class="pl-smi">$Agent.BaseName</span> <span class="pl-k">|</span> Select <span class="pl-k">-</span>Expand ProcessName)
}

<span class="pl-k">Function</span> <span class="pl-en">Keepass-Start</span> {
    <span class="pl-k">Param</span>([<span class="pl-k">String</span>[]]<span class="pl-smi">$ArgumentList</span> <span class="pl-k">=</span> <span class="pl-smi">$Database</span><span class="pl-k">,</span> [<span class="pl-k">Int</span>]<span class="pl-smi">$Width</span> <span class="pl-k">=</span> <span class="pl-smi">$KeepassWidth</span><span class="pl-k">,</span> [<span class="pl-k">Int</span>]<span class="pl-smi">$Height</span> <span class="pl-k">=</span> <span class="pl-smi">$KeepassHeight</span>)
    <span class="pl-c1">Start-Process</span> <span class="pl-k">-</span>PassThru <span class="pl-smi">$Keepass</span> <span class="pl-k">-</span>ArgumentList <span class="pl-smi">$ArgumentList</span> <span class="pl-k">|</span> <span class="pl-c1">Out-Null</span>
    <span class="pl-c1">Start-Sleep</span> <span class="pl-c1">0.1</span>
    <span class="pl-smi">$Process</span> <span class="pl-k">=</span> <span class="pl-c1">Get-Process</span> <span class="pl-k">-</span>Name <span class="pl-smi">$Keepass.BaseName</span> <span class="pl-k">-</span>ErrorAction SilentlyContinue <span class="pl-k">|</span> <span class="pl-c1">Select-Object</span> <span class="pl-k">-</span>First <span class="pl-c1">1</span>
    <span class="pl-k">If</span> (<span class="pl-k">-Not</span> <span class="pl-smi">$Process</span>) { <span class="pl-k">Return</span> <span class="pl-c1">$False</span> }
    <span class="pl-smi">$Handle</span> <span class="pl-k">=</span> <span class="pl-smi">$Process.MainWindowHandle</span>
    <span class="pl-k">If</span> (<span class="pl-smi">$Handle</span> <span class="pl-k">-eq</span> <span class="pl-c1">0</span>) { <span class="pl-k">Return</span> <span class="pl-c1">$False</span> }
    <span class="pl-smi">$ScreenWidth</span> <span class="pl-k">=</span> [<span class="pl-k">System.Windows.Forms.Screen</span>]::PrimaryScreen.WorkingArea.Width
    <span class="pl-smi">$ScreenHeight</span> <span class="pl-k">=</span> [<span class="pl-k">System.Windows.Forms.Screen</span>]::PrimaryScreen.WorkingArea.Height
    <span class="pl-smi">$X</span> <span class="pl-k">=</span> [<span class="pl-k">Math</span>]::Max(<span class="pl-c1">0</span><span class="pl-k">,</span> (<span class="pl-smi">$ScreenWidth</span> <span class="pl-k">-</span> <span class="pl-smi">$Width</span>) <span class="pl-k">/</span> <span class="pl-c1">2</span>)
    <span class="pl-smi">$Y</span> <span class="pl-k">=</span> [<span class="pl-k">Math</span>]::Max(<span class="pl-c1">0</span><span class="pl-k">,</span> (<span class="pl-smi">$ScreenHeight</span> <span class="pl-k">-</span> <span class="pl-smi">$Height</span>) <span class="pl-k">/</span> <span class="pl-c1">2</span>)
    [<span class="pl-k">WinAPI</span>]::MoveWindow(<span class="pl-smi">$Handle</span><span class="pl-k">,</span> [<span class="pl-k">Int</span>]<span class="pl-smi">$X</span><span class="pl-k">,</span> [<span class="pl-k">Int</span>]<span class="pl-smi">$Y</span><span class="pl-k">,</span> <span class="pl-smi">$Width</span><span class="pl-k">,</span> <span class="pl-smi">$Height</span><span class="pl-k">,</span> <span class="pl-c1">$True</span>)
}

<span class="pl-k">Function</span> <span class="pl-en">Keepass-Status</span> {
    <span class="pl-k">If</span> (<span class="pl-smi">$KeepassFocused</span>) { <span class="pl-k">Return</span> <span class="pl-c1">$False</span> }
    <span class="pl-smi">$Title</span> <span class="pl-k">=</span> <span class="pl-c1">Get-Process</span> <span class="pl-k">-</span>Name <span class="pl-smi">$Keepass.BaseName</span> <span class="pl-k">|</span> <span class="pl-c1">ForEach-Object</span> { <span class="pl-c1">$_</span><span class="pl-smi">.MainWindowTitle</span> }
    <span class="pl-smi">$Status</span> <span class="pl-k">=</span> <span class="pl-k">!</span><span class="pl-smi">$Title.Contains</span>(<span class="pl-s"><span class="pl-pds">"</span>[Locked]<span class="pl-pds">"</span></span>) <span class="pl-k">-And</span> <span class="pl-smi">$Title.Contains</span>(<span class="pl-s"><span class="pl-pds">"</span>- KeePassXC<span class="pl-pds">"</span></span>)
    <span class="pl-k">If</span> (<span class="pl-smi">$Status</span>) {
        <span class="pl-smi">$AgentHasNoKeys</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
        <span class="pl-k">Return</span> <span class="pl-c1">$True</span>
    } <span class="pl-k">Else</span> {
        <span class="pl-k">Return</span> <span class="pl-c1">$False</span>
    }
}

<span class="pl-k">Function</span> <span class="pl-en">Keepass-Isnt-Running</span> {
    <span class="pl-k">Return</span> <span class="pl-k">-Not</span> (<span class="pl-c1">Get-Process</span> <span class="pl-k">-</span>ErrorAction SilentlyContinue <span class="pl-smi">$Keepass.BaseName</span> <span class="pl-k">|</span> Select <span class="pl-k">-</span>Expand ProcessName)
}

<span class="pl-k">Function</span> <span class="pl-en">Keepass-Isnt-Active</span> {
    <span class="pl-k">If</span> (<span class="pl-smi">$KeepassFocused</span>) { <span class="pl-k">Return</span> <span class="pl-c1">$False</span> }
    <span class="pl-smi">$Window</span> <span class="pl-k">=</span> [<span class="pl-k">WinAPI</span>]::GetForegroundWindow()
    <span class="pl-smi">$Process</span> <span class="pl-k">=</span> <span class="pl-c1">Get-Process</span> <span class="pl-k">-</span>ErrorAction SilentlyContinue <span class="pl-k">-</span>Name <span class="pl-smi">$Keepass.BaseName</span>
    <span class="pl-k">If</span> (<span class="pl-smi">$Process</span> <span class="pl-k">-and</span> <span class="pl-smi">$Process.MainWindowHandle</span> <span class="pl-k">-ne</span> <span class="pl-c1">0</span>) {
        <span class="pl-smi">$IsMinimized</span> <span class="pl-k">=</span> [<span class="pl-k">WinAPI</span>]::IsIconic(<span class="pl-smi">$Process.MainWindowHandle</span>)
        <span class="pl-smi">$IsNotActive</span> <span class="pl-k">=</span> <span class="pl-smi">$Process.MainWindowHandle</span> <span class="pl-k">-ne</span> <span class="pl-smi">$Window</span>
        <span class="pl-smi">$KeepassFocused</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
        <span class="pl-k">Return</span> (<span class="pl-smi">$IsMinimized</span> <span class="pl-k">-or</span> <span class="pl-smi">$IsNotActive</span>)
    } <span class="pl-k">Else</span> {
        <span class="pl-smi">$KeepassFocused</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
        <span class="pl-k">Return</span> <span class="pl-c1">$True</span>
    }
}

<span class="pl-k">While</span> (<span class="pl-smi">$Status</span> <span class="pl-k">=</span> Agent<span class="pl-k">-</span>Status) {
    <span class="pl-k">Switch</span> (<span class="pl-smi">$Status</span>) {
        <span class="pl-c1">2</span> {
            <span class="pl-k">If</span> (Agent<span class="pl-k">-</span>Isnt<span class="pl-k">-</span>Running) {
                <span class="pl-smi">$KeepassFocused</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
                Agent<span class="pl-k">-</span>Start
                <span class="pl-c1">Start-Sleep</span> <span class="pl-c1">0.5</span>
                Keepass<span class="pl-k">-</span>Start <span class="pl-k">-</span>ArgumentList <span class="pl-k">--</span>lock
            }
        }
        <span class="pl-c1">1</span> {
            <span class="pl-k">If</span> (Keepass<span class="pl-k">-</span>Isnt<span class="pl-k">-</span>Running) {
                Keepass<span class="pl-k">-</span>Start
            }
            <span class="pl-k">If</span> (Keepass<span class="pl-k">-</span>Status) {
                <span class="pl-smi">$KeepassFocused</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
                <span class="pl-smi">$AgentHasNoKeys</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
                Keepass<span class="pl-k">-</span>Start <span class="pl-k">-</span>ArgumentList <span class="pl-k">--</span>lock
            }
            <span class="pl-k">If</span> (Keepass<span class="pl-k">-</span>Isnt<span class="pl-k">-</span>Active) {
                <span class="pl-smi">$KeepassFocused</span> <span class="pl-k">=</span> <span class="pl-c1">$True</span>
                Keepass<span class="pl-k">-</span>Start
            }
        }
        <span class="pl-c1">0</span> {
            <span class="pl-k">Exit</span> <span class="pl-c1">0</span>
        }
    }
	<span class="pl-c1">Start-Sleep</span> <span class="pl-c1">0.5</span>
}
</code></pre><p>I placed that script in <font class="hljs-attribute">~/.ssh/bin/wrapper.ps1</font>.
Logic explanation using pseudocode:</p>
<pre><code class="highlight highlight-python"><span class="pl-k">while</span> omnisshagent <span class="pl-k">is</span> empty:
  <span class="pl-k">if</span> omnisshagent <span class="pl-k">is</span> <span class="pl-k">not</span> running:
    startomnisshagent
  <span class="pl-k">if</span> keepassxc <span class="pl-k">is</span> <span class="pl-k">not</span> running:
    start keepassxc
  <span class="pl-k">if</span> keepassxc <span class="pl-k">is</span> minimized to tray:
    unminize keepassxc
</code></pre><p>Should be easy to understand.
Of course, I made sure that a million copies of programs will not spawn in that loop.</p>
<p>Now I must realize how to run that script before an SSH connection.
A wrapper for <font class="hljs-attribute">/usr/bin/ssh</font> in <font class="hljs-attribute">/usr/local/bin/ssh</font>?
Meh.
It will only work in <a href="https://learn.microsoft.com/en-us/windows/wsl/about">WSL2</a> by running <font class="hljs-built_in">ssh</font>.
I need something to make the wrapper run anytime an SSH connection starts.
It makes sense to set this up somewhere in the SSH config.
<a href="https://man7.org/linux/man-pages/man5/ssh_config.5.html">ProxyCommand</a>?
Ok, let&#39;s try:</p>
<pre><code class="highlight highlight-bash">Host <span class="pl-k">*</span>
  ProxyCommand <span class="pl-s"><span class="pl-pds">"</span>pwsh.exe -c c:/users/%u/.ssh/wrapper.ps1<span class="pl-pds">"</span></span>
</code></pre><p>The command above was selected so that it runs equally well from both environments.</p>
<p>To use that option properly, <a href="https://man.openbsd.org/nc.1">nc</a> must be called at the end of <font class="hljs-attribute">wrapper.ps1</font> with specific arguments to <a href="https://blog.pcarleton.com/post/ssh-proxy/">create a TCP connection between the client and the server</a>.
I rewrote the wrapper a little to be able to get arguments from the SSH config.
The config now:</p>
<pre><code class="highlight highlight-bash">Host <span class="pl-k">*</span>
  ProxyCommand <span class="pl-s"><span class="pl-pds">"</span>pwsh.exe -c c:/users/%u/.ssh/wrapper.ps1 %h %p<span class="pl-pds">"</span></span>
</code></pre><p>Where <font class="hljs-variable">%h</font> is the hostname of the target alias, and <font class="hljs-variable">%p</font> is the port of the target alias.</p>
<p>Sadly, connections end up with a bad length error when I call Windows programs from <font class="hljs-attribute">wrapper.ps1</font>.
I haven&#39;t figured out what the problem is.
I think Windows programs create unwanted output that passes in stdin of the server then an error occurs.
I tried to call programs with output redirection, tried it via shell script, tried <font class="hljs-built_in">nc</font> for <a href="https://nmap.org/ncat/">Windows</a> and <a href="https://man.openbsd.org/nc.1">Linux</a>, feels like I tried everything — no luck, skill issue for sure…</p>
<p>…then <a href="https://man.openbsd.org/ssh_config#Match">Match</a> walks into the bar:</p>
<pre><code class="highlight highlight-bash">Match Host <span class="pl-k">*</span> <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pwsh.exe -c c:/users/%u/.ssh/wrapper.ps1<span class="pl-pds">"</span></span>
</code></pre><p>Yes, <a href="https://en.wikipedia.org/wiki/RTFM">RTFM</a> moment.
Yes, it just runs the command before the connection.
Yes, no more dirty hacking in between.</p>
<p>The final file structure:</p>
<pre><code class="highlight highlight-plaintext">~/.ssh
├── aliases
│   └── git
├── bin
│   ├── fix-perms.sh
│   ├── omni-ssh-agent.exe
│   ├── wrapper.ps1
│   └── wsl2-ssh-agent
└── config
</code></pre><p>And <a href="https://dev.hexed.pw/logs/omnikeepass/data/ssh/config">the SSH config</a>:</p>
<pre><code class="highlight highlight-bash">Include aliases/<span class="pl-k">*</span>
Match Host <span class="pl-k">*</span> <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pwsh.exe -c c:/users/%u/.ssh/bin/wrapper.ps1<span class="pl-pds">"</span></span>
</code></pre><p>Additionaly I added a handler to connect to aliases via <font class="hljs-string">ssh://</font> handler. It can be called from <a href="https://keepassxc.org/">KeePassXC</a>, Windows Run, a web browser, etc. <a href="https://dev.hexed.pw/logs/omnikeepass/data/ssh_handler.reg">Source code of the handler</a>:</p>
<pre><code class="highlight highlight-re">Windows Registry Editor Version <span class="pl-c1">5.00</span>

[HKEY_CLASSES_ROOT\ssh]
@=<span class="pl-s"><span class="pl-pds">"</span>URL:Windows OpenSSH Handler<span class="pl-pds">"</span></span>
<span class="pl-s"><span class="pl-pds">"</span>URL Protocol<span class="pl-pds">"</span></span>=<span class="pl-s"><span class="pl-pds">""</span></span>

[HKEY_CLASSES_ROOT\ssh\shell]
[HKEY_CLASSES_ROOT\ssh\shell\open]
[HKEY_CLASSES_ROOT\ssh\shell\open\command]
@=<span class="pl-s"><span class="pl-pds">"</span>pwsh -wd ~ -c ssh %1<span class="pl-pds">"</span></span>
</code></pre><p>The last line can be replaced with the following option to connect to the alias from <a href="https://learn.microsoft.com/en-us/windows/wsl/about">WSL2</a> or by creating a separate handler with a different name:</p>
<pre><code class="highlight highlight-re">@=<span class="pl-s"><span class="pl-pds">"</span>bash -c 'eval $($HOME/.ssh/wsl2-ssh-agent -socket /tmp/wsl2.sock) ssh %1'<span class="pl-pds">"</span></span>
</code></pre><p>And finally I got what I wanted:</p>
<p><video muted loop controls autoplay src="https://dev.hexed.pw/logs/omnikeepass/assets/result.mp4"></video></p>
]]></content>
        <author>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </author>
        <contributor>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </contributor>
    </entry>
    <entry>
        <title type="html"><![CDATA[iBMA in Proxmox]]></title>
        <id>2</id>
        <link href="https://dev.hexed.pw/logs/ibma_proxmox/"/>
        <link rel="enclosure" href="https://dev.hexed.pw/logs/ibma_proxmox/header.png" type="image/png"/>
        <updated>2024-05-09T18:12:11.000Z</updated>
        <summary type="html"><![CDATA[Installing iBMA in Proxmox]]></summary>
        <content type="html"><![CDATA[<p><img src="https://dev.hexed.pw/logs/ibma_proxmox/assets/_header.png" alt=""></p>
<p>I had a little problem at work with a Huawei blade server.
I wanted to see the hardware information and manage things from <a href="https://en.wikipedia.org/wiki/Intelligent_Platform_Management_Interface">IPMI</a> called <a href="https://e.huawei.com/en/products/computing/kunpeng/accessories/ibmc">iBMC</a>, but to do this I needed to install the agent called <a href="https://support.huawei.com/enterprise/en/doc/EDOC1100218100/426cffd9">iBMA</a> on the host system, in my case <a href="https://proxmox.com">Proxmox</a>.</p>
<p>Well, I started digging for the information on the Huawei Enterprise website which is a real headache to interact.
I found that I needed to <a href="https://support.huawei.com/enterprise/en/doc/EDOC1100218100/b5683fc2">compile the driver</a> and <a href="https://support.huawei.com/enterprise/en/doc/EDOC1100218100/667adef0">install the service</a>.
It seems okay, I found the information, it&#39;s probably worth downloading the software to start somehow now.
Tried to download the latest <a href="https://support.huawei.com/enterprise/en/server/ibma-pid-21099187/software/">software</a> and... <em>*sigh*</em></p>
<p><img src="https://dev.hexed.pw/logs/ibma_proxmox/assets/bruh.png" alt=""></p>
<p>Support replied with a standard excuse that their system is being updated and maintained.
I got the same error when I tried to download something from there a year ago.
Infinite maintainance, unlucky me or sanctions?
Who knows.</p>
<p>I went looking for where I could download the packages.
By some luckily random query in Google I found <a href="https://mysite.zaixia108.com/archives/1708076797558">zaixia108&#39;s article</a> about installing <a href="https://support.huawei.com/enterprise/en/doc/EDOC1100218100/426cffd9">iBMA</a> with more easier instruction and, most importantly, download links.
All kudos to this man.</p>
<p>Judging by the article, some code lines about errors that could confuse the user are commented out in the package.
Also, there are no original packages and checksums, so I installed all this at my own risk.
I hope I won&#39;t be connected to a Chinese botnet.
I&#39;m just living on the edge.</p>
<p>So, I did everything as in <a href="https://mysite.zaixia108.com/archives/1708076797558">zaixia108&#39;s article</a> and it started up fine:</p>
<p><img src="https://dev.hexed.pw/logs/ibma_proxmox/assets/software_info.png" alt=""></p>
<p>Just in case I bundled everything to a small archive without unnecessary packages for other distros and wrote a script for automatic installation.
If you wanna try it, you can download the bundle <a href="https://dev.hexed.pw/storage/logs/2_ibma_proxmox/">here</a>.
Just unzip it somewhere in your Proxmox and run <code>setup.sh</code>, but beware: <font class="hljs-variable">this is all at your own risk</font>!</p>
<p>To be honest, my simple script doesn&#39;t seem like it should break anything…</p>
<pre><code class="highlight highlight-bash"><span class="pl-c">#!/usr/bin/env bash</span>

<span class="pl-c1">set</span> -e

DEBIAN_FRONTEND=noninteractive

WORK_DIR=<span class="pl-s"><span class="pl-pds">"$(</span>dirname <span class="pl-pds">"$(</span>readlink -f <span class="pl-pds">"</span><span class="pl-smi">${0}</span><span class="pl-pds">")")"</span></span>
DRIVER_DIR=<span class="pl-smi">$WORK_DIR</span>/driver
SERVICE_DIR=<span class="pl-smi">$WORK_DIR</span>/service

KERNEL_VER=<span class="pl-s"><span class="pl-pds">$(</span>uname -r<span class="pl-pds">)</span></span>
DRIVER_VER=<span class="pl-s"><span class="pl-pds">$(</span>cat <span class="pl-smi">$DRIVER_DIR</span>/build_manual.sh <span class="pl-k">|</span> grep -Po <span class="pl-pds">'</span>(?&#x3C;=DRV_VERSION=).*<span class="pl-pds">')</span></span>
SERVICE_VER=<span class="pl-s"><span class="pl-pds">$(</span>cat <span class="pl-smi">$SERVICE_DIR</span>/install.sh <span class="pl-k">|</span> grep -Po <span class="pl-pds">'</span>(?&#x3C;=IBMA_VERSION=).*<span class="pl-pds">')</span></span>


<span class="pl-c1">echo</span> -e <span class="pl-s"><span class="pl-pds">'</span>> Installing dependencies<span class="pl-pds">'</span></span>
sudo apt-get update -q
sudo apt-get install -qy dkms pve-headers-<span class="pl-smi">$KERNEL_VER</span>
cp -vf /usr/src/linux-headers-<span class="pl-smi">$KERNEL_VER</span>/include/linux/stdarg.h <span class="pl-smi">$DRIVER_DIR</span>/edma_drv 


<span class="pl-c1">echo</span> -e <span class="pl-s"><span class="pl-pds">"</span>\n> Building the driver<span class="pl-pds">"</span></span>
bash <span class="pl-smi">$DRIVER_DIR</span>/build_manual.sh linux-headers-<span class="pl-smi">$KERNEL_VER</span>
cp -vf <span class="pl-smi">$DRIVER_DIR</span>/ibmadriver-<span class="pl-smi">$KERNEL_VER</span>-<span class="pl-smi">$DRIVER_VER</span>-linuxheaders.amd64.deb <span class="pl-smi">$SERVICE_DIR</span>/drivers/Debian


<span class="pl-c1">echo</span> -e <span class="pl-s"><span class="pl-pds">"</span>\n> Installing the service<span class="pl-pds">"</span></span>
sudo systemctl stop iBMA.service <span class="pl-k">2></span> /dev/null <span class="pl-k">||</span> <span class="pl-c1">true</span>
bash <span class="pl-smi">$SERVICE_DIR</span>/install.sh -s

<span class="pl-c1">echo</span> -e <span class="pl-s"><span class="pl-pds">"</span>\n> Done! Don't forget to reboot the server.<span class="pl-pds">"</span></span>
<span class="pl-c1">exit</span> 0
</code></pre><p>…but here is a chance that Huawei software will do it.</p>
<p>And another just-in-case moment: I <a href="https://dev.hexed.pw/storage/logs/2_ibma_proxmox/mirror/">mirrored packages</a> from <a href="https://mysite.zaixia108.com/archives/1708076797558">zaixia108&#39;s article</a>.</p>
]]></content>
        <author>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </author>
        <contributor>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </contributor>
    </entry>
    <entry>
        <title type="html"><![CDATA[FFmpeg with NDI]]></title>
        <id>3</id>
        <link href="https://dev.hexed.pw/logs/ffmpeg_ndi/"/>
        <link rel="enclosure" href="https://dev.hexed.pw/logs/ffmpeg_ndi/header.png" type="image/png"/>
        <updated>2024-06-09T07:12:12.000Z</updated>
        <summary type="html"><![CDATA[Building fresh FFmpeg with NDI support]]></summary>
        <content type="html"><![CDATA[<p><img src="https://dev.hexed.pw/logs/ffmpeg_ndi/assets/_header.png" alt=""></p>
<p>Download <a href="https://downloads.ndi.tv/SDK/NDI_SDK/NDI%206%20SDK.exe">NDI SDK 6</a> and install</p>
<p>Clone <a href="https://github.com/m-ab-s/media-autobuild_suite">Media Autobuild Suite</a> somewhere in the root of the disk (to prevent long path errors). cd into the cloned repo and apply patch:</p>
<p>curl -sL <a href="https://github.com/flameshikari/logs/content">https://github.com/flameshikari/logs/content</a> | git apply -v --index</p>
<p>Create the script:</p>
<p>also keep in mind that the resulted binary is not for redistribution</p>
<p>dependencies:</p>
<ul>
<li><p><a href="https://github.com/m-ab-s/media-autobuild_suite">a</a></p>
</li>
<li><p><a href="https://github.com/moocowsheep/ffmpeg-ndi-patch">a</a></p>
</li>
<li><p><a href="https://ndi.video/for-developers/ndi-sdk/download">a</a></p>
</li>
</ul>
<p>This example is for Windows only. If you&#39;re experienced with building from the source, you can easily adapt it for other systems. H</p>
<ul>
<li><p><a href="https://downloads.ndi.tv/SDK/NDI_SDK/NDI%206%20SDK.exe">Windows</a></p>
</li>
<li><p><a href="https://downloads.ndi.tv/SDK/NDI_SDK_Linux/Install_NDI_SDK_v6_Linux.tar.gz">Linux</a></p>
</li>
<li><p><a href="https://downloads.ndi.tv/SDK/NDI_SDK_Mac/Install_NDI_SDK_v6_Apple.pkg">macOS / iOS</a></p>
</li>
<li><p><a href="https://downloads.ndi.tv/SDK/NDI_SDK_Android/Install_NDI_SDK_v6_Android.tar.gz">Android for Linux</a></p>
</li>
<li><p><a href="https://downloads.ndi.tv/SDK/NDI_SDK_Android/NDI%206%20SDK%20%28Android%29.exe">Android for Windows</a></p>
</li>
</ul>
<p>Copy:</p>
<ul>
<li>sdk/include/* to local64/include</li>
<li>sdk/bin/Processing.NDI.Lib.x64.lib to local64/lib/libndi.dll.a</li>
</ul>
<p>References:</p>
<ul>
<li><p>Issues <a href="https://github.com/m-ab-s/media-autobuild_suite/issues/903">#903</a>, <a href="https://github.com/m-ab-s/media-autobuild_suite/issues/1145">#1145</a>, <a href="https://github.com/m-ab-s/media-autobuild_suite/issues/2209">#2209</a></p>
</li>
<li><p><a href="https://github.com/moocowsheep/ffmpeg-ndi-patch?tab=readme-ov-file#usage-">FFmpeg NDI Patch</a></p>
</li>
</ul>
]]></content>
        <author>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </author>
        <contributor>
            <name>flameshikari</name>
            <email>mail@hexed.pw</email>
            <uri>https://dev.hexed.pw</uri>
        </contributor>
    </entry>
</feed>