Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Touch file with XFE Script

I use an empty file with the modification timestamp to indicate the last time I manually synced my SyncThing-ed directory of my mobile phone pictures to my backup location.

I set up an alias to touch in my ~/.config/xfe/scripts directory.

$ ls -l ~/.config/xfe/scripts
total 3
lrwxrwxrwx 1 bgstack15 bgstack15  14 Aug 13 14:42 touch -> /usr/bin/touch

So now I can just right-click the file and update the timestamp, now that I have re-synced. Because I keep some images on my mobile phone, I won't need to bother with any older than this synced-here file.

Read signature of .ps1 file with CLI on Linux

If you wish to read the PKCS7-encoded signature on a powershell script, and you don't have osslsigncode verify available to you (from https://github.com/mtrojnar/osslsigncode), you can use this script.

files/2024/listings/read-signature.sh (Source)

#!/usr/bin/env sh
# File: read-signature.sh
# Location: blog
# Author: bgstack15
# SPDX-License-Identifier: GPL-3.0-only
# Startdate: 2024-08-08-5 14:35
# Title: Read Signature
# Purpose: Read codesign signature on a powershell script on Unix-like cli
# History:
# Usage:
# Reference:
# Improve:
# Dependencies:
#    openssl, gsed, gawk, posix shell
# Documentation:
#    Skipping SAN; tends to not be used on codesigning certs?
command -v sed 1>/dev/null 2>&1 && SED=sed
command -v gsed 1>/dev/null 2>&1 && SED=gsed
command -v awk 1>/dev/null 2>&1 && AWK=awk
command -v gawk 1>/dev/null 2>&1 && AWK=gawk
read_sig() {
   _in="${INFILE:-${1}}"
   _in="${_in:-/dev/stdin}"
   test "${_in}" = "-" && _in="/dev/stdin"
   _contents="$(
      printf '%s\n' '-----BEGIN PKCS7-----'
      <"${_in}" "${SED}" -r -n '/^# SIG # Begin/,/^# SIG # End/{s/^\# //;p;}' | tr -d '\r' | grep -v -e 'signature block'
      printf '%s\n' '-----END PKCS7-----'
   )"
   # would need to parse SANs here if any.
   echo "${_contents}" | openssl pkcs7 -in /dev/stdin -print_certs | openssl x509 -in /dev/stdin -noout -subject -issuer -serial -email -dates
   # Print date
   echo "${_contents}" | openssl pkcs7 -in /dev/stdin -print -noout | "${AWK}" '/signingTime/{getline;getline;gsub(":","",$NF);print $NF}' | "${SED}" -r -e 's/^(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})/timestamp=20\1-\2-\3T\4:\5:\6/;'
}

Notice how I make sure we find GNU sed and awk, because the old BSD ones use a different syntax that are not worth learning. Just use real sed and awk.

Send SMTP with openssl cli

files/2024/listings/smtp1.sh (Source)

#!/bin/sh
# File: smtp1.sh
# Location: stackbin
# Author: bgstack15
# Startdate: 2024-08-05-2 14:05
# SPDX-License-Identifier: GPL-3.0-only
# Title: Send authenticated email with openssl s_client
# Purpose: demo cli smtp auth
# History:
# References:
#    https://stackoverflow.com/questions/1546367/how-to-send-mail-with-to-cc-and-bcc
#    https://szclsya.me/posts/net/send-email-with-netcat/
#    https://serverfault.com/questions/1101104/how-to-send-an-email-with-openssl-and-microsoft-exchange-online
#    https://woshub.com/sending-email-via-telnet-using-smtp-authentication/
#    https://learn.microsoft.com/en-us/exchange/mail-flow/test-smtp-telnet?view=exchserver-2019
#    https://stackoverflow.com/questions/14640560/openssl-to-negotiate-ssl-encryption-for-starttls
#    https://thelinuxcode.com/openssl-s-client/
#    https://www.stevenrombauts.be/2018/12/test-smtp-with-telnet-or-openssl/
#    https://stackoverflow.com/questions/44250054/send-email-with-netcat
# Improve:
# Dependencies:
#    dep-fedora: openssl, coreutils
#    an smtp account and server
# Documentation:
slowcat() {
   while read REPLY ; do sleep .05; echo "$REPLY"; done
}
{
   message1="$( printf '%s' 'exampleuser@example.com' | base64 )"
   message2="$( cat ~/.config/smtp1 )"
   printf '%s\n' "EHLO exampleaddress.com"
   printf '%s\n' "AUTH LOGIN"
   printf '%s\n' "${message1}"
   printf '%s\n' "${message2}"
   # Everybody, so TO, CC, BCC is a RCPT TO. The To, CC, BCC headers are the decorations visible to the mail client.
   cat <<-EOF
MAIL FROM:<exampleuser@example.com>
RCPT TO:<user2@local.example.com>
RCPT TO:<user3@anotherlocal.examplelong.com>
DATA
From: [marco polo] <exampleaddress.com>
To: <user3@anotherlocal.examplelong.com>
BCC: <user2@local.example.com>
Date: Mon, 5 Aug 2024 17:31:32 +0000
Subject: Hello from netcat
sample message here
.
QUIT
EOF
# | slowcat | nc -v mail.example.net 587
} | slowcat | openssl s_client -crlf -connect mail.example.net:587 -starttls smtp -ign_eof

