Setting ‘User Cannot Change Password’ using Python

Adding users manually to Active Directory can be a chore, especially if you have a lot of users to add and/or you need to remember to set several options. Fortunately AD is readily scriptable. I generally use Python for this purpose, and there are numerous examples for how to do things like add a new user or add an account to a group.

One thing I couldn’t find was a simple account of how to set the option which the ADUC ‘New User’ wizard labels ‘User Cannot Change Password’ . This option is not as simple as setting a flag when creating the user object; you have to add an ACE denying the ‘Change Password’ permission. Microsoft helpfully document the process, so it’s just a matter of translating the instructions into Python.

# See
# Standard definitions
ChangePasswordGuid = '{ab721a53-1e2f-11d0-9819-00aa0040529b}'
SID_SELF = "S-1-5-10"
SID_EVERYONE = "S-1-1-0"
# Get the full localised names for 'Everyone' and 'Self'
# For English language Domain Controllers this is equivalent to:
# selfName = u'NT AUTHORITY\\SELF'
# everyoneName = u'Everyone'
selfAccount = win32security.LookupAccountSid(None,
everyoneAccount = win32security.LookupAccountSid(None,
selfName = ("%s\\%s" % (selfAccount[1], selfAccount[0])).strip('\\')
everyoneName = ("%s\\%s" % (everyoneAccount[1], everyoneAccount[0])).strip('\\')
user = active_directory.find_user(userName)
sd = user.ntSecurityDescriptor
dacl = sd.DiscretionaryAcl
for ace in dacl:
    if ace.ObjectType.lower() == ChangePasswordGuid.lower():
        if ace.Trustee == selfName or ace.Trustee == everyoneName:
sd.DiscretionaryAcl = dacl
user.Put('ntSecurityDescriptor', sd)

Two things to note:

First, I’ve assumed that the name of the user to modify is stored in ‘userName‘, and used the active_directory module to do the lookup. Alternatively the object can be retrieved using win32com directly, by doing something like the following:

location = "cn=Users,dc=example,dc=org"


location = "ou=Roaming Users,ou=My User OU,dc=example,dc=org"

followed by

user = win32com.client.GetObject("LDAP://cn=%s,%s" % (userName, location))

In the active_directory case userName could be either the logon name (eg. ‘jsmith’) or the canonical name (eg. ‘John Smith’). In the win32com case it has to be the latter.

Second, in my case the user objects already had the relevant ACEs so it was just a case of setting them to ‘deny’ when necessary. Microsoft’s documentation describes how to add the entries if they’re absent, so presumably there must be circumstances in which that would happen. Translating that description into Python is a simple enough process that it’s left as an exercise for the reader.


This is the new computer case I received in the post today:

Alongside the box it came in:

And the box that came in:

ZFS: One or more devices has experienced an unrecoverable error

I’m using ZFS (via ZFS-FUSE), and at one point a zpool status gave me this rather scary report:

zpool status
  pool: srv
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
 scrub: none requested

        NAME                                                      STATE     READ WRITE CKSUM
        srv                                                       ONLINE       0     0     0
          disk/by-id/usb-Samsung_STORY_Station_0000002CE0C43-0:0  ONLINE       0     0     1
          disk/by-id/scsi-SATA_ST3500630AS_9QG3JRW0               ONLINE       0     0     0
          disk/by-id/scsi-SATA_SAMSUNG_HD103UJS13PJDWS516679      ONLINE       0     0     0

errors: No known data errors

‘Unrecoverable error’, eh? Crap. Wait, how can applications be unaffected by an unrecoverable error? How can there be ‘no known data errors’? Also, how is there a checksum error, but no read or write errors? What other operation could there be? Better check that link

…Well apparently ‘the device has experienced a read I/O error, write I/O error, or checksum validation error’. I guess that implies an answer to the last question: ‘READ’ and ‘WRITE’ refer specifically to disk I/O errors. Not to errors in reading or writing in general, just those where the disk itself has detected an error and reported it back. The way that information is presented is pretty apalling as you just need to know that peculiarity in order to interpret it, but okay, let’s press on.

‘Because the device is part of a mirror or RAID-Z device, ZFS was able to recover from the error and subsequently repair the damaged data’. What? No it isn’t. This is just a striped pool: no mirroring or RAID-Z involved. Any anyway, you said it was unrecoverable. Now I’m beginning to worry. The documentation claims that ZFS was able to recover from an unrecoverable error using data replication that doesn’t exist; WTF does that mean? Well obviously it means that the documentation was written by an imbecile, but what’s the message they’re clumsily trying to get across?

After some googling led me to this thread, I did eventually work this out. You get the message about an unrecoverable error if and only if (and this part’s genius) ZFS was able to recover. How very… special. If it wasn’t able to recover, you’ll instead be told that ‘a file or directory could not be read due to corrupt data’. No mention of the word ‘unrecoverable’ there.

But wait, how could it recover from it if there’s no data redundancy, and why does it think it’s a mirrored or RAID-Z device? The answer to that would appear to be that, through some happenstance, the error corrupted some metadata rather than actual file data. Since metadata always has at least one redundant copy, it corrected it as if it were mirrored. Phew.

So to recap: so far as ZFS is concerned, the alarming phrase ‘unrecoverable error’ means ‘error from which ZFS has successfully recovered’. Thanks for that Sun.


A Visual Git Reference

This page gives a good visual overview of numerous Git operations. If you understand Git in principle, but are unsure about the exact meaning of certain commands, then this may be useful; for each operation covered it gives a description and a block diagram of how it changes the state of the repository.

If you’re completely in the dark, or if you don’t understand what a DAG is then you might be better off with some of the introductory documentation.

Bonus: The images are all drawn using TeX and a package I’d never heard of called TikZ. The examples page is mindblowing.


This graphical Python shell appears to be an excellent tool for interactive Python use, possibly supplanting IPython. From the announcement:

* Has whatever you would expect from a graphical Python shell -
attribute completion, tooltips which show how to call functions,
highlighting of matching parentheses, etc.
* Fixes a lot of IDLE nuisances - in DreamPie interrupt always works,
history recall and completion works as expected, etc.
* Results are saved in the Result History.
* Long output is automatically folded so you can focus on what's important.
* Jython and IronPython support makes DreamPie a great tool for
exploring Java and .NET classes.
* You can copy any amount of code and immediately execute it, and you
can also copy code you typed interactively into a new file, with the
Copy Code Only command. No tabs are used!
* Free software licensed under GPL version 3.

Plus numerous other useful features highlighted on the website. My biggest gripe so far is that it uses Ctrl+Up/Down instead of simply Up/Down to go back through command history; maybe that’ll become configurable.

NB: I have no connection to this at all; I just think it looks good.

Automating Debian security updates

Thanks to ‘foom’ on LWN, comes a neat recipe for automatically installing critical updates on a Debian system with minimal risk: It’s explained in some detail, but in brief it uses (optionally) a separate sources.list into which you can put only critical sources, and makes dpkg/apt choose the default responses to any questions. Fortunately Debian are good at making sure that their security updates don’t change any behaviour unless absolutely unavoidable, so there shouldn’t be any unexpected surprises.


How did I not know about this?

Mintty is a terminal emulator for Cygwin. It is based on code from PuTTY 0.60 by Simon Tatham and team.”

Previously I’ve been using PuTTYcyg which is a version of PuTTY with Cygwin support added. It’s good, but mintty seems a lot neater – rather than being a hacked version of PuTTY it’s a dedicated application derived from it. Also, it’s actually packaged in Cygwin which is a plus.

This could almost be an elegant replacement for the (truly abysmal) Windows command prompt, except that a complete replacement would need to be compatible with the vast array of existing console applications – and that’s a rather difficult task for technical raisins. The author has also developed a program which should solve part of the issue, and deserves investigation.

Apple Sues HTC for Patent Infringement

As reported by just about everybody, those litigious bastards are at it again. The BBC has a reasonable summary, but Gizmodo seems to have the best coverage so far, including the list of (20!) patents, the full filings, some links to Apple’s related issues with Nokia1 and Palm, and a brief response from HTC.

It seems fairly clear this is mostly about competition from Android, but get this:

“We can sit by and watch competitors steal our patented inventions, or we can do something about it. We’ve decided to do something about it,” said Steve Jobs, Apple’s CEO. “We think competition is healthy, but competitors should create their own original technology, not steal ours.”


Let’s compare that to his opinions when it’s the other way around:

That man is so full of shit.


HTC finally responds – sadly with just the expected content-free press release. ‘We’re really good’, ‘We innovate loads’, ‘We don’t think this is fair’, etc.

  1. six of one and half a dozen of the other there really []

Connecting a screen session to ssh-agent

GNU screen is an excellent way of keeping a persistent multi-terminal session for console based programs. It shines when connecting to a remote server – ssh in, run screen to create a session, then do whatever you want in it. At any point you can detach from the session and it will keep running in the background until you reattach it (or screen is killed for some reason; good luck maintaining a persistant session across reboots). This works even if your connection is reset by Pierre, or whatever.

An SSH authentication agent (such as ssh-agent or Pageant) is a similarly excellent way of securely1 forwarding ssh authentication requests, allowing for something resembling single-sign-on between machines configured to accept your ssh key.

There is one problem however: the ssh client knows to connect to a running agent based on the environment variables the agent provides. On the other hand, screen inherits its environment from the shell that started it in the first place. When you reconnect, you are presented with exactly the environment you left, which has a different ssh-agent magic token – leaving ssh unable to find the agent.

Enter the following handy function:

function ssh-reagent () {
    for agent in /tmp/ssh-*/agent.*; do
        export SSH_AUTH_SOCK=$agent
        if ssh-add -l 2>&1 > /dev/null; then
            echo Found working SSH Agent:
            ssh-add -l
    . ~/.ssh-agent
    if ssh-add -l 2>&1 > /dev/null; then
        echo Found working SSH Agent:
        ssh-add -l
    echo Cannot find ssh agent - maybe you should reconnect and forward it?

Which I got from this guy. Put this in your ~/.bashrc2 and then you can type ‘ssh-reagent’ to set the appropriate environment variable. Alternatively, if you prefer a greater degree of automation, the author has a further development.

NB: My version has two differences to the original version in that post The first is a bugfix changing 2&>1 to 2>&1; see here if you don’t understand that. The second is to source ~/.ssh-agent; unfortunately I can’t remember doing that and I don’t seem to have a decent commit log for it, so I’ll be damned if I can remember what problem it fixed :P .

  1. As long as you trust root on any intermediate servers. For more on that look here, especially the section on ‘Agent Security Concerns’ []
  2. Or the equivalent for your shell of choice, if it acceps the same syntax []

Using physical disks with VMWare server

For some reason (product differentiation? simple oversight?) VMWare Server 21 has no option to create a VM using a physical disk. Fortunately, that doesn’t mean that it can’t use them; you just need to import a predefined VM and tell it to use that. It’s possible to create a VM in the right format using some other version of VMWare – Workstation, an older version of Server, and possibly Fusion – but that means you need to have those around.

Alternatively, there are some third-party tools to do the job. Take a look at VMX Builder; it’s a free (as in beer) Windows program, that’s said to work in Wine – though if you’re running Linux you’d probably be better with KVM and virt-manager than VMWare. VMX Builder makes it straightforward to define a VM as you need (NB: if you have a 64-bit guest you may need to choose the LSI Logic virtual SCSI controller).

Having done that, go to the VMWare console and choose ‘Add Virtual Machine to Inventory’ from the ‘Virtual Machine’ menu.

Using this method it’s possible to boot a real physical Linux installation from within Windows and have it run in the background as a service2. Most virtualisation options on Windows are either a) expensive, b) arbitrarily limited – 32-bit only, single-processor only, etc. or c) intended to run in the foreground as a standard windowed application.

  1. Downloadable from []
  2. If you’re doing that it’s probably worth looking at open-vm-tools which is probably packaged by your distribution of choice, and probably more likely to actually work than VMWare’s official version. []