Monday, September 15, 2008

Error in Publishing ASP.NET

If you get an error like "Access to the path 'C:\Documents and Settings\username\Local Settings\Temp\~6d4\bin\App_WebReferences.compiled' is denied." when you use the VS2005 | Build menu | Publish Web Site and your site impersonates a user this may help.

Open up Windows Explorer and navigate to the Temp directory specified in the path. In this example, go to "
C:\Documents and Settings\usb00528\Local Settings\Temp". Now right-click on the Temp directory and go to the security tab. Add the user that you are impersonating (usually specified in you web.config) and give the user Read and Write permissions. Now re-try the Publish Web Site menu item and it should publish successfully now. Yeah!

 

 

Regards,

 

Savitur Badhwar

(Computer Systems & Network Administrator)

Custom Control Sensors, Inc.

21111 Plummer Street | Chatsworth, CA 91311

Ph 818.341.4610 x2205 | Fax 818.709.0426

Chatsworth | Burbank | Mexico | http://www.ccsdualsnap.com

 

"Do all the good you can, by all the means you can, in all the ways you can, in all the places you can, to all the people you can, as long as ever you can" ~ John Wesley

 

CAUTION - The information contained in this communication is for the exclusive use of the addressee and may contain confidential privileged and non-disclosable information. If the recipient of this communication is not the addressee, or a person responsible for delivering the communication to the addressee, such recipient is prohibited from using this communication in any way. If you have received this communication by mistake, please notify us immediately. Any information related in the foregoing should be independently confirmed with the sender before reliance thereon including that represented to be from Custom Control Sensors, Inc.

 

 

 

Sunday, May 11, 2008

Anaylze Crash Mini Dump in Windows XP

About
So you got a XP blue screen of death (BSOD) and you'd like to have a crack at fixing it? Well hopefully this might help.

Turn On Minidumps

If you havn't already turned on minidumps, go to the Control Panel and follow this steps:
  1. System Icon
  2. Advanced Tab
  3. Startup and Recovery -> Settings
  4. Enable Write an Event to the system log
  5. Disable Automatically Restart
  6. Select the following debugging information:
    • Small memory dump (64 Kb)
    • Small Dump Directory : %SystemRoot%\Minidump
  7. Confirm all and restart the computer.

Crash It

Do whatever to make it crash. In my case it was leave the video encoding running overnight.

Install Tools

If you havn't got the windows debugging tools installed, then install the Microsoft Debugging Tools (Direct Link)

Analyse The MiniDump

To extract useful information out of the minidump file created:
  1. Open a command prompt (Start -> Run -> "cmd")
  2. cd \program files\debugging tools (Or wherever they are installed to)
  3. kd -z C:\WINDOWS\Minidump\Mini???????-??.dmp
  4. kd> .logopen c:\debuglog.txt
  5. kd> .sympath srv*c:\symbols*http://msdl.microsoft.com/download/symbols
  6. kd> .reload;!analyze -v;r;kv;lmnt;.logclose;q
  7. You now have a debuglog.txt in c:\, open it in a text edit (Notepad?).

Post Mortem

Look for the MODULE_NAME and IMAGE_NAME headings. This is the program that caused the error. Sometimes when it's a device driver it means that that device is causing the BSOD and by disabling it or updating the driver your system will run stable. If you don't know what device that name relates to then Google it.

I provide this information for free without any support.

Hope it helps.


 



Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now.

Monday, March 24, 2008

ASP.NET 2.0 Gridview/Dataview Update does not work

Problems with my GridView/Dataview update, it doesn't update the record in the database, it doesn't generate an error either, it just reloads the page with the previous values.


Check 1:

If you select the GridView in the designer, and select that entry in the Properties box, you can select the correct values.The result should change your source line to look something like the following (in bold):

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="id" DataSourceID="SqlDataSource1">


Check 2:

If you have NULL fields in your data and checked the "Use Optimistic Concurrency" option when configuring your SqlDatasource, then the update won't work. Re-configure the SqlDataSource (use the wizard again) and uncheck the "Use Optimistic Concurrency" option. It should work fine afterwards.

Friday, February 29, 2008

Authenticating a Windows User in .NET

Authenticating a Windows User in .NET

When it comes to authenticating a windows user from within a .NET application, a developer has 3 options

  1. Querying Active Directory via LDAP (Lightweight Directory Access Protocol)
  2. Microsoft.Samples.Security.SSPI
  3. LogOnUser API (advapi32.dll)

Personally I prefer the third option. Let me explain why.

