This project is read-only.

VPN Changing Password

Apr 14, 2010 at 8:14 AM

Hi all

I'm working on a VPN client, but I’m a bit stuck with how dotRas handles Change Password Required, error code 648.

I can detect it alright, but how do i go about sending the changed password to the server.

I'm thinking something like making a redial with the new credentials, but thus far i haven't been successful.

I Hope someone can help me with this.

Best regards


Apr 14, 2010 at 2:39 PM
Edited Apr 14, 2010 at 2:46 PM

To be honest, I don't believe DotRas currently supports changing passwords on the server. Right now everything that's implemented has been limited to the client APIs. If you can help me find the RAS API to do it, I can definitely get it implemented for you.

Edit: I forgot to put in I'm going to try and locate it myself and get the feature added for the 1.2 release if I can find it. Also, from my brief scan of the Windows SDK it looks like the RasDialDialog should be able to provide you with the means to change the password on the server if you want that functionality. Though it does display a user interface.

Apr 14, 2010 at 3:29 PM

Hi Jeff

Thanks for the quick reply

I found this:


dwSize As Long ' Specifies the structure size, in bytes.

szEntryName As String * 257 ' Specifies a string containing the phone-book entry to use to establish the connection. An empty string ("") specifies a simple modem connection on the first available modem port, in which case a nonempty szPhoneNumber must be provided.

' Windows NT 4.0 and later versions: The callback number is no longer stored in the registry. Specifying an asterisk for szCallbackNumber causes RAS to return error 704: ERROR_BAD_CALLBACK_NUMBER.

szPhoneNumber As String * 129 ' Specifies a string that contains an overriding phone number. An empty string ("") indicates that the phone-book entry's phone number should be used. If szEntryName is "", szPhoneNumber cannot be "".

szCallbackNumber As String * 129 ' Specifies a string that contains a callback phone number. An empty string ("") indicates that callback should not be used. This string is ignored unless the user has "Set By Caller" callback permission on the RAS server. An asterisk indicates that the number stored in the phone book should be used for callback.

szUserName As String * 257 ' Specifies a string that contains the user's user name. This string is used to authenticate the user's access to the remote access server.

szPassword As String * 257 ' Specifies a string that contains the user's password. This string is used to authenticate the user's access to the remote access server.

' Windows NT/2000: You can use szPassword to send a new password to the remote server when you restart a RasDial connection from a RASCS_PasswordExpired paused state. When changing a password on an entry that calls Microsoft Networks, you should limit the new password to 14 characters in length to avoid down-level compatibility problems.

' Windows 2000 and later versions: When retrieving the password using the RasGetEntryDialParams function, the szPassword member does not receive the actual password. Instead, szPassword receives a handle to the saved password. You can substitute this handle for the saved password in calls to RasSetDialParams, and RasDial. When presented with this handle, RasDial retrieves and uses the saved password. The value of this handle may change in future versions of the operating system; do not develop code that depends on the contents or format of this value.

szDomain As String * 16 ' Specifies a string that contains the domain on which authentication is to occur. An empty string ("") specifies the domain in which the remote access server is a member. An asterisk specifies the domain stored in the phone book for the entry.

Padding(2) As Byte ' * Padding to make sure that the type is the right size

'dwSubEntry As Long ' Windows NT Enhanced : Specifies the index of the initial subentry to dial. If the dial mode is RASEDM_DialAsNeeded, RAS dials this subentry. If dwSubEntry is not a valid subentry index, RAS dials the first subentry. If the dial mode of the phone-book entry is RASEDM_DialAll, dwSubEntry is ignored. If the phone-book entry has no subentries, dwSubEntry is ignored. The subentry indices are one-based. That is, the first subentry has an index of one, the second subentry as an index of two, and so on. The RASENTRY structure returned by RasGetEntryProperties indicates the dial mode (dwDialMode) and number of subentries (dwSubEntries) for the phone-book entry.

' Windows 2000 and later: If dwSubEntry specifies a valid subentry index, RAS dials the specified subentry regardless of the dial mode. If the dial mode is RASEDM_DialAll and dwSubEntry is zero, RAS dials all of the subentries.

'dwCallbackID As Long ' Windows NT Enh./Windows 2000: Specifies an application-defined value that RAS passes to your RasDialFunc2 callback function.

End Type 

So it seems to me, that when the connection receives an ErrorCode 648 you make a redial with the new password instead of the old one.

Unfortunately I haven't had any luck with this approach yet, but I will keep trying.

Perhaps you have some pointers as to how it can be done.

Hope to hear from you soon

Best regards


Apr 14, 2010 at 4:32 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Apr 14, 2010 at 4:33 PM

I shouldn't have much issue getting that implemented within the next couple of days, although you will need to use the development copy from source code in order to use it prior to the 1.2 release.

Keep an eye on the work item if you want to know the progress. Thanks for the feature request!

Apr 15, 2010 at 2:31 AM

It looks like it's going to be more difficult to implement than originally anticipated. I have the API changed to allow for it, but the RASCS_PasswordExpired state is never used in the callback. I've tried doing it a couple ways, but there might be an issue with the RAS API not working the way it's documented. I'll follow-up with Microsoft on their community forums, but not sure when or if I'll get the response we would like.

Apr 15, 2010 at 10:23 AM

Hi Jeff

Thanks for spending time on my issue, but it's as I feared not a simple matter.

I found this article from Microsoft , which I think is related to my problem. Unfortunately there doesn’t seems to be any solution for it. They only acknowledge that it's a problem.

Let me know if you find a solution. I will use my time on a workaround, but this would be a far better and cleaner solution than any workaround would provide.

Best regards


Apr 15, 2010 at 6:45 PM
Edited Apr 15, 2010 at 6:47 PM

Yeah, I saw that article myself last night while I was implementing everything. Which makes me sad, because I had a really nice API all worked out and even had it all implemented. :(

In order to fix the problem with the RasDialer component, that's going to take some coordination between myself and Microsoft if they will even consider fixing it. Which even if they do fix it, it won't be fixed on any machines until the next service pack for each operating system. I've done all I can to get it to work, but there is just no way around it. So even if I do get Microsoft to fix it, we're looking atleast a year before the issue is resolved on your client machines and that assumes they will be allowed to upgrade to the service pack that fixes it. I know the company I work at rolling out service pack updates to machines around the company is a big ordeal.

You do have some options to consider:

  1. You can use a service account whose password never expires for your clients.
  2. If you're using a user account, you can have the dial interface displayed and prompt them for their credentials through the RasDialDialog component. It displays the standard dial screen Windows uses, and will properly handle expired credentials (I have already tested this).

If you want to go down the road of using the interface, I can do some work on the RasDialDialog to add events that can be used to help development. However, you will lose all state events since that call is entirely self contained by the Windows API.

Edit: I wanted to add that I have shelved the changes on CodePlex until I can figure out what to do. Also, I'm going to change the feature request state to inactive until further notice.