http://qs321.pair.com?node_id=238740
Category: Win32 Stuff
Author/Contact Info Martin Hylerstedt
Description:

I was asked to have a look at security issues for a group of Windows computers, and one of the things I thought about was shared directories. Which directories are visible? I could click away in the network browser but that would be tiresome. Why not practically extract and report it in some language? I work mostly with Windows, and play around sometimes with ActivePerl (5.8.0). There is the package Win32::NetResource available, let's have a look at it... And already in the documentation is what I want; "Enumerating all resources on a particular host".

Usage: Give computername(s) as arguments to script. If no arguments given, it uses computernames hardcoded into the script.

I adjust it somewhat, to go over an array of computer names to check, and write it to a text file. Hmm, why not display it more nicely? use Tk;

A hierarchical listing (HList) would be nice. Could also use a Tree.

Oops, a gotcha. The script barfs if a sharename contains periods (.), since period (.) is the default separator in the entrypath for a Tk::HList and Tk::Tree. The solution was to configure the HList to use something else as a separator. A forward slash (/) would be good, since a / would/could not be used in a sharename. See also the $hlist->add in the inner foreach loop where the children are added.

Wouldn't it be nice to make it more visible which is what? The computername looking different from the sharename? This I wrestled with for a while. I didn't want to make the whole HList bold, only the toplevel nodes. Look, look, look, browse, browse, browse. Tk::ItemStyle to the rescue!

The trick was to

  1. Create a font ($boldfont) with the weight bold
  2. Create a style ($boldstyle) which uses the bold font
  3. For the widgets where I want it, apply the -style.

By wrapping the HList in Scrolled, scrollbars will appear if necessary. To make it more readable, do the rest of the settings with a -configure for the widget.

When I'd removed all comments, notes, tests and "debugging" prints, I was impressed and almost disappointed that the script was only thirty-odd lines. I decided to post it here at Perlmonks as an example (hints) for Win32::NetResource and Perl/Tk.

Now that this is working, I'm thinking of expanding it to display the permissions for the shares (NetShareGetInfo), maybe also flag if the permissions are Everyone-Full Control.

use strict;
use Win32::NetResource qw(:DEFAULT GetSharedResources GetError);
use Tk;
use Tk::HList;
use Tk::ItemStyle;
my @names; 
if(@ARGV) {@names = @ARGV;} else
{
    @names = ("computer1", "computer2", "computer3", "computer4");
}
my $mw = MainWindow->new();
$mw->title("Visible shares");
$mw->resizable("false", "false");
my $hlist = $mw->Scrolled('HList',-scrollbars => "osoe");
my $boldfont = $mw -> fontCreate(-weight => 'bold');
my $boldstyle = $hlist->ItemStyle("text", -font => $boldfont);
$hlist->configure(-width => 50, -height => 40, -separator => '/');
foreach (@names) {
    if (GetSharedResources(my $resources, RESOURCETYPE_ANY,
               { RemoteName => "\\\\" . $_ }))
    {
    $hlist->add("$_", '-text' => "$_", -style => $boldstyle);
    
    foreach my $href (@$resources) {
        my $sharename = (split(/\\/, $href->{RemoteName}))[-1];
        $hlist->add("$_/$href->{RemoteName}", '-text' => "$sharename")
+;
    }
    } # if ends
} #foreach ends
$hlist->pack(); 
MainLoop;
Replies are listed 'Best First'.
Re: Viewing network shares
by Mr. Muskrat (Canon) on Feb 26, 2003 at 14:08 UTC

    Instead of hardcoding the computer names in the script, why not read in the lmhosts file?

    Added from here down.

    I looked at lmhosts.sam and found the following example:

    102.54.94.97 rhino #PRE #DOM:networking #net group's DC 102.54.94.102 "appname \0x14" #special app serv +er 102.54.94.123 popular #PRE #source server 102.54.94.117 localsrv #PRE #needed for the i +nclude #BEGIN_ALTERNATE #INCLUDE \\localsrv\public\lmhosts #INCLUDE \\rhino\public\lmhosts #END_ALTERNATE

    It would be easy to extract the names of the computers (the ones in other domains too) and also to read in the names from include files on other systems.

      As I wrote in the initial description, I did this to check a group of computers, not all "visible" computers on the network.

      I wrote this little thing to save me from manually having to browse the computers for shares. Learning about the topic and writing it took longer than it would have taken to manually check the computers. But next time I want to check some computers it's just a matter of seconds to alter and run it. The ARGV bit also makes it possible to simply run

      sharescheck.pl computer1 computer7 server_A laptopBOB
      Does anyone really use the LMHOSTS file? Maybe for small internal networks with few (Windows) computers, but otherwise I think it's better managed by a Domain Controller (and with DHCP/WINS). It would be better to ask the "Windows network" about its resources than to check a local file whose validity you can't be sure of.
Re: Viewing network shares
by Hyler (Sexton) on Feb 28, 2003 at 09:10 UTC

    I've looked into viewing the permissions (for users and groups) on the shares somewhat, and it seems more daunting than I first believed.

    The {'permissions'} hash key in Win32::NetResource::NetShareGetInfo is merely read, write, change, delete and so on. MSDN mentions the SECURITY_DESCRIPTOR in the SHARE_INFO_502 structure, but that's not available in W::NR::NetShareGetInfo.

    One might work with Win32::FileSecurity, but it says in my version under Known issues/bugs:

    1. May not work on remote drives.

      Things are looking promising, I did some experimenting.

      Win32::FileSecurity::Get("\\\\computer\\share", \%sph); gives you a hash with the keys being users and/or groups and the values a bitmask. You can do the Get on a file, a directory or a share. For example, it could give the key DOMAIN\GROUP with the value 2032127, the bitmask being the permissions listed in CONSTANTS in the documentation for Win32::FileSecurity (DELETE, READ, FULL etc). Maybe it will only be a matter of using EnumerateRights and MakeMask.

      The testing done in ActivePerl 5.8.0 Build 805, Win32::FileSecurity version 1.03 ALPHA 97-12-14.