Objectmix
Tags Register Mark Forums Read

Issue With Programmatically Impersonating a User in a Web-Part : Sharepoint

This is a discussion on Issue With Programmatically Impersonating a User in a Web-Part within the Sharepoint forums in Microsoft Tools category; I'm trying to impliment a web-part that will allow select users (ones that are added to a custom sharepoint list) to Add, Edit and Delete user accounts on a Server. The client isn't using active directory yet, so I'm simply creating local machine accounts. I thought I had everything up and running, if I hit the web-part logged in with administrator privelages, the impersonation works, Prints out the correct name BEFORE impersonation, AFTER impersonation, and then AFTER UNDOING impersonation. It also creates, edits or deletes the user account appropriately. However, if I'm not logged in as a user that has ...


Object Mix > Microsoft Tools > Sharepoint > Issue With Programmatically Impersonating a User in a Web-Part

Sharepoint Microsoft sharepoint portal server development, administration and related discussions

Reply

 

LinkBack Thread Tools
  #1  
Old 11-08-2006, 08:38 AM
Junior Member
 
Join Date: Nov 2009
Posts: 0
Application Development is on a distinguished road
Default Issue With Programmatically Impersonating a User in a Web-Part

I'm trying to impliment a web-part that will allow select users (ones
that are added to a custom sharepoint list) to Add, Edit and Delete
user accounts on a Server. The client isn't using active directory yet,
so I'm simply creating local machine accounts. I thought I had
everything up and running, if I hit the web-part logged in with
administrator privelages, the impersonation works, Prints out the
correct name BEFORE impersonation, AFTER impersonation, and then AFTER
UNDOING impersonation. It also creates, edits or deletes the user
account appropriately.

However, if I'm not logged in as a user that has Administrator
privelages, the impersonation fails (kinda the whole point for
impersonation..). Any help would be MUCH appreciated.




