VSS history on ASP.NET web page


D

Dan Williams

I'm trying to display the version history and number of a Visual Sourcesafe
database on an ASP.NET page and am struggling to overcome the 'The
SourceSafe database path <user> does not exist' error.

VSS is installed on a different server to our web server, so i'm assuming
its a permissions problem with the ASPNET account trying to access the VSS
data and INI file.

I've attempted to give both the ASPNET and IUSR accounts access, but to no
avail. I've even tried to impersonate a different user, but am loathe to do
so as Microsoft doesn't recommend setting the ASPNET account to act as part
of the operating system.

Can anyone give a definitive answer to this problem as to what permissions
i should setup and what account i should have this single page running as?
 
Ad

Advertisements

J

Joe Masters

Are you using a drive name or a network share name for the path to
srcsafe.ini?

Joe
 
D

Dan Williams

Are you using a drive name or a network share name for the path to
srcsafe.ini?

Joe

A UNC network share path.

I have even managed to successfully impersonate myself as the user, and
have ensured that the share and NTFS permissions on the shared folder and
set to allow Everyone access (purely for tests reasons), but to no avail.

Anyone any ideas what the minumum permissions should be, so i can secure
the folder once i have it working?

Here is my complete C# source code (it'll probably wrap, so be wary of
simply cutting and pasting) :-

using System;
using System.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using SourceSafeTypeLib;


namespace BuildItTest
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label CurrentVerLabel;
protected System.Web.UI.WebControls.Label VersionNo;
protected System.Web.UI.WebControls.Label VerHistoryLabel;
protected System.Web.UI.WebControls.TextBox VersionHistory;

public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("advapi32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)]
public extern static int DuplicateToken(IntPtr hToken, int
impersonationLevel, ref IntPtr hNewToken);

private void Page_Load(object sender, System.EventArgs e)
{
// Displays current user, usually ASPNET.
//If web.config is setup with impersonate=true, then current user is
IUSR_MACHINENAME.
VersionHistory.Text =
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

// Attempt to get VSS info without impersonating a different user.
// Causes Sourcesafe database path <user> does not exist error.
// COMException (0x8004d117)
// GetVSSFileHistory();

// <validusername>, <domain> & <usrpwd> are obviously valid strings in
my real code.
if(impersonateValidUser("<validusername>", "<domain>", "<usrpwd>"))
{
VersionHistory.Text = VersionHistory.Text + Environment.NewLine +
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

// Following function call results in same COMException (0x8004d117)
GetVSSFileHistory();
undoImpersonation();
}
else
{
VersionHistory.Text = VersionHistory.Text + Environment.NewLine +
"UNABLE TO IMPERSONATE USER!";
}

// Redisplays current user (again ASPNET)
VersionHistory.Text = VersionHistory.Text + Environment.NewLine +
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void GetVSSFileHistory()
{
// <validVSSusr> & <validVSSpwd> are again valid strings
string UserName = "<validVSSusr>";
string Password = "<validVSSpwd>";

string SrcSafeIni = @"\\SERVER_ONE\VSS\SRCSAFE.INI";

// When attempting to use local srcsafe.ini file
// (which simply has an #include \\SERVER_ONE\VSS\SRCSAFE.INI in it),
// i get a [COMException (0x8004d849): Invalid handle.] error.
//string SrcSafeIni = @"C:\Program Files\Microsoft Visual
Studio\VSS\SRCSAFE.INI";

VSSDatabase objVssDatabase = new VSSDatabaseClass();
objVssDatabase.Open(SrcSafeIni, UserName, Password);

SourceSafeTypeLib.IVSSItem objProject =
objVssDatabase.get_VSSItem(@"$/Bookings/bookings",false);
SourceSafeTypeLib.IVSSItem objFile =
objVssDatabase.get_VSSItem(@"$/Bookings/bookings/text.asp",false);

foreach(SourceSafeTypeLib.IVSSVersion objVssVersion in
objFile.get_Versions(0))
{
VersionHistory.Text = VersionHistory.Text + "User: " +
objVssVersion.Username;
VersionHistory.Text = VersionHistory.Text + "Date: " +
objVssVersion.Date.ToString();
VersionHistory.Text = VersionHistory.Text + "Comment: " +
objVssVersion.Comment;
VersionHistory.Text = VersionHistory.Text + "-------------";
}
}

private bool impersonateValidUser(String userName, String domain, String
password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if(LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
return true;
else
return false;
}
else
return false;
}
else
return false;
}

private void undoImpersonation()
{
impersonationContext.Undo();
}

}
}
 
