asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search










Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

How to Display File ACLs on Your Web Page without Active Directory
By Larry Schwartz
Rating: 3.6 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    The genesis of this article arose when I found myself in need of providing a list of the access control lists (ACLs) for some of our Web pages. Since the Internet site is hosted by a third party, this precluded the idea of accessing this information through the Windows Explorer file properties. After some thought, I embarked on a mission to display file ACLs on a Web page in a browser. I quickly came to the conclusion that without Active Directory installed, this was going to be a bit tricky.

    I went looking for an object that has these values available. The logical place to start was with the File System object. However, although the File System object allows access to file attributes, it does not allow access to view file ACLs. The more I looked, the more I realized that there was no direct way to call up file ACLs using Active Server Pages without Active Directory installed. I had to take an indirect approach.

    Through some research, trial and error, I ended up getting my results through a patchwork of technologies. I created an ASP script that does the following:

    1. uses the Windows Script Host WshShell object to run CACLS, a WinNT utility, to pipe file ACLs to a text file;
    2. opens the text file with the File System object;
    3. parses through the text file line by line, removing unnecessary and duplicate data;
    4. creates an ADO recordset on the fly and adds each Access Control Entry (ACE) as a record to a column in the recordset; and
    5. displays the results of the recordset in alphabetical order on the ASP page

    CACLS

    CACLS is a Windows NT command line script that, among other things, displays the ACLs of a given file. If you are not familiar with this script, give it a try. Go to your DOS prompt, and type in "CACLS." If this script is installed, (it is installed by default with a Windows NT 4.0 workstation installation) you will see a list of its capabilities and the requisite syntax. You can do a number of things with this script, including edit ACLs. If you want to simply display the ACLs of a given file, the syntax is to type CACLS followed by the full pathname of the file:

    
    
              c:\>cacls c:\inetpub\wwwroot\global.asa
    
    
    

    The output you should see (assuming your global.asa file is located in the directory specified above) is the name of the file and a list of each ACE followed by a colon, and another list indicating the type of access to the file. This is an easy way to display file ACLs, provided you have access to the command line. Since I didn't, I needed a way to get this data into a Web page, and in a format where I could manipulate it. The wheels began to spin.

    The thought came to mind to pipe the results of the CACLS script into a text file. Once in a text file, I knew I could access it from my ASP page. Getting the results into a text file is easy. Simply use the pipe command ">" followed by the full pathname of the file you want to contain the results:

    
    
              c:\>cacls c:\inetpub\wwwroot\global.asa > c:\temp\acllist.txt
    
    
    

    By running this at the command line, I was able to get the results of my script into a text file. But I still had the problem of getting the command line script to run inside of a Web page. The answer was with the Windows Script Host WshShell object.

    Windows Script Host WshShell Object

    The Windows Script Host WshShell object provides access to the Windows shell and registry. This handy object is used for a variety of functions, but most importantly in our case, it can be used to run other programs. As you will see, it has a "run" method that can accept a command string and execute it. To script this, I first built the command string as follows:

    
    
              textFileToQuery = Request.ServerVariables ("PATH_TRANSLATED")
              textFileToQuery = """" & textFileToQuery & """"
              strTextFile = "c:temp.txt"
              strACLCommand = "cmd /c echo y| CACLS "
              strACLCommand = strACLCommand & textFileToQuery
              strACLCommand = strACLCommand & " >" & strTextFile
    
    

    The variable textFileToQuery contains the full pathname of the file whose ACLs will be displayed. I use an ASP server variable called PATH_TRANSLATED that provides the full pathname of the Web page my user has navigated to. You could also use a form to get direct user input. Be aware that this requires your users to know the full pathnames of the files whose ACLs they want to query.

    In the next line I encase the value in quotes. If any of the names have blank spaces in them, the script will not know that the blank space is part of the file name unless you enclose the whole name in quotes. The variable strTextFile contains the text file name to receive the results of the CACLS script.

    The strACLCommand contains the completed command string. When I have a long string, I like to build it in stages, as I have done here, to make it easier to debug. You can include it on one line if you like. Notice the rather cryptic string "cmd /c echo y|" just before I call CACLS. You are probably wondering what it is doing and why. As it turns out, although entering CACLS at the command line runs the script, when you invoke the script through the run method of WshShell, it requires the user to echo back "yes" to proceed. That is what this part of the script is for. Finally, I add the pipe command and the strText File to complete the command string.

    The next step is to pass the command string to the run method of the WshShell object. This is done with the following piece of code:

    
    
              Set objWSH = Server.CreateObject("WScript.Shell")
              objRTC = objWSH.Run (strACLCommand , 0, True)
              Set objWSH = Nothing
    
    

    The run method of the WshShell object accepts three arguments. The first is the command string; the second is the WindowStyle (optional); and the third is WaitOnReturn (optional). In this case, I have set the WindowStyle to "0" (hides the window and activates another window), and WaitOnReturn to "TRUE" (returns any error code returned by the application). Finally, I destroy the WshShell object because it has performed its duty and is no longer needed. Note that when you instantiate the WshShell object you strip off the Wsh part.

    File System Object

    If I were to stop at this point, I would have a file on my server that contains a long string with the results of my command-line CACLS script. The next part of my script invokes the File System object to read and parse through the text file created. This is done with the following piece of code:

    
    
              Const ForReading = 1
              Set FSO = CreateObject("Scripting.FileSystemObject")
              Set File = FSO.GetFile(strTextFile)
              Set TS = File.OpenAsTextStream(ForReading)
    
    

    After setting my constant ForReading, I instantiate the File System object. The next line gets the text file that houses the results of our CACLS script. The third line opens the file as a text stream and assigns its value to the variable TS. At this point, I am prepared to read the text file line by line and add each line as a new record to my recordset. However, before I do this, I need to create the recordset on the fly.

    Crafting an ADO Recordset

    The term "crafted recordset" is sometimes used to describe a recordset that is built from scratch from within an ASP page. There is no connection or database from which the records are pulled. The object is created and filled with records from the ASP script itself. The code for creating a crafted ADO recordset is as follows:

    
    
    
              Set rsNew = Server.CreateObject ("ADODB.Recordset")
              rsNew.CursorLocation = adUseClient
              rsNew.Fields.Append "ACL",AdChar,255,adFldMayBeNull
              rsNew.Open ,,adOpenStatic,adLockBatchOptimistic
    
    

    I was interested in creating a recordset with one column to contain the name of the ACL. As you can see, to achieve this I first instantiate an ADO Recordset using the adUseClient cursor. (Remember to include your adovbs.inc file if you want this script to work). Next I use the append method to create a new column in the recordset. Note that the append method accepts four arguments -- Name, Type, Defined Size (optional), and Attribute (optional). In this case, I named the column ACL, where each record can have up to 255 characters, and the record can contain null. The last line opens the recordset. Note that the first two arguments, Source and Active Connection, are intentionally left blank since there is no connection to a database. The recordset is being crafted on the fly.

    Next I read the text file line by line, clean it up, and populate my recordset. The code for this is as follows:

    
    
              strDomain = "MYDOMAIN\"
              Do While Not TS.AtEndOfStream
                s = TS.ReadLine
                s = replace(s,strDomain,"")
                length = instr(s,":")
                length = length-1
                s = left(s,length)
                duplicate = instr(strFinal,s)
                if duplicate = 0 then
                  strFinal = strFinal & s & "<br>"
                  rsNew.AddNew
                  rsNew.Fields("ACL").Value = s
                end if
              Loop
              rsNew.UpdateBatch
    
    

    As you can see, this is a standard Do While loop. The key here is to open the text file as a text stream and use the ReadLine method to read each line of your text file. After the line is read, I clean it up. Your results will display both the domain name as well as the read/write permissions of the file. Since all I am interested in is the name of the access control entry (ACE), I strip off both the domain name and everything following the colon. Next I look for duplicates. To do this I build a string (strFinal) consisting of each line and use the instring method "instr()" to look for any occurrences of my next line in the last built-up string. If there are none, I add the line as a new record to the ACL column of my recordset. Finally, I close the loop and call UpdateBatch to update the recordset with the new values.

    At this point I have a complete updated recordset. The next thing I need to do is to order the entries and display them on the page. When I did this, I noticed that the first record contains the pathname of the file. Since I did not want to display this record, I simply skipped the record before displaying it. The code for displaying the records is as follows:

    
    
              rsNew.Sort = "ACL desc"
              rsNew.MoveFirst
              rsNew.MoveNext
    
              strAdminUsers = "NT AUTHORITY\SYSTEM, new service 1, new service 2"
              strAdminUsers= Trim(strAdminUsers)
                 do while not rsNew.eof
                    strACL = rsNew.Fields("ACL")
                    strACL = Trim(strACL)
                    posACL = instr(strAdminUsers, strACL)
                       if posACL = 0 then
                          Response.write strACL & "<BR>"
                       end if
                    rsNew.MoveNext
                 loop
              rsNew.close
              set rsNew = nothing
              ts.Close
              set ts = nothing
              set fso= nothing
    
    

    In this final piece of code I start by sorting the recordset, and then skipping the first record as explained above. I next set up a string consisting of all the ACLs that I do not want displayed, such as the admin ACLs that appear on all of the files. I start another Do While loop cycling through each record, checking to see if any of the records match any of the values in my strAdminUsers list. If they do not match, then the ACL is not for an admin user so I write it out followed by a break tag. Finally, I close the loop and clean it up.

    Conclusion

    ASP is indeed the glue that binds several technologies. In the above, I was able to leverage the power of a "C-Script" function like CACLS by using the Windows Script Host, the File System object and an ADO recordset. It is easy to see how this ASP script can be adapted to display or run other "C-Script" functions through a Web page.

    About the Author

    Larry Schwartz ( mailto:larry@larryschwartz.com) is currently a software engineer at Moody's Investors Service, where he is the lead programmer for Moodys.com. Larry began his career in programming in 1995 as a freelance HTML programmer and designer, working with SOHO design shops and small, independent businesses. He has been designing and programming Web sites ever since. Prior to coming to Moody's, he was a consultant to several Fortune 500 companies and the lead programmer for a major Internet startup. He holds a B.S. from SUNY Albany and a J.D. from St. John's University School of Law.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Supporting Products/Tools
    Proposion N2N
    Proposion N2N connects Microsoft .NET applications to Lotus Notes and Lotus Domino databases. This ADO.NET managed data provider allows you to perform blindingly fast queries and updates of Notes data from ASP.NET pages, .NET web services, Windows, or Mobile applications. An innovative SQL-like query language leverages the unique features of Notes and makes collaborative software accessible to relational database programmers.
    [Top]
    Other Articles
    Jun 6, 2002 - Client Side Validation Using the XMLHTTPRequest Object
    Jonathan Zufi shows how to use the XMLHTTP object within JavaScript or VBScript to validate form-field information without having to submit a page and wait for the result.
    [Read This Article]  [Top]
    Nov 6, 2001 - Writing Your Own Script File to Migrate a Database
    Learn how to write a script file using SQL Server's Bulk Copy Program for easy and speedy database migration.
    [Read This Article]  [Top]
    Sep 5, 2001 - Firing Events in a Shared Hosting Environment
    Firing events on a Web server is an easy task. However most of the easy solutions require you to have your own dedicated IIS or SQL Server on the Internet to play with, a privilege not shared by many. In this article, Matthew Muller shows you how to get the same functionality in a shared hosting environment.
    [Read This Article]  [Top]
    Jun 26, 2001 - Dynamically Changing Static Web Galleries
    Web galleries are an easy way to add interactivity and content to your Web site. However, how do you keep the Web galleries consistent with your site and how do you overcome the deficiencies of your Web gallery creation tool? John Sorensen explains a simple way to do both.
    [Read This Article]  [Top]
    Jun 8, 2001 - Implementing Dynamic Arrays of Objects
    Using classes in ASP 3.0 we can create dynamic arrays of objects. Donnell DeLeon Smith's article also shows how we can implement a class of dynamic arrays of objects several layers deep, if required.
    [Read This Article]  [Top]
    Mar 27, 2001 - Using ASP to Send a Wireless Text Message
    Even though SMS is now in high gear, developers remain slated with restrictive limits to carrier resources. Sending an SMS message via e-mail requires the acceptance of several hidden flaws. Joe Lauer shows how to avoid these complications by sending a wireless text-message through the use of ASP.
    [Read This Article]  [Top]
    Mar 1, 2001 - Server-Side Validations Using Regular Expressions
    Add punch to your validation routines by adding regular expressions. Further prepare yourself for the coming ASP.NET regular expression validation control. This article shows you how to use regular expressions and provides sample patterns for different user inputs.
    [Read This Article]  [Top]
    Aug 11, 2000 - Servers-Side Validations on the Client Side
    Servers-side validations on the client side...isn't that an oxymoron? Maybe, but Pandurang Nayak shows us how to accomplish a type of remote scripting using a mix of Javascript and ASP.
    [Read This Article]  [Top]
    Aug 3, 2000 - Recursive Functions
    A function that calls itself repeatedly, satisfying some condition is called a Recursive Function. Using recursion, we split a complex problem into its single simplest case. The recursive function only knows how to solve that simplest case. You'll see the difference between solving a problem iteratively and recursively later.
    [Read This Article]  [Top]
    Jul 27, 2000 - Effect of Using Multiple Scripting Languages in ASP
    Do you know what happens when you use multiple languages within your ASP page? Gopikrishna S throws light on how an ASP page behaves when multiple languages are used for server side scripting.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers