Re: Changing domain user password
- From: "Joe Kaplan \(MVP - ADSI\)" <joseph.e.kaplan@xxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Thu, 22 Dec 2005 12:55:06 -0600
In AD users and computers, find the machine account and open its properties.
There should be Delegation tab where you can enable it. If your AD is 2003,
then you have options on which services the account can delegate to
(constrained delegation), but otherwise you just turn it on.
The only other thing to watch out for is that if you are using a DNS alias
to access the website which is different from the server's default DNS
registration, you will also need to set a service principal name for the
machine account as well that matches the additional DNS name. This is
required to ensure that your users are actually authenticating with the web
server with Kerberos (not NTLM, which does not support delegation).
If you put this off until your 2003 server upgrade, it might go more
smoothly. You could then simply use Ryan's impersonation class if you want.
All in all there are more options.
Best of luck,
Joe K.
"Harry Devine" <hdevine@xxxxxxxxxxxxxxxx> wrote in message
news:%23eZu9VyBGHA.216@xxxxxxxxxxxxxxxxxxxxxxx
> We plan on upgrading our servers to Win2K3 early next year, so maybe I'll
> put this off until then and get it working. I did upgrade the Framework
> to 2.0 in the mean time. How would I go about adding the machine account
> for Kerberos Delegation?
>
> Thanks,
> Harry
>
> "Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@xxxxxxxxxxxxxxxxxxxxxxxx> wrote
> in message news:elN7cEyBGHA.4076@xxxxxxxxxxxxxxxxxxxxxxx
>> Ok. In this case, you really want to be using the ChangePassword method,
>> not SetPassword. SetPassword is for administrative resets.
>> ChangePassword is generally only performed by a user on their own account
>> and requires the current and new password.
>>
>> ChangePassword can be a little tricky to get working on Win2K, especially
>> if your domain controller does not have an SSL certificate installed.
>> They don't by default, so someone would have needed to do this.
>>
>> You will have trouble using Ryan's Impersonation class on Win2K server
>> though as an account must have the "act as part of the operating system"
>> privilege to call the LogonUser function he is using, and only SYSTEM has
>> that by default. You really should not be running your processModel as
>> SYSTEM. It is a very bad security practice! The problem you may be
>> having right now might relate to this.
>>
>> As such, you probably want to consider doing regular impersonation
>> combined with Kerberos delegation. Kerberos delegation is an AD feature
>> that allows you to specify specific accounts that may log on to another
>> service on the network using the credentials the user originally supplied
>> to them. In this case, the web server would be logging in to AD on
>> behalf of the user who authenticated with the web site.
>>
>> You would configure the app to use integrated auth in IIS (no anonymous),
>> configure ASP.NET for Windows auth and <identity impersonate="true"/> and
>> configure the machine account for the web server for Kerberos Delegation
>> in AD.
>>
>> The code for doing the change would be similar, except that you would not
>> do programmatic impersonation and would invoke "ChangePassword", passing
>> in both the old and the new password.
>>
>> You also want to be using SSL to protect this website since you are
>> dealing in plain text credentials. You don't want this traffic getting
>> sniffed on the wire!
>>
>> Regarding the .NET Framework version, I definitely think you should be
>> using the 1.1 Framework minimum and possibly the 2.0 one. It is released
>> now and there is no good reason not to use it here. It has some nice bug
>> fixes and new features for System.DirectoryServices. The new features
>> you don't need, but the fixes are nice.
>>
>> Your options get considerably better if you can upgrade your web server
>> to 2003 SP1. Some of the limitations and difficulties go away and 2003
>> is overall a much better web server platform in general.
>>
>> HTH,
>>
>> Joe K.
>>
>> "Harry Devine" <hdevine@xxxxxxxxxxxxxxxx> wrote in message
>> news:e30ZkVxBGHA.516@xxxxxxxxxxxxxxxxxxxxxxx
>>>I wanted to allow a user to change their password to something else, so
>>>maybe I've been confusing myself here. Our server is Win2K, and I was
>>>changing the processModel section due to some info I found on the 'Net.
>>>I can put it back to it's original form. Would you recommend upgrading
>>>to the .NET framework 2.0 as well?
>>>
>>> Basically, I'm looking for an example of allowing a user to hit the
>>> site, enter their current password, and then enter a new one, using
>>> ASP.NET and System.Directory services.
>>>
>>> Sorry for the confusion, and thanks again for any help.
>>> Harry
>>>
>>> "Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@xxxxxxxxxxxxxxxxxxxxxxxx>
>>> wrote in message news:%23znXXqwBGHA.1144@xxxxxxxxxxxxxxxxxxxxxxx
>>>>I thought you were doing password changes, not resets. There are
>>>>actually important differences on how that is approached.
>>>>
>>>> It sounds like this is running on Win2K or XP, right? That's why you
>>>> are editing the processModel section.
>>>>
>>>> It also looks like you are using the 1.0 version of the .NET Framework.
>>>> Any reason for that? 1.1 or 2.0 would be preferred. The 1.0.3300.0
>>>> version for System.DirectoryServices points to the 1.0 framework.
>>>>
>>>> If you have changed the process model account, there is no reason to
>>>> also impersonate the same account in code. The process account will be
>>>> running as the admin user. However, this is generally not considered a
>>>> good practice, especially if other apps may be running on the same
>>>> server as they will all run under this administrative account and have
>>>> more privileges than they should.
>>>>
>>>> Can you also show the exact line where this is crashing? If they page
>>>> displays, it seems like there should be some indication of what the
>>>> problem was on the postback.
>>>>
>>>> Joe K.
>>>>
>>>> "Harry Devine" <hdevine@xxxxxxxxxxxxxxxx> wrote in message
>>>> news:eZ8u$cvBGHA.3604@xxxxxxxxxxxxxxxxxxxxxxx
>>>>> I'm reasonably sure ASP.NET is working (the .aspx page that I'm
>>>>> putting below comes up), but this is my first try at programming
>>>>> anything in it, so take that for what it's worth. I'm including the
>>>>> code for the reset.aspx file and web.config. The only change that I
>>>>> made to machine.config was to change the username and password under
>>>>> the processModel section to be my domain admin account (I found that
>>>>> suggestion somewhere on the Web while researching the error).
>>>>>
>>>>> Thanks for any help,
>>>>> Harry
>>>>>
>>>>> reset.aspx:
>>>>> <%@ Assembly Name="System.DirectoryServices, Version=1.0.3300.0,
>>>>> Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"%>
>>>>> <%@ Assembly Name="Dunnry.Security" %>
>>>>>
>>>>> <%@ Import Namespace="System.DirectoryServices" %>
>>>>> <%@ Import Namespace="Dunnry.Security" %>
>>>>>
>>>>> <HTML>
>>>>> <script language="C#" runat="server">
>>>>>
>>>>> void Page_Load(Object Src, EventArgs E ) {
>>>>> if(!Page.IsPostBack)
>>>>> {
>>>>>
>>>>> }
>>>>> }
>>>>>
>>>>> private void ResetPassword(object sender, EventArgs e)
>>>>> {
>>>>> //for impersonation
>>>>> string username = "AdminUser";
>>>>> string password = "adminpwd";
>>>>> string domain = "domain";
>>>>>
>>>>> Impersonate i = new
>>>>> Impersonate(LogonProvider.LOGON32_PROVIDER_WINNT50);
>>>>> i.ImpersonateUser(username, domain, password);
>>>>>
>>>>> string ldapPath = LDAP://dc=mydomain,dc=com;
>>>>> DirectoryEntry de = new DirectoryEntry(ldapPath);
>>>>> de.AuthenticationType = AuthenticationTypes.Secure;
>>>>> string qry =
>>>>> String.Format("(&(objectClass=user)(objectCategory=person)(sAMAccountName={0}))",
>>>>> txtUsername.Text);
>>>>>
>>>>> DirectorySearcher ds = new DirectorySearcher(de,qry);
>>>>> SearchResult sr = ds.FindOne();
>>>>>
>>>>> if(sr==null)
>>>>> {
>>>>> lblMessage.Text = "User not found";
>>>>> return;
>>>>> }
>>>>>
>>>>> try
>>>>> {
>>>>> DirectoryEntry user = sr.GetDirectoryEntry();
>>>>> user.AuthenticationType = AuthenticationTypes.Secure;
>>>>> user.Invoke("SetPassword", new object[]{txtPassword.Text});
>>>>> lblMessage.Text = "Success <br>";
>>>>> }
>>>>> catch(Exception ex)
>>>>> {
>>>>> //throw ex;
>>>>> lblMessage.Text = "Failure: " + ex.Message;
>>>>> if(ex.InnerException != null)
>>>>> lblMessage.Text += "<br>" + ex.InnerException.Message;
>>>>> }
>>>>> finally
>>>>> {
>>>>> de.Close();
>>>>> i.UndoImpersonation();
>>>>> }
>>>>> }
>>>>> </script>
>>>>>
>>>>> <body>
>>>>> <form runat="server">
>>>>> UserName: <asp:textbox id="txtUsername" runat="server"/><br>
>>>>> New Password: <asp:textbox id="txtPassword" runat="server"/><br>
>>>>> <asp:button id="btnReset" runat="server" Text="Reset"
>>>>> OnClick="ResetPassword" /><br>
>>>>> <asp:label id="lblMessage" runat="server"/><br><br>
>>>>> I am running as: <%=Context.User.Identity.Name %><br>
>>>>> My process is running as:
>>>>> <%=System.Security.Principal.WindowsIdentity.GetCurrent().Name %>
>>>>> </form>
>>>>> </body>
>>>>> </HTML>
>>>>>
>>>>>
>>>>> web.config:
>>>>>
>>>>> <?xml version="1.0" encoding="utf-8" ?>
>>>>> <configuration>
>>>>> <system.web>
>>>>> <compilation debug="true"/>
>>>>> <authentication mode="Windows" />
>>>>> <!--<authorization>
>>>>> <deny users="?" />
>>>>> </authorization>-->
>>>>> </system.web>
>>>>>
>>>>> <!-- Secure the .aspx page using web.config
>>>>> <location path="reset.aspx">
>>>>> <system.web>
>>>>> <authorization>
>>>>> <allow roles="DOMAIN\AdminUser" />
>>>>> <deny users="*" />
>>>>> </authorization>
>>>>> </system.web>
>>>>> </location> -->
>>>>> </configuration>
>>>>>
>>>>> processModel section of machine.config:
>>>>> <processModel
>>>>> enable="true"
>>>>> timeout="Infinite"
>>>>> idleTimeout="Infinite"
>>>>> shutdownTimeout="0:00:05"
>>>>> requestLimit="Infinite"
>>>>> requestQueueLimit="5000"
>>>>> restartQueueLimit="10"
>>>>> memoryLimit="60"
>>>>> webGarden="false"
>>>>> cpuMask="0xffffffff"
>>>>> userName="domain\adminuser"
>>>>> password="adminpwd"
>>>>> logLevel="Errors"
>>>>> clientConnectedCheck="0:00:05"
>>>>> comAuthenticationLevel="Connect"
>>>>> comImpersonationLevel="Impersonate"
>>>>> responseDeadlockInterval="00:03:00"
>>>>> maxWorkerThreads="20"
>>>>> maxIoThreads="20"
>>>>> />
>>>>>
>>>>>
>>>>> "Joe Kaplan (MVP - ADSI)" <joseph.e.kaplan@xxxxxxxxxxxxxxxxxxxxxxxx>
>>>>> wrote in message news:e%235SZFnBGHA.1864@xxxxxxxxxxxxxxxxxxxxxxx
>>>>>> The crux of doing this in a web page is simply to create a
>>>>>> DirectoryEntry object that is bound to the user's object in AD and
>>>>>> invoking the ChangePassword ADSI method. Impersonation may or may
>>>>>> not be needed as you need to prompt for the old password anyway, so
>>>>>> it doesn't really hurt to simply use those credentials in your
>>>>>> DirectoryEntry constructor.
>>>>>>
>>>>>> The error you are getting sounds like it is unrelated to an
>>>>>> DirectoryServices programming stuff though. Are you sure ASP.NET is
>>>>>> working in general?
>>>>>>
>>>>>> Note also that Ryan and I have book coming out that covers this stuff
>>>>>> in detail, but it won't be available for a few more months now.
>>>>>>
>>>>>> Posting an example of the code you are using would be a great start.
>>>>>>
>>>>>> Joe K.
>>>>>>
>>>>>> "Harry Devine" <hdevine@xxxxxxxxxxxxxxxx> wrote in message
>>>>>> news:%23FysvCmBGHA.1008@xxxxxxxxxxxxxxxxxxxxxxx
>>>>>>> I've been searching around for an answer to this question, but
>>>>>>> haven't gotten too far. I'm fairly new to ASP.NET, so I'm not sure
>>>>>>> how to setup machine.config and web.config properly.
>>>>>>>
>>>>>>> What I want to be able to do is allow a domain user to change their
>>>>>>> password in the AD via a webpage. We have several users with domain
>>>>>>> accounts, but they do not actually login to our domain as they are
>>>>>>> spread out all over the country. I have a VBS script that notifies
>>>>>>> them when their password is due to expire, starting 10 days out.
>>>>>>>
>>>>>>> Since these users are not local to where my domain controller
>>>>>>> resides, they have to call me or email me to have their password
>>>>>>> reset. I found an example written by Ryan Dunn using an Impersonate
>>>>>>> function that he wrote (www.dunnry.com), but I keep getting an error
>>>>>>> stating: "Parser Error Message: The XML file
>>>>>>> c:\winnt\microsoft.net\framework\v1.1.4322\Config\machine.config
>>>>>>> could not be loaded. Either a required impersonation level was not
>>>>>>> provided, or the provided impersonation level is invalid. "
>>>>>>>
>>>>>>> This seems like, to me, a fundamental type of function to do, but
>>>>>>> info on how to do it is all over the place. Does anyone have any
>>>>>>> good ideas or steps on how to accomplish this?
>>>>>>>
>>>>>>> Thanks for any help,
>>>>>>> Harry
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>
>
.
- References:
- Changing domain user password
- From: Harry Devine
- Re: Changing domain user password
- From: Joe Kaplan \(MVP - ADSI\)
- Re: Changing domain user password
- From: Harry Devine
- Re: Changing domain user password
- From: Joe Kaplan \(MVP - ADSI\)
- Re: Changing domain user password
- From: Harry Devine
- Re: Changing domain user password
- From: Joe Kaplan \(MVP - ADSI\)
- Re: Changing domain user password
- From: Harry Devine
- Changing domain user password
- Prev by Date: Re: Changing domain user password
- Next by Date: Re: ASP.NET Authentication
- Previous by thread: Re: Changing domain user password
- Next by thread: ASP.NET Authentication
- Index(es):
Relevant Pages
|