Windows Remote Log in

David Bolen db3l at fitlinxx.com
Mon Sep 1 17:28:09 CEST 2003


Jesse <redrumjack at hotmail.com> writes:

> What I need is some way for user to enter the proper credentials so
> Python could restart the service on the remote machine.
> 
> If this isn't making sense please disregard and I'll move on to
> something a bit easier.

When I first started doing a lot of management scripts for Windows it
seemed strange to me that so many Win32 API calls would accept a
remote machine name, but no optional credentials.  As it turns out,
Windows shares a single set of credentials per remote machine among
any operations being performed to that remote machine.  If there are
no established credentials due to a prior operation or access that is
still in place, then your default credentials (those currently
established by your login) are used.  And in fact if you try an
operation that does accept credentials, and they are different from
the established credentials the operation will fail (which can be
infuriating at times :-)).

So it's a clumsy mechanism in many ways, but convenient in others
(since any operation the system performs, even with utilities that
don't provide a way to enter credentials) will inherit the established
credentials.

The trick is to get the proper set of credentials in place in a
persistent manner prior to performing whatever operation you want to
do.  One of the simplest persistent mechanisms is by accessing a
remote share.  And since all systems supporting Windows networking
operations always have an IPC$ share (used for basic connection
establishment), you can just "use" that share - as I believe another
responder pointed out recently. You don't need to map it to a drive or
anything, just use the share, and if you want, drop it when you are done.

Once you have this, then I'd just go for straight Win32 network calls
to manipulate the remote machine.  This has the advantage of being
more assured of working on your NT machines, since in most cases they
won't have some of the newer stuff like WMI installed, although you
could add that on.

Mark Hammond's win32all package wraps all of the appropriate functions
that you'll need (both to manipulate the remote access via the shares,
as well as perform remote operations such as calls to the service
manager).  You can generally start by using MSDN to examine how you
would perform the task with Win32 calls and then just find the right
wrapper in the win32all package.  In the 

For example, here's a snippet of code (using the win32net module) from
one of our scripts that is triggered when a remote machine for some
reason loses its D$ share (the administrative share to drive D:).  If
necessary we use the IPC$ share to gain the proper remote credentials,
and then create the remote share.

The NetUseAdd call is effectively the replacement for a command line
"net use" operation without a drive assignment, and the NetUseDel call
mimics the "net use /delete" operation.

Coming into this code:
    use_servers = optional list of machines we already have access to
    machine     = machine we are manipulating
    wic6user    = administrative user on remote machine
    wic6pwd     = administrative password on remote machine

          - - - - - - - - - - - - - - - - - - - - - - - - -

    print "(Creating temporary share)"

    if use_servers and machine not in use_servers:
        print "(Creating temporary use)"
        use_info = {'remote':r'\\'+machine+r'\IPC$',
                    'asg_type':-1,
                    'username':wic6user,
                    'password':wic6pwd}
        try:
            win32net.NetUseAdd(None,2,use_info)
            have_use = 1
        except pywintypes.error, value:
            print "Couldn't create temporary use:", value

    # Create the remote share

    shareinfo = {'netname':'D$','path':'D:\\','max_uses':-1}
    try:
        win32net.NetShareAdd(machine,2,shareinfo)
        have_share = 1
    except pywintypes.error, value:
        print "Couldn't create share:", value

    # ... perform any other operations on remote machine ...

    if have_share:
        try:
            win32net.NetShareDel(machine,'D$')
        except pywintypes.error, value:
            print "Couldn't remove temporary D$ share:", value

    if have_use:
        try:
            win32net.NetUseDel(None,r'\\'+machine+r'\IPC$')
        except pywintypes.error, value:
            print "Couldn't remove temporary use:", value

          - - - - - - - - - - - - - - - - - - - - - - - - -

In the case of managing services, the win32service module wraps most
everything you would need.  You can start a service with StartService,
stop it with ControlService with the SERVICE_CONTROL_STOP code, check
status with QueryServiceStatus and so on.  Or, if the existing
WService module you've been using works fine, you should just be able
to use it unchanged once you have locked in the proper remote
credentials via the IPC$ share.

Another quick 'n dirty approach we've also used is just to use
os.system, or more typically (so you can log the output) one of the
os.popen# calls, to farm the service operation out to a utility like
"sc" from the resource kit or psservice from sysinternals
(www.sysinternals.com).  You still need the IPC$ share in place for
credentials to remote domain machines, but like any other system call,
Windows will simply apply the established credentials to any
operations that those utilities perform.

-- David




More information about the Python-list mailing list