PDA

View Full Version : permissions issue on object model


realtytrac
05-18-2006, 12:03 PM
Hello,

I'm using the object model to run scripts on top of an ASP.NET 2.0 web application. The web app uses windows integrated security, and impersonation for security purposes because my script will need to copy files to multiple servers.

I have gotten so many permissions errors its unbelievable. I was able to get around some of them simply by giving EVERYONE permission on the folders i am testing with (a solution that will not hold when i move to production).

One of these errors is when i try to do a simple copy of files from my box to another server. Under the impersonation account that my web app runs under, the copy should be no problem at all. I have full access to the folders i am trying to access. in fact, when i access them through convential ASP.NET code, there is absolutely no problem at all.

However, when i run the build script through the API, all these permission problems come about, the one above being "Error creating destination path '\\webdev\DEVLaunchFolder\Websites\RealtyTrac\Test App\': Logon failure: unknown user name or bad password." I did an audit on the destination path and found that its my ASPNET username from my machine that is trying to access that folder, and naturally that is not permitted. This is happening even though i am using impersonation, which is odd. Then i researched a bit and found out that some COM components can not be passed the impersonation tokens if their apartment state is single threaded. So i figured maybe that is what is happing with the visual build pro COM object. Soooo, i went further and created a separate thread that is STA. in that thread, i do impersonation (again!) using LogonUser, and execute the code. SAME ERROR COMES UP. I am lost, and i need help with this. It just doesn't sound correct that Visual Build Pro's API can not execute copies to other servers, something so elemental to the application.

PLEASE HELP

The following is the message i get back when i execute the build script:

5/18/2006 9:51:19 AM: Building Project Step 'Project Steps'...
Step 'Project Steps' completed, status = Succeeded
5/18/2006 9:51:19 AM: Building Project Step 'Move to DEV Rollback Folder'...
Step 'Move to DEV Rollback Folder' completed, status = Succeeded
5/18/2006 9:51:19 AM: Building Project Step 'Copy ASPX and root'...
C:\Working\Testing\RealtyTracBuilds\DEV\4_12_2006-04\Push\TestApp\ -> C:\Working\Testing\RealtyTracBuilds\DEV\3_31_2006-03\Rollback\TestApp\
Copying: Global.asax
Copying: Web.config
Copying: WebForm1.aspx
Copying: WebForm2.aspx
Copying: WebForm3.aspx
Copying: bin\TestApp.dll
6 file(s) copied, 0 file(s) deleted
Step 'Copy ASPX and root' completed, status = Succeeded
5/18/2006 9:51:19 AM: Building Project Step 'Clean the TestApp build folder'...
-> C:\Inetpub\wwwroot\TestApp\
0 file(s) copied, 17 file(s) deleted
Step 'Clean the TestApp build folder' completed, status = Succeeded
5/18/2006 9:51:19 AM: Building Project Step 'Labeled Application'...
Step 'Labeled Application' completed, status = Succeeded
5/18/2006 9:51:19 AM: Building Project Step 'Get Label TestApp'...
"C:\Program Files\SourceGear\Vault Client\vault.exe" -host SERVER_NAME -user USER -password xxx -repository REP_NAME getlabel $/TestApp 3/31/2006-03 -setfiletime current -destpath C:\Inetpub\wwwroot\TestApp

