Convert Local to AD Users

Project CLADU

CLADU stands for Convert Local to AD User.

When you want to take local accounts and remove them and have the AD user with the exact same name take its place, use cladu.

usage: [-duV] [-gr] [--ng] [--nr] user1 [ user2 user3 ... ]
version 2018-03-09a
-d debug Show debugging info, including parsed variables.
-u usage Show this usage block.
-V version Show script version number.
-g groups Add the AD user to the local groups of the local user. Default is to skip this action.
--ng Do not perform the -g action
-r report Generate report in each user homedir.
--nr Do not perform the -r action
Environment variables:
Parameters override environment variables
CLADU_USER_REPORT any non-null value will perform the -r action.
CLADU_USER_REPORT_FILENAME=converted.txt File to save report to in each homedir
CLADU_GROUPS any non-null value will perform the -g action.
Return values:
0 Normal
1 Help or version info displayed
2 Count or type of flaglessvals is incorrect
3 Incorrect OS type
4 Unable to find dependency
5 Not run as root or sudo

Go check out the entire source to look at the flow of the script.


Install Logical Journey of the Zoombinis (1996) on Linux


The game Logical Journey of the Zoombinis was an amazing game when I was young. It was fun, and apparently I learned a lot. I decided to try to install it on my Devuan ceres laptop. Here is the optimal route for making it work.

How to Install Zoombinis on Linux

The Zoombinis game was published in 1996, and it supports Windows 3.1 and Windows 95. We are going to install Windows 3.1 in DOSBox, install drivers, and then install the game.

Prepare Windows 3.1

Install DOSBox, which is probably in the main package manager on your GNU/Linux platform.

sudo dnf install dosbox
sudo apt-get install dosbox

Extract the Windows 3.1 VHD file (which I had from my old MSDN AA days). Also extract into sub-folders the Zoombinis disc contents, the sound drivers that DOSBox emulates, and the emulated video drivers.

mkdir -p ~/win31 ; cd ~/win31 ; 7z x ~/Downloads/Windows\ 3.1.vhd
mkdir -p ~/win31/zoominst ; cd ~/win31/zoominst && 7z x ~/Downloads/Logical\ Journey\ of\ the\ Zoombinis.iso
mkdir -p ~/win31/drivers/SB ; cd ~/win31/drivers/SB && 7z x ~/Downloads/
mkdir -p ~/win31/drivers/S3 ; cd ~/win31/drivers/S3 && 7z x ~/Downloads/

Prepare a batch file for mounting the right drives in the emulated environment.

cat <<'EOF' > win31.bat
REM for Zoombinis
MOUNT C ~/win31
MOUNT D ~/win31/zoominst


Run DOSBox:

dosbox win31.bat

Run Windows:


It might prompt you about deleting a corrupt swap file. You can select “Y” to do so, and then go into the Control Panel, “386 Enhanced,” Virtual Memory button, and save the information that is present. Then it shouldn’t prompt you anymore.

Install sound and video drivers

Zoombinis will warn you about sound and video settings, so the driver we loaded earlier should cover this. Now we have to install them. DOSBox emulates the SoundBlaster and S3 video hardware, so we just apply those drivers for Windows 3.1, and then audio will work and higher graphics settings too.
In DOSBox, cd to DRIVERS\SB and run the INSTALL utility.


Press enter to install the driver now.
Press enter to do a full installation.
Navigate with the arrow keys down to the Windows 3.1 path and enter in the “C:\Windows” value.

Change the Interrupt setting to the DOSBOX default of 7, as seen in this screenshot (unless you modified it in the dosbox.conf).

If it prompts you about replacing a file, feel free. It will not harm anything to replace it.
When that finishes, you can either reboot or stay on the current session.
Now it is time to install the video drivers. In DOSBox, run the Windows SETUP.EXE utility.


Select the DISPLAY option and press enter.

Scroll all the way to the bottom of the list and select “Other (requires disk…)”
Type in the directory where the video drivers are, e.g. “C:\DRIVERS\S3”
I am uncertain if Windows 3.1 has the ability to change the display resolution, so just pick your preferred screen resolution here.

I picked the 800×600 64K color with small fonts (as opposed to large-print fonts).
The SETUP utility will then return to the full list of system information, and you can select “Accept the configuration shown above.”
You might need to point it to the “C:\DRIVERS\S3” folder once more.
Now you can run Windows 3.1 with sound and an 800×600 display!


Install Zoombinis

Use File Manager to navigate to where we injected the install files.

Run the setup.exe!
Make sure you have enough disk space.

I installed QuickTime as well, although I don’t know what its omission would do.
Now you should have “Broderbund Software” group in Program Manager and the Zoombinis launcher inside it!


