Somewhat astonished by the triumphal course of our Linux thin clients we decided to take the concept to the next level and also offer Windows logons on the same thin clients. To this end, we needed to add our OpenLDAP user directory to the Active Directory so that the Windows Terminal Server can authenticate thin client logins. The basic part of adding a user to an Active Directory is pretty easy, but then at some point you realize that for full-fledged Terminal Server operation one also needs the mysterious TerminalServicesProfilePath. And this is where the fun starts. Fasten your seatbelt.
Now, it is one thing to store the string \\winprofile\profiles\adtest\profile.ts in a binary blob in a
plaintext LDAP database, but the actual encoding of this blob is simply
hair-raising. I can only begin to imagine what might have prompted
the Terminal Server team to encode one character in three bytes (can you
spell efficiency?), in a way that is so mind-bogglingly nutty that one
almost has to admire it. Seriously Microsoft, this is sick. You people
need to see a doctor. Alas, resistance to esh's and daduke's mad hexedit
skillz is futile, and it took about 6 hours until the
userParameters blob was containing the values we want.
We have not yet figured out all details of the userParameters blob, but we do know that it contains field names in plaintext followed by the value(s) in said screwed-up binary. For our purpose of simply setting TerminalServicesProfilePath, we just took an existing entry soft as a template and then encode the desired value to binary and paste it into the original pattern. Should you ever find yourself in the predicament of having to create these fields yourself - and I honestly hope you won't -, you might want to take my PERL script as an inspiration.
Update: my man Harry implemented the algorithm in C and was kind enough to make the source code available. Thanks, Harry.
Update II: Some more source code can be found here. Thanks again, Harry.
But now let's come back to the way the values are obfuscated in the binary blob. As mentioned before, each character is encoded in three bytes of binary. A look at the following schematic might be instructional (this is for character 'a'):
Basically, the algorithm works like this:
- for each character you want to encode, do:
- split the character's byte into nibbles xxxx and yyyy
- have a look at xxxx. If it's <= 9, control x equals 001011, otherwise it's 011010
- have a look at yyyy. Here the bit patterns for control y are 001110 (yyyy<=9), 011010 otherwise
- if xxxx>9: xxxx -= 9
- if yyyy>9: yyyy -= 9
- take the 1110 prefix, control y, yyyy, control x and xxxx and glue them all together to yield a 24 bit string
- convert this bit stream to three bytes
Update: now there is some documentation