namespace UserAdministration
{
using System;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.DirectoryServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

/// <summary>
/// Summary description for AddUser.
/// </summary>
///
public class AddUser : System.Web.UI.UserControl
{
#region Declarations
//Error Message Label
protected System.Web.UI.WebControls.Label lblErrorMessage;

//Text and Check Boxes
protected System.Web.UI.WebControls.TextBox txtUserName;
protected System.Web.UI.WebControls.TextBox txtFullName;
protected System.Web.UI.WebControls.TextBox txtDescription;
protected System.Web.UI.WebControls.TextBox txtPassword;
protected System.Web.UI.WebControls.TextBox txtConfirmPassword;
protected System.Web.UI.WebControls.CheckBox cbPasswordExpire;

//Buttons
protected System.Web.UI.WebControls.Button btnSave;

//Variables
private string currentUser;
const int ADS_UF_DONT_EXPIRE_PASSWD = 0x10000;

#endregion

#region Page Load
private void Page_Load(object sender, System.EventArgs e)
{

}
#endregion

#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.btnSave.Click += new System.EventHandler(this.btnSave_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

#region Classes

#region Save Button Class
private void btnSave_Click(object sender, System.EventArgs e)
{

if(authorizeUser() == true)
{
string strImpersonationUserName =
ConfigurationSettings.AppSettings["ImpersonationUser"].ToString();
string strImpersonationDomain =
ConfigurationSettings.AppSettings["ImpersonationDomain"].ToString();
string strImpersonationPassword =
ConfigurationSettings.AppSettings["ImpersonationPassword"].ToString();

Response.Write("UserName: " + strImpersonationUserName +
"<BR>Domain: " + strImpersonationDomain + "<BR>Password: " +
strImpersonationPassword);

if (ValidateFields())
{
ImpersonateUser(strImpersonationUserName, strImpersonationDomain,
strImpersonationPassword);
}
}
else
{
lblErrorMessage.ForeColor = System.Drawing.Color.Red;
lblErrorMessage.Text = "You do not have permission to manage user
accounts";
}
}
#endregion

#region Validate Fields Class
/// <summary>
/// Checks that all fields are valid and sets the error message or
returns true.
/// </summary>
/// <returns>Boolean value determining whether the form is valid or
not</returns>
private bool ValidateFields()
{
bool returnValue = true;
lblErrorMessage.Text = "";

if (
(txtUserName.Text.Trim() == "") ||
(txtFullName.Text.Trim() == "") ||
(txtDescription.Text.Trim() == "") ||
(txtPassword.Text.Trim() == "") ||
(txtConfirmPassword.Text.Trim() == "")
)
{
returnValue = false;
lblErrorMessage.ForeColor = System.Drawing.Color.Red;
lblErrorMessage.Text = "All fields are required.<p>";
}

if (txtPassword.Text.Trim() != txtConfirmPassword.Text.Trim())
{
returnValue = false;
lblErrorMessage.ForeColor = System.Drawing.Color.Red;
lblErrorMessage.Text += "Password fields do not match";
}

return returnValue;
}
#endregion

#region Add New User Class
/// <summary>
/// Adds a new user to the local machine
/// </summary>
private void AddNewUser()
{
Response.Write("Current User (In Add New User Class): " +
WindowsIdentity.GetCurrent().Name + "<BR>");
try
{
DirectoryEntry AD = new DirectoryEntry("WinNT://" +
Environment.MachineName + ",computer");
DirectoryEntry NewUser = AD.Children.Add(txtUserName.Text.Trim(),
"user");
NewUser.Invoke("SetPassword", new object[]
{txtPassword.Text.Trim()});
NewUser.Invoke("Put", new object[] {"Description",
txtDescription.Text.Trim()});
NewUser.Invoke("Put", new object[] {"FullName",
txtFullName.Text.Trim()});
NewUser.CommitChanges();


if (cbPasswordExpire.Checked)
{
int val = (int)NewUser.Properties["UserFlags"].Value;
NewUser.Invoke("Put", new object[] {"UserFlags", val |
ADS_UF_DONT_EXPIRE_PASSWD});
NewUser.CommitChanges();
}

lblErrorMessage.ForeColor = System.Drawing.Color.Blue;
lblErrorMessage.Text = "User " + txtUserName.Text.Trim() + " added
successfully!";

ResetForm();
}
catch (Exception ex)
{
lblErrorMessage.ForeColor = System.Drawing.Color.Red;
lblErrorMessage.Text += "<p>Error Adding User: " + ex.Message;
}
}
#endregion

#region Reset Form Class
/// <summary>
/// Resets the form.
/// </summary>
private void ResetForm()
{
txtUserName.Text = "";
txtFullName.Text = "";
txtDescription.Text = "";
txtPassword.Text = "";
txtConfirmPassword.Text = "";
cbPasswordExpire.Checked = false;
}
#endregion

#region Authorize User Class
/// <summary>
/// Checks whether the current user has authorization or not.
/// </summary>
/// <returns>Boolean value of whether or not the user has
authorization.</returns>
private bool authorizeUser()
{
currentUser = getCurrentUser();
try
{
SPSite currentSiteCollection = SPControl.GetContextSite(Context);
SPWeb currentWeb = currentSiteCollection.OpenWeb();

SPList userList = currentWeb.Lists["Wss Admin List"];
if (userList != null)
{
//An SPQuery object represents a query in a list view
SPQuery query = new SPQuery();
//the query must be in CAML format
query.Query = "<Where><Eq><FieldRef Name='LinkTitle'/><Value
Type='Text'>" + currentUser + "</Value></Eq></Where>";
SPListItemCollection hits = userList.GetItems(query);

if(hits.Count > 0)
return (true);
else
return (false);
}
else
{
return (false);
}
}
catch(Exception ex)
{
lblErrorMessage.Text = ex.Message;
return false;
}
}
#endregion

#region Get Current User Class
/// <summary>
/// Gets the currently logged in user
/// </summary>
/// <returns>String containing the currently logged in
user.</returns>
private string getCurrentUser()
{
string user =
System.Security.Principal.WindowsIdentity.GetCurrent().Name;
System.Text.RegularExpressions.Regex rx = new
System.Text.RegularExpressions.Regex(".+\\\\");
string trimmedUser = rx.Replace(user, "");
return trimmedUser;
}
#endregion

#region Impersonate User Class

[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LogonUser(String lpszUsername, String
lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

// [DllImport("kernel32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Auto)]
// private unsafe static extern int FormatMessage(int dwFlags, ref
IntPtr lpSource,
// int dwMessageId, int dwLanguageId, ref String lpBuffer, int
nSize, IntPtr *Arguments);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

public WindowsImpersonationContext ImpersonateUser(string
strUsername, string strDomain, string strPassword)
{

// initialize tokens
IntPtr pExistingTokenHandle = new IntPtr(0);
IntPtr pDuplicateTokenHandle = new IntPtr(0);
pExistingTokenHandle = IntPtr.Zero;
pDuplicateTokenHandle = IntPtr.Zero;

// if domain name was blank, assume local machine
if (strDomain == "")
strDomain = System.Environment.MachineName;

try
{
const int LOGON32_PROVIDER_DEFAULT = 0;

// create token
const int LOGON32_LOGON_INTERACTIVE = 2;
const int SecurityImpersonation = 2;

// get handle to token
bool boolImpersonated = LogonUser(strUsername, strDomain,
strPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref
pExistingTokenHandle);

if(boolImpersonated == false)
{
int intErrorMessage = Marshal.GetLastWin32Error();
Response.Write("LogonUser failed with error code: " +
intErrorMessage);
return null;
}

//Display User Before Impersonation - COMMENT OUT BEFORE DEPLOYING
Response.Write("Current User (Before Impersonation): " +
WindowsIdentity.GetCurrent().Name + "<BR>");

bool boolRetVal = DuplicateToken(pExistingTokenHandle,
SecurityImpersonation, ref pDuplicateTokenHandle);

// did DuplicateToken fail?
if (boolRetVal == false)
{
int intErrorCode = Marshal.GetLastWin32Error();
// close existing handle
CloseHandle(pExistingTokenHandle);
Response.Write("DuplicateToken() failed with error code: " +
intErrorCode);
return null;
}
else
{
// create new identity using new primary token
WindowsIdentity newId = new
WindowsIdentity(pDuplicateTokenHandle);
Response.Write("pfft.");
WindowsImpersonationContext impersonatedUser =
newId.Impersonate();

// Display User After Impersonation - COMMENT OUT BEFORE DEPLOYING
Response.Write("Current User (After Impersonation): " +
WindowsIdentity.GetCurrent().Name + "<BR>");

//Call AddNewUser method
AddNewUser();

impersonatedUser.Undo();

// Display User After Undoing Impersonation - COMMENT OUT BEFORE
DEPLOYING
Response.Write("Current User (After Undoing Impersonation): " +
WindowsIdentity.GetCurrent().Name + "<BR>");

return impersonatedUser;
}

}
catch (Exception ex)
{
lblErrorMessage.Text = "Real Exception" + ex.Message;
return null;
}
finally
{
// close handle(s)
if (pExistingTokenHandle != IntPtr.Zero)
CloseHandle(pExistingTokenHandle);
if (pDuplicateTokenHandle != IntPtr.Zero)
CloseHandle(pDuplicateTokenHandle);
}
}

#endregion

#endregion
}
}