First of all, I had to find my old .VCD file (from my Virtual Drive Manager days on a non-free OS). I know those are basically ISO files and can just loop-mount them. Unfortunately, my .VCD file was corrupted. I then had to scrounge around for the old .FCD file and finally found it. But then, I had to try to get the contents out of it. I spent about 45 minutes researching online before I found IsoBuster. That software is shareware, but its free components worked enough to let me copy out the contents of the FCD file. On GNU/Linux these days, it’s all ISOs, and those are much easier to work with and find tutorials.

Did you know that 7zip can extract files from ISO and VHD files? That was very neat to learn.
I tried installing the game in Wine, and after getting the cd check part to work (by modifying the ini file “INSTALLFROMDRIVE=D”), I ran into an error: “Cannot initialize graphics.” And it included some contents of a register, and I never solved it.

err:int21:INT21_Ioctl_Block int21: unknown/not implemented parameters:
int21: AX 440d, BX 0004, CX 0848, DX db46, SI 0000, DI 0000, DS 0000, ES 0000
fixme:reg:RegOpenUserClassesRoot (0x7c, 0x0, 0x2000000, 0xe2e6d8) semi-stub
err:int21:INT21_Ioctl_Block int21: unknown/not implemented parameters:
int21: AX 440d, BX 0004, CX 0848, DX dde2, SI 0000, DI 0000, DS 0000, ES 0000

I think that’s functionality that just hasn’t been added to Wine. I’m pretty sure the game does some early DirectX fullscreen mumbo-jumbo and this version of how it does that was not implemented in wine. Ah, well.
But, during all this work I had read the Zoombini readme and it indicates it can be installed in Windows 3.1, ergo the main part of this article.



General Win 3.1 howto
Another general Win.31 howto, with sound and video driver installations
Sound driver SB16W3X
Video driver S3

Devuan, Dell Inspiron 1525, and b43 wireless network card

In my attempts to be more diverse in my GNU/Linux experience (and not be so dependent on systemd for everything), I am using Devuan on my old Dell Inspiron 1525.
Getting my Broadcom BCM4312 802.11b/g LP-PHY [14e4:4315] wireless network card working was one of the harder tasks on it. Installing freeipa is another, and it involved upgrading the distro to the rolling release version, ceres.

apt-get install firmware-b43-installer

Make sure that command downloads and extracts the broadcom driver. I think that package is from the contrib or non-free package set (in sources.list) and not main.
If it does not do the downloading part, you might have to remove the package and install it again.

modprobe | grep -E 'b43|wl|bcm'

Make sure the kernel module was installed by checking for it with modprobe.
I rebooted at various points, but it might not be necessary to do so. If you have to remove and add it again, use modprobe -r b43 ; modprobe b43.
I could then see the device listed when I ran

ip link show

I tried to enable it:

ip link set wlan0 up

But it warned me that it might not be able to do that because of rf-kill. Rather than remember/search how to do that on the cli, I just switched to wicd and checked the box for “switch on wifi.” Then I could set it up.
I also had to configure wicd to use “wlan0” as the wireless network card. And I threw in some service networking restart in here somewhere as well.
After all that, then wicd saw the wireless networks near me and I could join my wireless network!


Interesting, how running from systemd has made me embrace closed-source drivers. I don’t know what to say about that. But my laptop is not dependent on a wired network connection or systemd.

Additional notes

eudev:amd64 in ceres is giving me grief and will not install, which messes up pulseaudio I think, and certainly bluez and xserver-xorg-core. If you try this whole process on an Inspiron 1525, go with the 32-bit devuan and let me know it if works better.




Delayed cleanup of temp files for shell script

If you want the temp files from your script to be left around for a few minutes, you can use a few shell tricks to remove a temp directory a few minutes later.

If the environment variable FETCH_NO_CLEAN has any content at all, the script will not clean up at all.
The script sends a heredoc to a separate, nohupped shell instance. The commands are to wait so many seconds (default of 300 seconds), and then remove the directory.

To ensure the cleanup function is called, set a trap on the most common exit codes (0 through 20) to call the function, unset the traps, and then exit.
Then you can define a tempdir, and use it to make some temp files.

Using the TMPDIR variable is safe on FreeBSD mktemp, but bash will be /usr/local/bin/bash.

Get SID from Linux ldapsearch in Active Directory

With the help of a fantastic post on ServerFault, here is a way to find a user’s SID in string format from an ldapsearch against Active Directory.