Step 'Get Label TestApp' completed, status = Succeeded
5/18/2006 9:51:22 AM: Building Project Step 'Latest Application'...
Step 'Latest Application' build rule evaluates false: %FIRST_BUILD% (expanded value = false) is equal to true
Step 'Latest Application' completed, status = Skipped
5/18/2006 9:51:22 AM: Building Project Step 'Delete Label TestApp'...
Step 'Latest Application' build rule evaluates false: %FIRST_BUILD% (expanded value = false) is equal to true
Step 'Delete Label TestApp' completed, status = Skipped
5/18/2006 9:51:22 AM: Building Project Step 'Get Latest TestApp'...
Step 'Latest Application' build rule evaluates false: %FIRST_BUILD% (expanded value = false) is equal to true
Step 'Get Latest TestApp' completed, status = Skipped
5/18/2006 9:51:22 AM: Building Project Step 'Label TestApp'...
Step 'Latest Application' build rule evaluates false: %FIRST_BUILD% (expanded value = false) is equal to true
Step 'Label TestApp' completed, status = Skipped
5/18/2006 9:51:22 AM: Building Project Step 'Build Solution'...
Pre-processing...
Building configuration 'Release'...
Microsoft (R) Development Environment Version 7.10.3077. Copyright (C) Microsoft Corp 1984-2001. All rights reserved. ------ Build started: Project: TestApp, Configuration: Release .NET ------ Preparing resources...
Updating references... Performing main compilation...
Build complete -- 0 errors, 0 warnings Building satellite assemblies... ---------------------- Done ----------------------
Build: 1 succeeded, 0 failed, 0 skipped
Step 'Build Solution' completed, status = Succeeded
5/18/2006 9:51:29 AM: Building Project Step 'Move to DEV Push Folder'...
Step 'Move to DEV Push Folder' completed, status = Succeeded
5/18/2006 9:51:29 AM: Building Project Step 'Copy ASPX and root'...
C:\Inetpub\wwwroot\TestApp\ -> C:\Working\Testing\RealtyTracBuilds\DEV\3_31_2006-03\Push\TestApp\
Copying: Global.asax
Copying: Web.config
Copying: WebForm1.aspx
Copying: WebForm2.aspx
Copying: WebForm3.aspx
Copying: bin\TestApp.dll
6 file(s) copied, 0 file(s) deleted
Step 'Copy ASPX and root' completed, status = Succeeded
5/18/2006 9:51:29 AM: Building Project Step 'Update DEV files'...
Step 'Update DEV files' completed, status = Succeeded
5/18/2006 9:51:29 AM: Building Project Step 'Change web.config'...
1 match(es) found, 1 replacement(s) made in file
Step 'Change web.config' completed, status = Succeeded
5/18/2006 9:51:29 AM: Building Project Step 'Move To DEV Server'...
Step 'Move To DEV Server' completed, status = Succeeded
5/18/2006 9:51:29 AM: Building Project Step 'Copy ASPX and root'...
Error creating destination path '\\webdev\DEVLaunchFolder\Websites\RealtyTrac\Test App\': Logon failure: unknown user name or bad password.
Step 'Copy ASPX and root' completed, status = Failed

kinook
05-19-2006, 01:43 PM
The VBP Builder component creates its own thread for all build activity. It turns out that when a new thread is created, it gets the security context of the process, not the creating thread. So currently, the account that the process your page runs in will need to have the necessary permissions to network resources. We'll investigate to see if there is a clean way to get around the default behavior of Windows WRT a thread's security context.

realtytrac
05-30-2006, 11:41 AM
Thank you for a copy of the 6.2 Beta version geared to fix this problem.

I tried to use it and it does not seem to have fixed the problem. Using ASPCompat still gives the same error as before, namely "Unknown Error".

Without the ASPCompat it was even worse. An alert came up titled "vault.exe - Common Language Runtime Debugging Service"

It said: "Process id=0x8b8 (2232), Thread id = 0xfcc (4044)

Click Ok to terminate...
Click cancel to debug..."

The message i got back from build itself was the following:

5/30/2006 9:35:38 AM: Building Project Step 'Project Steps'...
Step 'Project Steps' completed, status = Succeeded
5/30/2006 9:35:38 AM: Building Project Step 'Move to DEV Rollback Folder'...
Step 'Move to DEV Rollback Folder' completed, status = Succeeded
5/30/2006 9:35:38 AM: Building Project Step 'Copy ASPX and root'...
FOLDER1 -> FOLDER2
Copying: Global.asax
Copying: Web.config
Copying: WebForm1.aspx
Copying: WebForm2.aspx
Copying: WebForm3.aspx
Copying: bin\TestApp.dll
6 file(s) copied, 0 file(s) deleted
Step 'Copy ASPX and root' completed, status = Succeeded
5/30/2006 9:35:38 AM: Building Project Step 'Clean the TestApp build folder'...
-> C:\Inetpub\wwwroot\TestApp\
0 file(s) copied, 0 file(s) deleted
Step 'Clean the TestApp build folder' completed, status = Succeeded
5/30/2006 9:35:38 AM: Building Project Step 'Labeled Application'...
Step 'Labeled Application' completed, status = Succeeded
5/30/2006 9:35:38 AM: Building Project Step 'Get Label TestApp'...
"C:\Program Files\SourceGear\Vault Client\vault.exe" -host xxx -user xxx -password xxx -repository xxx getlabel $/TestApp 3/31/2006-03 -setfiletime current -destpath C:\Inetpub\wwwroot\TestApp
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at VaultClientNetLib.VaultConnection.Logout() at VaultClientOperationsLib.ClientInstance.Logout() at VaultCmdLineClient.VaultCmdLineClient.Logout(Boole an bForceLogout) at VaultCmdLineClient.VaultCmdLineClient.Main(String[] args)
Process completed with exit code -1073741819
Step 'Get Label TestApp' completed, status = Failed


Please help

kinook
05-30-2006, 12:58 PM
First, additional research indicates that the ASPCompat option should NOT be used, as it is not compatible with free threaded components (such as the VBP Builder component).

At issue now is vault.exe, not Visual Build Professional. It apparently can not run in an impersonated thread environment. You can verify this by attempting to invoke the vault.exe application directly from your asp page.