I needed to test (credentials, but also in general) the ability to send smtp messages. Here is my small script that does that.

The slowcat is useful because smtp (or maybe just my email implementation) wanted to delay between some of the steps, particularly EHLO and AUTH.

I couldn't get netcat (nc) to work with tls, although I thought I saw that once. At least s_client could do it.

set or update xml element from cli

The code:

update_xml_element() {
   # usage: parent="/toplevelobject" element="internalid" value="12341234" infile=./foo.xml _insert_xml_element
   _parent="${parent:-${1}}" ; _parent="${_parent%%/}"
   _element="${element:-${2}}"
   _value="${value:-${3}}"
   _infile="${infile:-${4}}"
   # example: xmlstarlet edit --update "/toplevelobject/internalid" --value "if-updated" --subnode "/toplevelobject[not(internalid)]" --type elem -n "internalid" --value "if-inserted"
   xmlstarlet edit --inplace --update "${_parent}/${_element}" --value "${_value}" --subnode "${_parent}[not(${_element})]" --type elem -n "${_element}" --value "${_value}" "${_infile}"
}

So then you just call this function, and it adds the correct element. I haven't needed to customize attributes of elements yet.

infile=input.xml parent="/episodedetails" element="episodenumber" value="4" update_xml_element

References

  1. xmlstarlet update attribute value if it exists or create a line with the attribute - Stack Overflow
  2. xml - xmlstarlet: create an attribute if it does not exist and edit it otherwise - Stack Overflow

Alternative to `apt-mark hold`

This is a rewritten version of an old post: apt/preferences.d: A Useful Example with a focus on what syntax it replaced.

I used to use apt-mark hold to control packages that I wanted to pin. For example, zenity now uses gtk4 so I

But before I got that epoch part added, I marked the package.

apt-mark hold zenity

But I never found where this information was stored, and I prefer to have files that configure my apps rather than online commands only. I bet it was in /var/lib somewhere I never found.

You could at least show holds, and unhold items.

apt-mark showhold
apt-mark unhold zenity

Anyway, so to make the process so I can deploy a file to control this, I made a file: /etc/apt/preferences.d/zenity

Package: zenity
Version: 3.44.2-1
Pin: release
Pin-Priority: 600
Package: zenity-common
Version: 3.44.2-1
Pin: release
Pin-Priority: 600

The pin priority is higher than the default 500 for installed and installable packages. Of course if you've started tweaking these numbers for specific repositories but you still want this preference to have priority, you can adjust the numbers.

Later on, I built a copy of the last gtk3-based one for myself, with a package epoch (the number prepending a colon and then the regular version number) so it always has top priority version-wise. So I didn't need any of this anymore. But for anyone who doesn't want to rebuild a whole package, use this method I just described.

AndBible compared to BibleTimeMini

I use two different main Bible programs on my mobile device (with apologies to a random dude I follow):

Both of these are SWORD project clients, which means they can use the mostly-open-source Bible contents and distribution mechanisms to get more content.

While I grew up reading the King James Version (KJV), aka Authorized Version (AV), of the Holy Bible, I now primarily use the English Standard Version (ESV). I also am interested in a few other translations, and both of these programs let you download and use and switch between multiple versions. In addition to other Bible texts, there are commentaries, dictionaries, and other types of mostly-print media available as modules to the SWORD project.

