A client had been posting training files and some order templates in an unmarked directory on their website. None of them are really all that secret, but some contact lists and other things got picked up by google.
So, they’ve got pages and pages on their intranet that has links to these docs. Templates for new orders, insurance forms, calculators for price lists, etc… So, I can’t just move them. They are a mixture of doc, xls, docx, xlsx, etc… just random crap.
Initially, I figured, I’ll just put in a nice handler to catch things first (which is so easy that it took me all damn day – I’ll get into that later!)
Here was the real problem: The intranet site it is written in classic asp, so the session variables, so my standard “if session(“loggedin”)<>true then goto login page” isn’t going to work. Classic asp doesn’t have the ease of a handler and if there is a way to do it, well…. I really don’t want to know. Seriously, I’m not going to learn how to write something complicated in a dead language. I’d prefer to learn something new that will be useful in the future.
So, sticking with the .Net handler idea. Here’s the theory I decided upon. Yes, I know, it is horrible, but here it is:
All I’m going to do is check to see if the referring page was within the intranet site. Think about it… If you really really really wanted to, you could write a script that would rip out those files, but seriously…. this is about all it really needs and I’m not going to make a new login page.
Here’s how I started:
Imports Microsoft.VisualBasic
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.IO
Public Class secureDocs : Implements IHttpHandler
Dim mimes As New contentTypes
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim f, strReqPath, filePath, sql As String
strReqPath = context.Request.Path
Dim ref As String = context.Request.ServerVariables("HTTP_REFERER")
Dim fileOK As Boolean = False
Dim strliveSite As String = ConfigurationManager.AppSettings("public-domain") 'I keep these values in my web.config as appsettings
Dim strlocalSite As String = ConfigurationManager.AppSettings("local-domain")
Dim liveSite As Integer = InStr(ref, "http://" &amp;amp; strliveSite)
Dim localSite As Integer = InStr(ref, "http://" &amp;amp; strlocalSite)
If liveSite > 0 Or localSite > 0 Then fileOK = True
If Not fileOK Then
' normally, I'd be checking to see if the user was logged in
' and then send them to a login page, but I just don't have
' the budget for that right now. so....
context.Response.Write("THIS IS A SECURE FILE")
Exit Sub
End If
f = context.Request.Path.Substring(context.Request.Path.LastIndexOf("/") + 1)
filePath = context.Request.PhysicalPath
Dim strContentType As String
Dim extension As String = context.Request.Path.Substring(context.Request.Path.LastIndexOf(".") + 1)
strContentType = mimes.getContentType(extension)
Try
Dim file As New FileInfo(filePath)
Dim len As Integer = file.Length
context.Response.Clear()
context.Response.AddHeader("Content-Disposition", "inline; filename=" &amp;amp; file.Name)
context.Response.AddHeader("Content-Length", file.Length.ToString())
context.Response.ContentType = strContentType
context.Response.WriteFile(file.FullName)
Try
context.Response.End()
Catch ex As Exception
End Try
Catch ex As Exception
context.Response.Write("FILE DOES NOT EXIST")
Exit Sub
End Try
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Class contentTypes
Dim _types As New StringDictionary
Sub New()
makeKeys()
End Sub
Public ReadOnly Property getContentType(myExtension As String) As String
Get
Return _types.Item(myExtension)
End Get
End Property
Sub makeKeys()
_types.Add("acx", "application/internet-property-stream")
_types.Add("ai", "application/postscript")
_types.Add("aif", "audio/x-aiff")
'---- a whole bunch more mime types here -----'
_types.Add("z", "application/x-compress")
_types.Add("zip", "application/zip")
End Sub
End Class
Now, that file I stick into my app_code directory and I can then reference it by putting it in my web.config file.
it needs to be in two spots:
<system.web>
<httpHandlers>
<add verb="*" path="/client_files/*" type="secureDocs" />
<add verb="*" path="/someOtherDirectory/*" type="secureDocs" />
</httpHandlers>
</system.web>
And you’re also going to need to tell the server that you don’t care what the file is, but you absolutely MUST kick off aspnet when you are in the
directories where these files are. Otherwise, IIS will see .doc or .xls and just give it to them without hitting your handler.
<system.webServer> <handlers> <add name="sd" path="client_files/*" verb="*" modules="IsapiModule" scriptProcessor="C:\windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv4.0,bitness64" /> </handlers> </system.webServer>
HOWEVER…. If you run a shitty old server that still has IIS 6.0 on it, this latter module doesn’t work.
You need to open IIS on the server, hit the properties for your website, go to “home direc

No comments yet
No comments yet.
RSS feed for comments on this post. TrackBack URL
Leave a comment