  #2  
Old 11-08-2006, 08:40 AM
Junior Member
 
Join Date: Nov 2009
Posts: 0
Application Development is on a distinguished road
Default Re: Issue With Programmatically Impersonating a User in a Web-Part

And before someone asks, I'm using SmartPart and creating my web-parts
as usercontrols.

  #3  
Old 11-08-2006, 04:11 PM
Junior Member
 
Join Date: Nov 2009
Posts: 0
Application Development is on a distinguished road
Default RE: Issue With Programmatically Impersonating a User in a Web-Part

I'd start by making some changes to your impersonation code. Yours looks a
little more complicated than it has to be, plus you've got application logic
mixed in there with it. Try this code instead:

To start impersonating the Sharepoint domain service account:

WindowsIdentity objOriginalUser = WindowsIdentity.GetCurrent();
RevertToSelf();
WindowsIdentity.GetCurrent().Impersonate();

To stop:
objOriginalUser.Impersonate();


To start impersonating a specific account:

WindowsImpersonationContext wic =
CreateIdentity(ACCOUNTNAME,DOMAIN,PASSWORD).Impersonate();

To stop:

wic.Undo();



And you'll need this code to call that previous code:

using System.Security.Principal;
using System.Runtime.InteropServices;
//////////////////////////////////////


#region Impersonation code
protected static WindowsIdentity CreateIdentity(string User, string
Domain, string Password)
{
// The Windows NT user token.
IntPtr tokenHandle = new IntPtr(0);

const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_NETWORK = 3;

tokenHandle = IntPtr.Zero;

// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(User, Domain, Password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);

if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
throw new Exception("LogonUser failed with error code: " + ret);
}

System.Diagnostics.Debug.WriteLine("Created user token: " + tokenHandle);

//The WindowsIdentity class makes a new copy of the token.
//It also handles calling CloseHandle for the copy.
WindowsIdentity id = new WindowsIdentity(tokenHandle);
CloseHandle(tokenHandle);
return id;
}