Querying the Active Directory is the most common way of performing authentication or at least it seems that way since when you google the subject most of the results point to this solution. An active directory is a directory structure used on Microsoft Windows based computers and servers to store information and data about networks and domains. It is primarily used for online information and was originally created in 1996 and first used with Windows 2000. An active directory (sometimes referred to as an AD) does a variety of functions including the ability to provide information on objects, helps organize these objects for easy retrieval and access, allows access by end users and administrators and allows the administrator to set security up for the directory. So its obvious that AD's sole purpose is not authentication. Hence the frustrated comments you WILL find on various blogs and other web pages on performing authentication using AD. In addition, the active directory feature should be installed on a server to make this work. If its not installed querying the AD amounts to no result.

I must admit that my knowledge on the second solution is much limited. But when going through some solutions in the web I saw that it required some fiddling with windows sockets involving some classes like Socket, TcpListener, etc. I could only imagine what sort of problems you may come across when you try that out in a firewalled environment.

So to be on the safe side I chose to go with the LogOnUser API. IMHO there is not enough documentation to be found in the internet on how to use the Windows LogOnUser API exposed by advapi.dll so I had to depend on trial and error and managed to create a managed wrapper consisting of a set of classes which I mention below. It is possible to perform the following functions with this wrapper.

  • Authenticating a local or domain windows user
  • See whether a windows user is in a specified windows user group
  • List all windows user groups that a certain windows user belongs to.
  • Impersonation may also be possible with some additional lines of coding.

Here's how I got it working,

The first class called 'WindowsAPIDeclarations' contains all the Windows API declarations.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace libWinSecuritySubSystem
{
internal sealed class WindowsAPIDeclarations
{
internal static Int16 LOGON32_LOGON_NETWORK = 3;
internal static Int16 LOGON32_LOGON_INTERACTIVE = 2;
internal static Int16 LOGON32_PROVIDER_DEFAULT = 0;

internal WindowsAPIDeclarations() { }

[DllImport("advapi32.dll")]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
internal static extern bool CloseHandle(IntPtr handle);
}
}

The second class "AuthenticationService" contains the main AuthenticateUser() method. Remember to replace the string "<YOUR DOMAIN NAME HERE>" with your windows domain name in which you want to do the authentication.

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Collections;

namespace libWinSecuritySubSystem
{
public sealed class AuthenticationService
{
public static AuthenticationResult AuthenticateUser(string userName, string password)
{
IntPtr token = IntPtr.Zero;

try
{
string domainName = "<YOUR DOMAIN NAME HERE>";

if (!WindowsAPIDeclarations.LogonUser(userName, domainName, password, WindowsAPIDeclarations.LOGON32_LOGON_INTERACTIVE, WindowsAPIDeclarations.LOGON32_PROVIDER_DEFAULT, ref token))
{
int errID = Marshal.GetLastWin32Error();
throw new Win32Exception(5);
}

WindowsPrincipal principal = new WindowsPrincipal(new WindowsIdentity(token));
WindowsAPIDeclarations.CloseHandle(token);

return new AuthenticationResult(true, null, new AuthenticatedUser(principal));
}
catch (Exception ex)
{
try
{
WindowsAPIDeclarations.CloseHandle(token);
}
catch (Exception) { }
return new AuthenticationResult(false, ex, null);
}
}
}
}

The third class named "AuthenticationResult" contains information regarding the ultimate result of the AuthenticateUser() method.

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.ComponentModel;

namespace libWinSecuritySubSystem
{
public class AuthenticationResult
{
bool isAuthenticated;
Exception authenticationException;
AuthenticatedUser user;

internal AuthenticationResult(bool isAuthenticated, Exception authenticationException, AuthenticatedUser user)
{
this.isAuthenticated = isAuthenticated;
this.authenticationException = authenticationException;
this.user = user;
}

public AuthenticatedUser User
{
get { return user; }
}

public bool IsAuthenticated
{
get { return isAuthenticated; }
}

public Exception AuthenticationException
{
get { return authenticationException; }
}
}
}

Last but not least the "AuthenticatedUser" class which contains the functions to get info on the authenticated user.

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Collections;

namespace libWinSecuritySubSystem
{
public class AuthenticatedUser
{
WindowsPrincipal principal;

internal AuthenticatedUser(WindowsPrincipal principal)
{
this.principal = principal;
}
public WindowsPrincipal Principal
{
get { return principal; }
}
public bool IsUserInGroup(string groupName)
{
try
{
return principal.IsInRole(groupName);
}
catch (Exception)
{
return false;
}
}

public bool IsUserInGroup(WindowsBuiltInRole builtInGroup)
{
try
{
return principal.IsInRole(builtInGroup);
}
catch (Exception)
{
return false;
}
}

public Dictionary<string, string> GetGroups()
{
Dictionary<string, string> groups = new Dictionary<string,string>();
IdentityReferenceCollection irc = ((WindowsIdentity)(principal.Identity)).Groups;
foreach (IdentityReference ir in irc)
groups.Add(ir.Value, ir.Translate(typeof(NTAccount)).Value);

return groups;
}

}
}

Additional functions like impersonation may also be introduced as necessary.