Because of BibleTimeMini's disappearance 1 from the Play Store, I started researching presently-available Bible apps for mobile devices, starting in the free-software F-Droid app store, and found AndBible.

Each app has a different-generation mobile UI to navigate. I like the traditional view of BibleTimeMini, but I guess I'm getting used to the Material Design/modernness of AndBible.

BibleTimeMini would download additional modules to my visible internal storage, at /.sword/, so it was easy for me to manually manipulate the modules (i.e., back them up with other means). AndBible stores them... somewhere, that I haven't found. I found that frustrating. However, AndBible supports custom web repositories for modules (and you know how much I love repositories, so it's not too hard to get custom selections available as kind of a reverse-backup.

I much prefer the book-and-chapter navigation of BibleTimeMini, but I fear that AndBible is the only one to be available on the web in the long term, so I'm trying to get used to AndBible. I have backed up the apk of BibleTimeMini though, just like I partially mirror F-droid's repository.

Basically, I like carrying the Word of God in my pocket 2, in all the various translations I care about, alongside all the electronic conveniences I would have in my pocket already anyways. And these two apps both do the job. And they're both FLOSS!


  1. Probably merely through lack of recent development; a finished product doesn't need updates, but you know how marketplaces seem to think no updates means it's dead. 

  2. And not just a New Testament; How big do you think my pockets are?! 

Openssl: Generate CSR with NTDS CA Security Extension

To request a certificate with the exact Microsoft OID for Client Auth certs for the domain, you can use an openssl.cnf that resembles the following.

This also includes the SAN URI which is separate from the NTCS.

files/2024/listings/openssl.cnf (Source)

[ req ]
prompt             = no
default_bits       = 4096
default_md         = sha256
default_keyfile    = privkey.pem
distinguished_name = req_distinguished_name
req_extensions     = req_ext
[ req_distinguished_name ]
C = US
ST = Florida
L = Miami
O = Example Org
# Important value
CN = hostname123498.example.org
#emailAddress = noreply@example.org
[ req_ext ]
basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment
# this oid is szOID_NTDS_CA_SECURITY_EXT
1.3.6.1.4.1.311.25.2   = ASN1:SEQUENCE:NTDSCASecurityExt
subjectAltName         = @alt_names
[ alt_names ]
# Important value
DNS.1 = hostname123498.example.org
DNS.2 = hostname123498.subnet.example.org
# hardcoded text until the sid
URI.1 = tag:microsoft.com,2022-09-14;sid:S-1-5-21-2059058832-2300889872-1288252972-490382
[ NTDSCASecurityExt ]
# If you wanted to use another SEQUENCE but that does not conform to the M$ example.
#wrappingSeq = EXPLICIT:0,SEQUENCE:ExtOid
# The EXPLICIT,0 is required to get the specific context which is displayed by asn1parse as: cont [ 0 ]
szOID_NTDS_OBJECTSID = EXPLICIT:0,OID:1.3.6.1.4.1.311.25.2.1
# Important value
key = EXPLICIT:0,OCTETSTRING:S-1-5-21-2059058832-2300889872-1288252972-490382
[ ExtOid ]
oid = OID:1.3.6.1.4.1.311.25.2.1

References

Weblinks

  1. [MS-WCCE]: szOID_NTDS_CA_SECURITY_EXT | Microsoft Learn
  2. x509 - Create own ASN.1 module for custom extension in OpenSSL command line tools - Stack Overflow
  3. /docs/man1.1.1/man3/ASN1_generate_nconf.html
  4. is it possible making openssl skipping the country/common name prompts? - Stack Overflow
  5. Preview of SAN URI for Certificate Strong Mapping for KB5014754 - Microsoft Community Hub
  6. KB5014754: Certificate-based authentication changes on Windows domain controllers - Microsoft Support
  7. certreq | Microsoft Learn

Auxiliary

  1. Manually injecting a SID in a certificate – Q&D Security
  2. Generate-ServerCertificate.ps1

Extract attached file from encrypted PDF

I received an email with an attached pdf. This pdf was password-protected (encrypted). Atril thankfully can read those, but I didn't know how to view the file attached to the pdf. (Yes, I know, attached inside an attachment; I wasn't in control of the sender.)