[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(String lpszUsername, String
lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll")]
static extern bool RevertToSelf();

#endregion



"ptranfa@gmail.com" wrote:

> I'm trying to impliment a web-part that will allow select users (ones
> that are added to a custom sharepoint list) to Add, Edit and Delete
> user accounts on a Server. The client isn't using active directory yet,
> so I'm simply creating local machine accounts. I thought I had
> everything up and running, if I hit the web-part logged in with
> administrator privelages, the impersonation works, Prints out the
> correct name BEFORE impersonation, AFTER impersonation, and then AFTER
> UNDOING impersonation. It also creates, edits or deletes the user
> account appropriately.
>
> However, if I'm not logged in as a user that has Administrator
> privelages, the impersonation fails (kinda the whole point for
> impersonation..). Any help would be MUCH appreciated.
>
>

  #4  
Old 11-08-2006, 05:19 PM
Junior Member
 
Join Date: Nov 2009
Posts: 0
Application Development is on a distinguished road
Default RE: Issue With Programmatically Impersonating a User in a Web-Par

It just occured to me that you may also be having an issue with the security
context under which your smart part is running.

I'd recommend following Jan Tielen's advice in the article
http://weblogs.asp.net/jan/archive/2...23/414699.aspx regarding custom
code policy files, if you haven't already done so.

"Joe" wrote:

> I'd start by making some changes to your impersonation code. Yours looks a
> little more complicated than it has to be, plus you've got application logic
> mixed in there with it. Try this code instead:
>
> To start impersonating the Sharepoint domain service account:
>
> WindowsIdentity objOriginalUser = WindowsIdentity.GetCurrent();
> RevertToSelf();
> WindowsIdentity.GetCurrent().Impersonate();
>
> To stop:
> objOriginalUser.Impersonate();
>
>
> To start impersonating a specific account:
>
> WindowsImpersonationContext wic =
> CreateIdentity(ACCOUNTNAME,DOMAIN,PASSWORD).Impersonate();
>
> To stop:
>
> wic.Undo();
>
>
>
> And you'll need this code to call that previous code:
>
> using System.Security.Principal;
> using System.Runtime.InteropServices;
> //////////////////////////////////////
>
>
> #region Impersonation code
> protected static WindowsIdentity CreateIdentity(string User, string
> Domain, string Password)
> {
> // The Windows NT user token.
> IntPtr tokenHandle = new IntPtr(0);
>
> const int LOGON32_PROVIDER_DEFAULT = 0;
> const int LOGON32_LOGON_NETWORK = 3;
>
> tokenHandle = IntPtr.Zero;
>
> // Call LogonUser to obtain a handle to an access token.
> bool returnValue = LogonUser(User, Domain, Password,
> LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
> ref tokenHandle);
>
> if (false == returnValue)
> {
> int ret = Marshal.GetLastWin32Error();
> throw new Exception("LogonUser failed with error code: " + ret);
> }
>
> System.Diagnostics.Debug.WriteLine("Created user token: " + tokenHandle);
>
> //The WindowsIdentity class makes a new copy of the token.
> //It also handles calling CloseHandle for the copy.
> WindowsIdentity id = new WindowsIdentity(tokenHandle);
> CloseHandle(tokenHandle);
> return id;
> }
>
> [DllImport("advapi32.dll", SetLastError=true)]
> private static extern bool LogonUser(String lpszUsername, String
> lpszDomain, String lpszPassword,
> int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
>
> [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
> private extern static bool CloseHandle(IntPtr handle);
>
> [DllImport("advapi32.dll")]
> static extern bool RevertToSelf();
>
> #endregion
>
>
>
> "ptranfa@gmail.com" wrote:
>
> > I'm trying to impliment a web-part that will allow select users (ones
> > that are added to a custom sharepoint list) to Add, Edit and Delete
> > user accounts on a Server. The client isn't using active directory yet,
> > so I'm simply creating local machine accounts. I thought I had
> > everything up and running, if I hit the web-part logged in with
> > administrator privelages, the impersonation works, Prints out the
> > correct name BEFORE impersonation, AFTER impersonation, and then AFTER
> > UNDOING impersonation. It also creates, edits or deletes the user
> > account appropriately.
> >
> > However, if I'm not logged in as a user that has Administrator
> > privelages, the impersonation fails (kinda the whole point for
> > impersonation..). Any help would be MUCH appreciated.
> >
> >

  #5  
Old 11-09-2006, 08:45 AM
Junior Member
 
Join Date: Nov 2009
Posts: 0
Application Development is on a distinguished road
Default Re: Issue With Programmatically Impersonating a User in a Web-Par

Thank you. I've been instructed to stand the web-part up in its current
state (it works fine for people with administrative privelages on the
machine) as an interim solution.

I tried using the reverttoself method of impersonation late yesterday
and it wouldn't work either. The default identity that the site uses is
Network Service and it was tossing Access Denied errors as well.

I was wrong in stating that the impersonation worked if I was logged in
as an Administrator, the development virtual server I was given had the
default identity for IIS set to the Administrator account, so of course
it worked, I changed it, un-installed and re-installed a fresh copy of
WSS to fix some errors in the previous installation inconsistencies,
and realized I was wrong.

The problem is that this is for a DoD client and I can't make too many
changes on the server without huge political overhead and they need
this up and running COB today.

I just started this job on Monday

  #6  
Old 11-09-2006, 11:41 AM
Junior Member
 
Join Date: Nov 2009
Posts: 0
Application Development is on a distinguished road
Default Re: Issue With Programmatically Impersonating a User in a Web-Par

You should have your Sharepoint site running under its own application pool,
and that application pool should have its identity configured as a domain
account that has power user or administrator privileges on the server.
That's the cause of your impersonation problems -- the identity Sharepoint is
running under (network service) doesn't have rights to do what you want it to
do. As you've found, though, this is trumped by having an actual
administrator log in to the site.

I'm not sure what other issues you'll run into (if any) with your current
setup. I think problems will arise if you start adding other servers to your
Sharepoint environment.

Do you have any good Sharepoint books? The Resource Kit, by Bill English,
is pretty comprehensive, and a lot of it is available online.

http://www.microsoft.com/technet/win...t/default.mspx



"ptranfa@gmail.com" wrote:

> Thank you. I've been instructed to stand the web-part up in its current
> state (it works fine for people with administrative privelages on the
> machine) as an interim solution.
>
> I tried using the reverttoself method of impersonation late yesterday
> and it wouldn't work either. The default identity that the site uses is
> Network Service and it was tossing Access Denied errors as well.
>
> I was wrong in stating that the impersonation worked if I was logged in
> as an Administrator, the development virtual server I was given had the
> default identity for IIS set to the Administrator account, so of course
> it worked, I changed it, un-installed and re-installed a fresh copy of
> WSS to fix some errors in the previous installation inconsistencies,
> and realized I was wrong.
>
> The problem is that this is for a DoD client and I can't make too many
> changes on the server without huge political overhead and they need
> this up and running COB today.
>
> I just started this job on Monday
>
>

  #7  
Old 02-17-2010, 04:51 AM
Member
 
Join Date: Feb 2010
Posts: 49
elizas is on a distinguished road
Default Re: Issue With Programmatically Impersonating a User in a Web-Part

SharePoint provides options to create sites with different types of locales available out of the box. Suppose we have a SharePoint site built using the English locale and we want to change the existing site to some other locale then this can be achieved using the following piece of code. Changing the locale of the site helps display the date and number formats with their respective decimal and group separators.


Eliza
__________________
Cheers,
Eliza
Reply

Thread Tools


Similar Threads

Thread Thread Starter Forum Replies Last Post
Adding web part programmatically usenet Sharepoint 4 02-09-2010 08:34 AM
Impersonating user usenet DOTNET 4 09-12-2007 02:43 PM
Impersonating user usenet Inetserver 1 09-12-2007 12:41 PM
Programmatically Changing the URL of a Page Viewer web part usenet Sharepoint 1 01-24-2007 05:25 PM
Programmatically specify client cert as part of web service call usenet Java 2 01-11-2004 08:31 AM


All times are GMT -5. The time now is 08:41 AM.

Managed by Infnx Pvt Ltd.