smbpasswd GUI

Danny Wahl's picture Danny Wahl  •   •  DevOps

I recently came across an application I wrote a while back in AppleScript to slap a basic GUI on OS X terminal program smbpasswd.  This utility is basically the BSD version of dscl found on Linux – and interfaces with Microsoft Active Directory.  Here’s the man page as of Snow Leopard:

       smbpasswd - change a users SMB password

       smbpasswd   [-a]   [-c ]  [-x]  [-d]  [-e]  [-D debuglevel]  [-n]  [-r ]
        [-R ] [-m] [-U username[%password]] [-h] [-s] [-w pass] [-W]  [-i]  [-L]  [user-name] [username]

       This tool is part of the samba(7) suite.

Apple has actually done a pretty good job integrating this utility into the core of OS X (password expiry, etc…) but only for bound clients.  That’s where this little utility comes in.  Here’s the scenario, a client has a MacBook (or other device) with a local account that isn’t affiliated with the directory, but they also have a directory account to use intranet resources like printing, or network storage. OS X doesn’t provide a way for the client to manage their AD account outside of terminal, and if something happens like an expired password, everything just stops working, and the only way for them to get their account working again is to log into a bound client and update their account.  Needless to say, most users don’t like either of those options.  So this is smbpasswdgui (or as I call it “NetPass”) , a simple AppleScript program that presents the user with a workflow to change their password.

(* Written by Danny Wahl *)

set domain to "YourDomain1"  
display dialog "Domain (YourDomain1 or YourDomain2):" default answer domain  
if the text returned of the result is "YourDomain1" then  
    set controller to ""
    set controller to ""
end if

set username to ""  
display dialog "Username:" default answer (do shell script "echo $USER")  
set username to (text returned of result)

set oldpass to ""  
display dialog "Old Password:" default answer oldpass with hidden answer  
set oldpass to (text returned of result)

    set newpass to ""
    display dialog "New Password:" default answer newpass with hidden answer
    set newpass to (text returned of result)
    if length of newpass is greater than 7 then
        exit repeat
        display dialog "Password must be at least 8 characters" buttons {"OK"} default button 1
    end if
end repeat

    set newpassv to ""
    display dialog "New Password (Verify):" default answer newpassv with hidden answer
    if the text returned of the result is newpass then
        exit repeat
        display dialog "Passwords do not match, please verify again" buttons {"OK"} default button 1
    end if
end repeat

    do shell script "(echo " & oldpass & ";" & "echo " & newpass & ";" & "echo " & newpass & ";) | smbpasswd -s -U" & username & " -r " & controller
    display dialog "Network password has been changed" buttons {"OK"} default button 1
on error error_message  
    display dialog "Error: " & error_message buttons {"OK"} default button 1 with icon stop
end try  

Now, this probably isn’t for everyone but it’s easy to change, and I’ll walk you through the workflow.  First it sets a default domain (YourDomain1) and prompts the user for their domain – not every environment has multiple domains, but you may have and – and OS X doesn’t like browsing a forest without an explicit domain.

Next, it takes the domain that your user input (remember OS X uses DOMAINUSERNAME format) and matches it to the fqdn for your domain controller.  Then it asks the user for their domain username (populated with bash username) old password and a new password (and validation) – I threw in a little bit of password policy just for fun.  Then it takes the four variables (domain controller fqdn, directory username, old password, and new password) and pipes them to smbpasswd.  The beauty is that you only have to program minimal error handles – just tell it to display whatever terminal says is the result, since smbpasswd has full error handling built-in.