# Filename:
# Author: YasithaB
# Startdate: 2018-02-14 15:58
# Title: Script that Converts Sid from AD Ldap Hexadecimal into String
# Purpose: Help convert sid to usable value
# History:
#    2018-02-15 Modified to work with kornshell
# Usage:
#    ldapsearch -b 'dc=prod,dc=example,dc=com' -s 'sub' -x -D 'CN=My Username,OU=Domain Users,DC=prod,DC=example,DC=com' -W -H 'ldaps://' '(cn=Target Username)' objectSid | grep -E '^objectSid:' | awk '{print $2}' | ./ --stdin
# Reference:
# Improve:
# Document: Below this line

# Base-64 encoded objectSid
case "${1}" in
   "--stdin" ) read OBJECT_ID ;;
   "") : ;;
   *) OBJECT_ID="${1}" ;;

# Decode it, hex-dump it and store it in an array
H="$(echo -n $OBJECT_ID | base64 -d -i | hexdump -v -e '1/1 "%02X"')"

# SID Structure:
# LESA = Little Endian Sub Authority
# BESA = Big Endian Sub Authority
# LERID = Little Endian Relative ID
# BERID = Big Endian Relative ID



echo "${SID}"

getent passwd -s sss LOCALUSER shows local user


I want to easily and quickly tell if a user is local or domain (don’t care which domain).


  • freeipa-client-4.6.1-3.fc27.x86_64
  • sssd-1.16.0-4.fc27.x86_64

Full story

I am writing a script that will show if a user is local, sssd, can ssh, and is permitted by sssd.

Currently I am doing the check for if the user is from the domain with the getent passwd -s sss $USERNAME command. But I ran into an issue where checking the sssd database returns a local user!

# getent passwd -s sss 'bgstack15-local'

Checking the contents of the database (cache) for sss shows sssd apparently caches all sorts of information about the local user.

# sudo su root -c 'strings /var/lib/sss/db/* | grep bgstack15-local' | sort | uniq
[...output truncated]

I tried clearing the sssd cache overall, and just for the user. Neither made a difference.

# sss_cache -U
# sss_cache -u bgstack15-local

The user does show up as a local user, and I promise it is only a local user!

getent passwd -s files 'bgstack15-local'

The man pages for getent(1) and getpwent(3) don’t help me understand what could be going on. sssd(8) shows me that sssd can cache local users, which actually goes against what I want! The nss section of sssd.conf(5) doesn’t help, but maybe I didn’t take enough time to read it. I’m a little stuck.

My sssd.conf

id_provider = ipa
ipa_server = _srv_,
ipa_domain =
ipa_hostname =
auth_provider = ipa
chpass_provider = ipa
access_provider = ipa
cache_credentials = True
ldap_tls_cacert = /etc/ipa/ca.crt
krb5_store_password_if_offline = True
services = nss, pam, ssh, sudo
domains =
homedir_substring = /home

Last resort

I can try doing my checks against ${USERNAME}@${DOMAIN} when doing the -s sss check, but that means I then have to iterate over all domains in sssd.conf and that would slow the process down.


The option that controls this behavior is buried in sssd.conf(5) on CentOS 7 and Fedora, but not in the online man page.


enable_files_domain = false

Reference 3 shows that sssd makes a “fast cache for local users.”

From man sssd.conf(5) on my Fedora system:

   enable_files_domain (boolean)
       When this option is enabled, SSSD prepends an implicit domain with
       “id_provider=files” before any explicitly configured domains.

       Default: true

Disabling this behavior lets me make a simple check to see if it is a local user or domain user.


  1. ddg: sssd disable caching local users
  4. Fedora 27 sssd.conf(5)

Ldapsearch notes

This post will be updated over time.

List all members of an AD group, including following the nested group membership

ldapsearch -b 'dc=dc=example,dc=com' -s 'sub' -x -D 'CN=B Stack,OU=Domain Users,DC=example,DC=com' -W -H 'ldaps://' '(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:=CN=complex_sample_group,OU=Linux,OU=Security Groups,DC=example,DC=com))' samaccountname | awk '/^samaccountname/{print $2;}'



Unattended software updates on Devuan

Devuan, as a fork of debian that uses sysvinit (or another– your choice), still uses debian-based utilities. I come from the Fedora/Red Hat/CentOS rpm-based family of distributions, and I struggle with the dpkg-based package management on occasion.

I really dislike how the software upgrades will sometimes pause in the middle, to display the changelog. If I wanted a changelog, I’d go read it! When I issue a command to update packages, I want to walk away, and come back, and it be done, not get stuck at 20% because openssh changed some defaults and wants to tell me. It emails me anyway! I find the defaults of apt-get to be not sane.

Here is how to configure apt-get to run without pausing to display duplicate information or ask you questions.

export DEBIAN_FRONTEND=noninteractive
apt-get -q -y upgrade