Ad

Advertisements

J

Joe Masters

MS is aware of the issue, but apparently the fix they suggest doesn't work,
according to this blog:

http://blogs.msdn.com/korbyp/archive/2003/06/24/54033.aspx

This page talks about using WNetAddConnection2A prior to connecting to VSS:
http://www.wimdows.net/newsgroups/v...6&mid=<[email protected]>

That one sounds the most promising. A good test would be if your asp.net
page could display the contents of the srcsafe.ini file. If the share isn't
active for the asp.net user, then the access would certainly be denied.

Joe

Dan Williams said:
Are you using a drive name or a network share name for the path to
srcsafe.ini?

Joe

A UNC network share path.

I have even managed to successfully impersonate myself as the user, and
have ensured that the share and NTFS permissions on the shared folder and
set to allow Everyone access (purely for tests reasons), but to no avail.

Anyone any ideas what the minumum permissions should be, so i can secure
the folder once i have it working?

Here is my complete C# source code (it'll probably wrap, so be wary of
simply cutting and pasting) :-

using System;
using System.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using SourceSafeTypeLib;


namespace BuildItTest
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label CurrentVerLabel;
protected System.Web.UI.WebControls.Label VersionNo;
protected System.Web.UI.WebControls.Label VerHistoryLabel;
protected System.Web.UI.WebControls.TextBox VersionHistory;

public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
public static extern int LogonUser(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("advapi32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)]
public extern static int DuplicateToken(IntPtr hToken, int
impersonationLevel, ref IntPtr hNewToken);

private void Page_Load(object sender, System.EventArgs e)
{
// Displays current user, usually ASPNET.
//If web.config is setup with impersonate=true, then current user is
IUSR_MACHINENAME.
VersionHistory.Text =
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

// Attempt to get VSS info without impersonating a different user.
// Causes Sourcesafe database path <user> does not exist error.
// COMException (0x8004d117)
// GetVSSFileHistory();

// <validusername>, <domain> & <usrpwd> are obviously valid strings in
my real code.
if(impersonateValidUser("<validusername>", "<domain>", "<usrpwd>"))
{
VersionHistory.Text = VersionHistory.Text + Environment.NewLine +
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

// Following function call results in same COMException (0x8004d117)
GetVSSFileHistory();
undoImpersonation();
}
else
{
VersionHistory.Text = VersionHistory.Text + Environment.NewLine +
"UNABLE TO IMPERSONATE USER!";
}

// Redisplays current user (again ASPNET)
VersionHistory.Text = VersionHistory.Text + Environment.NewLine +
System.Security.Principal.WindowsIdentity.GetCurrent().Name;

}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void GetVSSFileHistory()
{
// <validVSSusr> & <validVSSpwd> are again valid strings
string UserName = "<validVSSusr>";
string Password = "<validVSSpwd>";

string SrcSafeIni = @"\\SERVER_ONE\VSS\SRCSAFE.INI";

// When attempting to use local srcsafe.ini file
// (which simply has an #include \\SERVER_ONE\VSS\SRCSAFE.INI in it),
// i get a [COMException (0x8004d849): Invalid handle.] error.
//string SrcSafeIni = @"C:\Program Files\Microsoft Visual
Studio\VSS\SRCSAFE.INI";

VSSDatabase objVssDatabase = new VSSDatabaseClass();
objVssDatabase.Open(SrcSafeIni, UserName, Password);

SourceSafeTypeLib.IVSSItem objProject =
objVssDatabase.get_VSSItem(@"$/Bookings/bookings",false);
SourceSafeTypeLib.IVSSItem objFile =
objVssDatabase.get_VSSItem(@"$/Bookings/bookings/text.asp",false);

foreach(SourceSafeTypeLib.IVSSVersion objVssVersion in
objFile.get_Versions(0))
{
VersionHistory.Text = VersionHistory.Text + "User: " +
objVssVersion.Username;
VersionHistory.Text = VersionHistory.Text + "Date: " +
objVssVersion.Date.ToString();
VersionHistory.Text = VersionHistory.Text + "Comment: " +
objVssVersion.Comment;
VersionHistory.Text = VersionHistory.Text + "-------------";
}
}

private bool impersonateValidUser(String userName, String domain, String
password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

if(LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
return true;
else
return false;
}
else
return false;
}
else
return false;
}

private void undoImpersonation()
{
impersonationContext.Undo();
}

}
}


--

Thanks in advance

Dan Williams
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top