If you can get vault.exe to execute from your asp web app, then if you invoke Visual Build Professional in the same manner, the entire build (including the execution of vault.exe) will likely work.

realtytrac
05-30-2006, 01:02 PM
Vault was able to work before i upgraded to the Beta version you just gave me. I was able to get latest, label, delete labels; all from asp.net. My only problem was when i was trying to move files from one server to another, which had nothing to do with Vault. All of the above was done in an impersonated environment. In fact, Vault's API is used elsewhere in our app independent of Visual Build pro, and we are able to log in and out of Vault using impersonation without a problem.

kinook
06-02-2006, 07:30 AM
The change that was made ensures that the build thread runs under the same identity as the thread that created it, which is fairly straightforward (see [1] for more details).

However, the thread's impersonated identity does not extend to processes that a thread creates via CreateProcess (which applies to many actions, including Vault), and the Vault client doesn't handle the default context it does get created in very well (and it probably would not have the necessary permissions to perform its task anyway). It turns out that it is not trivial to implement this transparently, and may not even be possible without giving the user account more rights than you probably want to (see [2], [3]).

Also, since the technique you are using waits for the build to complete, the client browser could easily timeout waiting for a response from the server.

An alternative technique would be to instead invoke the VBP console app [4] to build (using CreateProcessWithLogonW with the credentials of the impersonated identity [5]). When a process is started this way, an impersonated identity will flow properly to processes that it in turn creates. This method could be performed synchronously as well (for instance, waiting for the process to complete while populating the response page with stdout) or asynchronously, returning as soon as the process was started.

[1] http://groups.google.com/group/microsoft.public.platformsdk.win_base_svcs/browse_thread/thread/60175a8d042ea332/fba8e19cdbd8e3d1?lnk=st&q=createthread+security+context+process&rnum=3&hl=en
[2] http://groups.google.com/group/microsoft.public.platformsdk.security/browse_thread/thread/7c1dd3bf72ff98b0/799c440af87bc027?lnk=st&q=createprocessasuser+%22a+required+privilege+is+n ot+held+by+the+client%22&rnum=24#799c440af87bc027
[3] http://groups.google.com/group/microsoft.public.security.crypto/browse_thread/thread/f8072c952e930bad/dbb76b88c6b54203?lnk=st&q=createprocessasuser+%22a+required+privilege+is+n ot+held+by+the+client%22&rnum=2#dbb76b88c6b54203
[4] http://www.visualbuild.com/Manual/consoleapp.htm

[5]

[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
internal IntPtr hProcess;
internal IntPtr hThread;
internal int dwProcessId;
internal int dwThreadId;
}

[StructLayout(LayoutKind.Sequential)]
internal struct STARTUPINFO
{
internal int cb;
[MarshalAs(UnmanagedType.LPTStr)]
internal string lpReserved;
[MarshalAs(UnmanagedType.LPTStr)]
internal string lpDesktop;
[MarshalAs(UnmanagedType.LPTStr)]
internal string lpTitle;
internal int dwX;
internal int dwY;
internal int dwXSize;
internal int dwYSize;
internal int dwXCountChars;
internal int dwYCountChars;
internal int dwFillAttribute;
internal int dwFlags;
internal short wShowWindow;
internal short cbReserved2;
internal IntPtr lpReserved2;
internal IntPtr hStdInput;
internal IntPtr hStdOutput;
internal IntPtr hStdError;
}

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool CreateProcessWithLogonW(String lpszUsername,
String lpszDomain, String lpszPassword, int dwLogonFlags, string applicationName,
StringBuilder commandLine, int creationFlags, IntPtr environment, string currentDirectory,
ref STARTUPINFO sui, out PROCESS_INFORMATION processInfo);

//dwLogonFlags Specifies the logon option
const int LOGON_WITH_PROFILE = 1;
const int LOGON_NETCREDENTIALS_ONLY = 2;

//dwCreationFlags - Specifies how the process is created
const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;

//dwCreationFlags parameter controls the new process's priority class
const int NORMAL_PRIORITY_CLASS = 0x00000020;
const int IDLE_PRIORITY_CLASS = 0x00000040;
const int HIGH_PRIORITY_CLASS = 0x00000080;
const int REALTIME_PRIORITY_CLASS = 0x00000100;
const int BELOW_NORMAL_PRIORITY_CLASS = 0x00004000;
const int ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000;


// retrieve the path+filename of the console app
string app = Registry.LocalMachine.OpenSubKey(
@"Software\Microsoft\Windows\CurrentVersion\App Paths\VisBuildCmd.exe").GetValue(null).ToString();

StringBuilder parms = new StringBuilder();