Besides, who wants to use a graphical environment when a cli will do?

qpdf input.pdf output.pdf --decrypt --password='passphrasehere'
mkdir -p outdir
pdftk output.pdf unpack_files output outdir

Old research

My old solution involved pdftk and pdfdetach and for some reason I was failing to read the pdf correctly with pdftk.

pdftk inputfile.pdf input_pw 'passphrasehere' outputfile.pdf
pdfdetach -upw 'passphrasehere' -saveall inputfile.pdf

References

  1. How to Remove a Password from a PDF File in Linux
  2. Open a pdf with blank password with pdftk - Stack Overflow

Unicode cheat sheet for myself

I heavily adapted a unicode chart I found somewhere for my own needs. I show the hexadecimal, decimal, and vim digraph values for some characters I use occasionally. I miss the ALT+157 alt codes, but they were from my old non-free OS days when you didn't want to load up charmap.exe. If I had any environments around like that, I'd bother to add those here too.

<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel=stylesheet type="text/css" href="general-info.css">
<meta name="description" content="Lists all Unicode characters">
<meta name="keywords" content="character code">
<style type="text/css">
</style>
<title>Abbreviated Unicode Table</title>
</head>
<body>
<hr class=hf>
<h2>Useful Unicode Table</h2>
<p><table cellspacing=0 cellpadding=2 border=0><tr>
<td>
<table cellspacing=0 cellpadding=2 border=1 bordercolor="#88DD44">
<tr><th>Name</th><th>Html Symbol</th><th>Raw character</th><th>hex</th><th>dec</th><th>vim digraph</th></tr>
<tr><td>Cent</td>       <td>&#x00A2;</td><td>¢</td><td>00A2</td><td>162</td> <td>Ct</td></tr>
<tr><td>Yen</td>        <td>&#x00A5;</td><td>¥</td><td>00A5</td><td>165</td> <td>Ye</td></tr>
<tr><td>Section</td>    <td>&#x00A7;</td><td>§</td><td>00A7</td><td>167</td> <td>SE</td></tr>
<tr><td>Degrees</td>    <td>&#x00B0;</td><td>°</td><td>00B0</td><td>176</td> <td>DG</td></tr>
<tr><td>Euro</td>       <td>&#x20AC;</td><td></td><td>20AC</td><td>8364</td><td>Eu or =e</td></tr>
<tr><td>Square root</td><td>&#x221A;</td><td></td><td>221A</td><td>8730</td><td>RT</td></tr>
</table>
</body>
<footer>
<h4>References</h4>
vim <em>:help digraph</em>
</footer>
</html>

A screenshot of it rendered on my system.

Powershell Use-Culture function

Provided by a coworker, who got it from somewhere on the Internet that I cannot source correctly:

function Use-Culture
{
   param(
      [Parameter(Mandatory)][CultureInfo]$Culture,
      [Parameter(Mandatory)][ScriptBlock]$ScriptBlock
   )
   # Note: In Windows 10, a culture-info object can be created from *any* string.
   #        However, an identifier that does't refer to a *predefined* culture is
   #        reflected in .LCID containing 4096 (0x1000)
   if ($Culture.LCID -eq 4096) { Throw "Unrecognized culture: $($Culture.DisplayName)" }
   # Save the current culture / UI culture values.
   $PrevCultures = [Threading.Thread]::CurrentThread.CurrentCulture, [Threading.Thread]::CurrentThread.CurrentUICulture
   try {
      # (Temporarily) set the culture and UI culture for the current thread.
      [Threading.Thread]::CurrentThread.CurrentCulture = [Threading.Thread]::CurrentThread.CurrentUICulture = $Culture
      # Now invoke the given code.
   & $ScriptBlock
   }
   finally {
      # Restore the previous culture / UI culture values.
      [Threading.Thread]::CurrentThread.CurrentCulture = $PrevCultures[0]
      [Threading.Thread]::CurrentThread.CurrentUICulture = $PrevCultures[1]
   }
}

You would use it in something like this:

Use-Culture -Culture en-US -ScriptBlock { Get-AdUserPasswordExpiration -Identity bgstack15 }

This might have been adapted from Windows PowerShell 2.0 String Localization | Keith Hill's Blog