blackadder has asked for the wisdom of the Perl Monks concerning the following question:

Monks,

What I am trying to do with this following code is to be able to assign permission to folder and sub folder level for a given NT account.

Basically on the command line I type in the script name and then followed with the required permission.
example; c:\myscript READ WRITE

However it doesn't work, because the perms add command expects the permissions to be a constant. My question is; how the hell can I pass @ARGV values to the perms add command as constants? Or is what I am trying to do possible?

In dave Roth’s second book he uses the constants in side the add command (i.e not through variables) and on the perms home page web site @ Roth.net there isn’t one example that shows how this can be achieved.

Can someone please enlighten me on how can I achieve this.
use strict; use Win32::Perms; my $path = 'c:/temp'; my $folder_ace = shift @ARGV; my $subfolder_ace = pop @ARGV; my $perms = new Win32::Perms($path) || die "\n$^E\n"; print "\nPath: " . $perms->Path(); $perms->Add('MYDOMAIN\bloggJo', $folder_ace|$subfolder_ace, ACCESS_ALL +OWED_ACE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE); if ($perms->Set()) { print "\nDone\n"; } else { print "\nFailed\n"; }
Many Thanks for your help in advance.

Replies are listed 'Best First'.
Re: Perms Perms Perms
by BrowserUk (Patriarch) on Sep 13, 2002 at 12:45 UTC

    You could do the if{...}elsif{...}elsif{...}else{...} things, but much simpler would be to set yourself up some hashes that will convert the strings to their bitmap constant values like this:

    #! perl -sw use strict; use Win32::Perms; my %ACE_masks = ( FULL => FULL, # Full access (RWDXOP) ALL => ALL, # Same as FULL CHANGE => CHANGE, # Change access (RWDX) READ => READ, # Read access WRITE => WRITE, # Write access DELETE => DELETE, # Delete access EXECUTE => EXECUTE, # Execute access NO_ACCESS => NO_ACCESS, # No permissions specified ); my %ACE_types = ( ALLOW => ALLOW, # The permission mask is allowed GRANT => GRANT, # Same as ALLOW DENY => DENY, # Permission mask is denied AUDIT => AUDIT, # The permission mask is for auditin +g OWNER => OWNER, # The account specified is the OWNER + (the permission mask is ignored) GROUP => GROUP, # The account specified is the GROUP + (the permission mask is ignored) ); my %ACE_flags = ( DIRECTORY => DIRECTORY, # The permission is for a directory DIR => DIR, # Same as DIRECTORY KEY => KEY, # the permission is for a Registry k +ey CONTAINER => CONTAINER, # The permission is for a container +object (dir, Registry key, etc) FILE => FILE, # The permission is for a file NON_CONTAINER => NON_CONTAINER, # The permission is for +a non container object (file, etc) SUCCESS => SUCCESS, # If the type is AUDIT then this wil +l log a successful audit FAILURE => FAILURE, # If the type is AUDIT then this wil +l log a failed audit );

    This is only a subset of those exported by Win32::Perms, but it may be enough for your needs.

    You would use these in a snippet from your code like this:

    ... $perms->Add('MYDOMAIN\bloggJo', $ACE_masks{$ARGV[1]}|$ACE_masks{$ARGV[ +2]} ACCESS_ALLOWED_ACE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_AC +E);

    This will take the 2nd string that you supply on the command line as $ARGV[1] (ie. READ), use that as the key in the %ACE_masks hash and retreive the corresponding bit map. The same for the 3rd command line parm $ARGV[2] (WRITE) and do the same. It will then binary or (|) these together and then supply the result to Add().

    If you need to supply a variable number of arguements, then you will need to loop over the @ARGV array, lookup the strings, oring the values into a scalar and then pass those.

    If you get stuck with that, come back.


    Well It's better than the Abottoire, but Yorkshire!
      "If you get stuck with that, come back".

      Many thanks for your help,....

      If I wanted to implement the ‘List’ access type permission (this can be achieved in WinNT Explorer by pointing at a directory icon, right clicking, then selecting properties, security and permissions and then using the drop down field 'type of access' to select the List permission), which is made of Read and Execute (RX) | (Not Specific). My question is, how can I program this using perms? i.e.
      $dir-> Add (‘MYDOMAIN\JoBloggs’, (RX)|(Not Specific), ACCESS_ALLOWED_A +CE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE); )
      I am not sure how to implement the Read and Excute on one side of the ‘or’ and the 'Not Specific' bit on the other side.

      Thanks for your help in advance.