// pass all macro values to VBP on command-line based on user inputs
// foreach (DictionaryEntry keypair in macros)
// parms.AppendFormat(" \"{0}={1}\"", keypair.Key, keypair.Value);

// pass the filename to build
parms.AppendFormat(" /b \"{0}\"", projectFile);

// retrieve the impersonated identity credentials
XmlDocument cfg = new XmlDocument();
cfg.Load(Path.Combine(Server.MapPath("."), "web.config"));
XmlNode ident = cfg.SelectSingleNode("configuration/system.web/identity");

PROCESS_INFORMATION processInfo;
STARTUPINFO startInfo = new STARTUPINFO();
startInfo.cb = Marshal.SizeOf(startInfo);
startInfo.lpDesktop = "winsta0\\default";

// create the process under the credentials of our impersonated identity so that it has
// the necessary rights for performing a build
if (CreateProcessWithLogonW(ident.Attributes["userName"].Value, ".", ident.Attributes["password"].Value,
LOGON_NETCREDENTIALS_ONLY /*LOGON_WITH_PROFILE*/, app, parms,
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, IntPtr.Zero, "", ref startInfo, out processInfo))
{
Response.Write("Started with Process ID " + processInfo.dwProcessId.ToString());
}
else
{
Response.Write(Marshal.GetLastWin32Error());
}

realtytrac
06-05-2006, 03:36 PM
Ok, i have not tried that method because i rely so much upon the API to pass MACRO data to and from the build script.

Could i do that using the VBP?

What about the log of the build?

Is there any other way to do this with the API?

kinook
06-05-2006, 04:54 PM
Yes, you can pass macro values on the command-line (see the link above or the commented out code in the sample), and you can also specify the logfile to write to via the command-line. As far as reading the log file (I'm not sure what your question is regarding the log file), you would have to poll that manually or read the stdout of the console app.

I'm still not convinced that using the object model is the best approach for this (mainly due to potential timeouts waiting for the build to complete), but we could add some properties to the VBP object model to specify a username/domain/password for all processes that it creates to run under, and have it internally call CreateProcessWithLogonW in that case, allowing your ASP.NET code to read the credentials from web.config and set them on the VBP application object before starting the build.

realtytrac
06-05-2006, 04:56 PM
Thanks for answering my question about the macros.

Regarding your comment " we could add some properties to the VBP object model to specify a username/domain/password for all processes that it creates to run under, and have it internally call CreateProcessWithLogonW in that case, allowing your ASP.NET code to read the credentials from web.config and set them on the VBP application object before starting the build.",

how soon would you be able to do that?

realtytrac
06-08-2006, 07:11 PM
Dear Kinook,

I received another BETA to solve the above issue. Your developers created a new function SyncBuildEx that takes user credentials. I used it and on my XP machine, everything worked smoothely. Thank you so much.

However, i just deployed the web application onto a Windows Server 2003 machine, and i am getting the following error upon reach SyncBuildEx:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at VisBuildSvr.Interop.BuilderClass.SyncBuildEx(Boole an flowThreadIdentity, String processIdentityUserName, String processIdentityDomain, String processIdentityPassword, Boolean logonNetCredentialsOnly, Boolean useInteractiveWinstaDesktop) at RealtyTrac.VaultVDD.ProjectBuild.BuildExecution() in C:\Documents and Settings\haider.sabri\My Documents\Visual Studio 2005\Projects\VDDManagerV2\VaultVDDV2\Build.cs:lin e 656


The oddest thing about this is that the exception stack shows a path that is not on the machine i deployed this app to. That path corresponds to my development machine, but this error is happening on a totally different server.

Please advise

realtytrac
06-08-2006, 07:44 PM
Look at this link. I think it may help:

http://msdn2.microsoft.com/en-us/library/ms164911.aspx



An access violation occurs in unmanaged or unsafe code when it attempts to read or write to memory that has not been allocated, or to which it does not have access. Not all reads or writes through bad pointers lead to access violations, so an access violation usually indicates that several reads or writes have occurred through bad pointers, and that memory might be corrupted.

In managed code, all references are either valid or null. Any operation that attempts to reference a null reference in verifiable code throws NullReferenceException.

An access violation that occurs in unsafe managed code can be expressed as either a NullReferenceException or a AccessViolationException, depending on the platform.

kinook
06-08-2006, 08:54 PM
It sounds like you may not have installed the latest VBP beta onto the W2003 box or perhaps a reboot is in order.

realtytrac
06-09-2006, 11:15 AM
I think you may be right, but i have not checked yet because I am a little aprehensive to install beta software on this server. I will get another server to test with until Kinook decides to make it part of a release. By the way, do you know if that is something you may do sometime soon?

thank you

realtytrac
06-12-2006, 10:22 AM
Thank you.

That fixed my problem