Re: Perms Perms Perms
by ozone (Friar) on Sep 13, 2002 at 10:52 UTC
    I'm not an expert on Win32, or the Win32::Perms module you're using, but something like this should work:

    $userPerm is your command line argument

    my $flags = $folder_ace|$subfolder_ace, ACCESS_ALL +OWED_ACE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; if($userPerm eq 'READ') { $flags |= READ; } elsif($userPerm eq 'WRITE') { $flags |= WRITE; } $perms->Add('MYDOMAIN\bloggJo', $flags);

    I've kept this verbose for clarity.

    Your basic problem is that 'constants' in Perl are actually calls to subroutines, which return a constant value. And as the 'READ' or 'WRITE' arguments from the command line are simply text strings, they aren't then interpreted as constants.

    So you need to 'translate' the command line args into calls to the relevant perl 'constants'.

      Thanks very much for this.

      But my Command line arguments (i.e. @ARGV) are broken into $folder_ace and $subfolder_ace, so I am a bit confused on where do I obtain $userPerms? @ARGV is an array with two elements in it, the first is the perms type for folder level and the second element is the perms type for sub folder level.

      I appreciate it if you could clear this up for me.

      Regards
      Blackadder
Re: Perms Perms Perms
by particle (Vicar) on Sep 13, 2002 at 13:13 UTC
    how the hell can I pass @ARGV values to the perms add command as constants?

    the question you should be asking is: how can i convert @ARGV values to constants for use with the add command?

    i haven't tested this, but it *looks* right...

    #!/usr/bin/perl require 5.006; use strict; use warnings; $|++; use Win32::Perms; ## takes directory path and permissions as args my( $path, @requested_perms ) = @ARGV; my $dir = Win32::Perms::new( $path ) || die $!; print "\nPath: " . $dir->Path(); ## map args to valid ace permissions ## found at http://www.roth.net/perl/perms/#Table1 my %args_to_perms = ( READ => READ, WRITE => WRITE, FULL => FULL, ALL => ALL, CHANGE => CHANGE, DELETE => DELETE, EXECUTE => EXECUTE, NO_ACCESS => NO_ACCESS, ); ## build full perms list my $perms; $perms |= $args_to_perms{$_} for @requested_perms; ## add access control entry $dir->Allow( 'MYDOMAIN\bloggJo', $perms, ACCESS_ALLOWED_ACE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ); $dir->Set() ? print "\nDone\n"; : print "\nFailed\n";
    Update: looks likeBrowserUK beat me to it. well, at least i've given you a start on taking variable params from the command-line...

    ~Particle *accelerates*

Re: Perms Perms Perms
by blssu (Pilgrim) on Sep 13, 2002 at 14:20 UTC

    As others have said, those READ and WRITE constants are actually Perl subroutines. You can't use "READ" the string as if it were READ the subroutine.

    However, you can find the subroutine using the string name and then call it. There are two ways to do this. The first is to use string references and the second is to use the package "stash". Here's a short demo:

    use strict; sub READ () { 34 } { no strict 'refs'; print &{'READ'}(), "\n"; } { print &{$main::{'READ'}}(), "\n"; }

    You "use strict" so you'll probably want to use the second method. Here's the change you need to make to your program:

    &{$main::{$folder_ace}}() | &{$main::{$subfolder_ace}}()

    Be sure to include those empty parens -- when calling subs using the '&', the prototype is ignored and the current '@_' will always be passed to the sub unless an explicit argument list is given. The empty parens means the sub gets an empty argument list.

    WARNING! This technique is not safe to use unless you trust the input -- it can allow people to call any subroutine in your package. I think it's ok to use in the example without any checking, but if you are very concerned about security, check the strings before looking up the subroutine.

      OK, the hash technique seems to work,....(Thanks very much for this chaps)

      Now, in NT explorer, if I wanted to assign read permission -which is (RX)(RX) i.e. read and execute - to Mr Jo Bloggs on the directory c:/temp then I would do something like this:
      Use Win32::Perms; My $path = ‘c:/temp’; My $dir = new Win32::Perms($path) || die “\n$E, $^E\n”; $dir->Add(‘MYDOMAIN\BloggsJo’, READ|EXECUTE, ACCESS_ALLOWED_ACE_TYPE, +OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
      If I wanted the Change permission then I would do this:
      $dir->Add(‘MYDOMAIN\BloggsJo’, CHANGE|CHANGE, ACCESS_ALLOWED_ACE_TYPE, + OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
      And if I wanted Full permission, then I change the CHANGE|CHANGE to FULL|FULL. All this works fine, however If I wanted to assign the List permission – which is (RX)(Not Specific) – or the Add&Read permission - which is (RWX)(RX). Then can someone please enlighten me on how can I go about implementing this?

      Thanks in Advance.
      Regards
Re: Perms Perms Perms
by jordanh (Chaplain) on Sep 13, 2002 at 14:02 UTC
    I hesitate to give this "solution", but you can generate code to execute in Perl. It's a dangerous practice, but it is possible.

    I've not tested this, but you _should_ be able to replace your call to Add() with something like:

    eval( '$perms->Add(\'MYDOMAIN\\bloggJo\', ' . $folder_ace . " | " . $subfolder_ace . ' ACCESS_ALLOWED_ACE_TYPE, OBJECT_INHERIT_ACE | CONTAINER_INHERI +T_ACE );' );

    uhhh... don't do this... There are lots of issues. Use the other suggested solutions instead, you'll definitely want to check that the values passed in are valid constants anyway, so why do this.

    Thought I would point out the flexibility of Perl here.