Creating an SSTP VPN Connection: "The certificate's CN name does not match the passed value"

Aug 23, 2012 at 9:11 AM

Hi all,

I am trying to use DotRas to create an SSTP VPN connection using the following code:

  // create vpn connection
  RasEntry entry = RasEntry.CreateVpnEntry(connectionName, serverIP, RasVpnStrategy.SstpOnly, RasDevice.GetDeviceByName(("(L2TP)"), RasDeviceType.Vpn, false));
  entry.Options.RemoteDefaultGateway = false;
  entry.Options.IPv6RemoteDefaultGateway = false;
  entry.NetworkProtocols.IPv6 = false;

  // set vpn connection options
  RasEntryOptions options = new RasEntryOptions();
  options.ReconnectIfDropped = true;
  entry.Options = options;

  // add connection
  RasPhoneBook phoneBook = new RasPhoneBook();
  phoneBook.Open();
  phoneBook.Entries.Add(entry);

However when I try to connect to the VPN that is created I get an error message saying "The certificate's CN name does not match the passed value". 

I have created another connection manually using the same settings and it connects fine. I have compared all the settings in the properties dialog of the two connections and made them the same and yet the problem persists.

Can anybody point me in the right direction? I am sure I am missing some kind of automatic certificate generation step...

Thanks,
Max. 

Aug 23, 2012 at 9:44 AM

Ok, silly mistake, fixed it by setting the server address to a domain name that has an ssl certificate instead of the server IP. However, getting a new problem:

Creating the connection and dialing it programatically with the following code:

// dial
RasDialer dialer = new RasDialer();
dialer.Credentials = new System.Net.NetworkCredential(username, password);
dialer.AutoUpdateCredentials = RasUpdateCredential.AllUsers;
dialer.EntryName = connectionName;
dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);
dialer.Dial();

works fine. I can connect and see the server. However as soon as I disconnect and try to redial the new connection it prompts me to re-enter my username and password and says "Windows could not connect using the username and password you provided". It also says "You can leave the domain box empty since domain names are not needed to connect to the internet". This dialog looks different to the normal login box I see with a manually created VPN connection.

Any ideas?

Aug 23, 2012 at 10:27 AM
Edited Aug 23, 2012 at 10:27 AM

Ok solved the credentials prompt problem by updating the entries credentials after having added it to the phone book, using:

 

entry.UpdateCredentials(new System.Net.NetworkCredential(username, password), true);

 

Note: This MUST go after the line: 

phoneBook.Entries.Add(entry);
Coordinator
Aug 23, 2012 at 9:12 PM
Edited Aug 23, 2012 at 9:15 PM

Yes, that's one of the "gotchas" about working with the RAS API. Since DotRas doesn't store the credentials in memory internally, you'll need to add the entry to the phone book before most of those methods on the RasEntry class can be called.

Though I am surprised that the dialer isn't updating the credentials for you once the successful connection attempt has been established in your earlier post. Once the Dial attempt succeeds the AutoUpdateCredentials property should be causing the credentials you used to connect to be stored with the entry automatically.

Edit: I was also curious if you noticed you're using an L2TP VPN device rather than the SSTP device you were trying to use when creating your entry in your first post. Also, you really should avoid clearing out all the entry options that are being set by DotRas when you create the connection. A lot of those options if turned on or off could inadvertently cause connection problems since you're clearing out all the settings Windows generally uses.

Aug 24, 2012 at 8:55 AM

Thanks for the reply jeff_winn. I have now updated my code as follows:

 

            // create vpn connection
            RasEntry entry = RasEntry.CreateVpnEntry(connectionName, serverAddress, RasVpnStrategy.SstpOnly, RasDevice.Create(connectionName, DotRas.RasDeviceType.Vpn));
            
            // set vpn connection options
            entry.Options.RemoteDefaultGateway = false;
            entry.Options.IPv6RemoteDefaultGateway = false;
            entry.Options.ReconnectIfDropped = true;
            entry.Options.ShowDialingProgress = false;
            entry.Options.RequireMSChap2 = true;
            entry.Options.PreviewUserPassword = false;
            
            // add connection
            RasPhoneBook phoneBook = new RasPhoneBook();
            phoneBook.Open();
            if (phoneBook.Entries.Contains(connectionName))
            {// already exists
                // check if connected
                RasConnection rasConnection = RasConnection.GetActiveConnectionByName(connectionName, phoneBook.Path);
                if (rasConnection != null)
                    rasConnection.HangUp();
                phoneBook.Entries.Remove(connectionName);
            }
            phoneBook.Entries.Add(entry);
            
            // set credentials
            entry.UpdateCredentials(new System.Net.NetworkCredential(username, password), true);

I am now creating a VPN device instead of getting an L2TP one. Is this correct procedure?

I am now updating options instead of overwriting them. 

After creating the connection I successfully programatically connect to it using the code in the second post. When I manually disconnect and reconnect, I am not prompted for credentials (good) however sometimes the connection connects and sometimes it still gives me the error in my second post. Any ideas why this might happen?

Thanks,
Max. 

 

Coordinator
Aug 24, 2012 at 2:20 PM

If you're trying to make an SSTP VPN connection, you just need to use the SSTP VPN device, which would be available.

RasDevice.GetDeviceByName("(SSTP)", RasDeviceType.Vpn, false)

Creating the device means if you are on a different operating system it would try to register the SSTP VPN device profile even though it may not exist, say on Windows XP... which would cause your connection to fail. SSTP VPNs are only available on Windows 7 and higher as of right now.

As for your problem with the credentials not working correctly, it might be a combination of how you're using both components. Since you're storing the credentials on the entry through the UpdateCredentials call, you do not need to pass anything to the dialer via the Credentials property. Also, since you're not going to be passing the credentials there, make sure you remove the line where you're setting the AutoUpdateCredentials property to AllUsers. Once you call Dial on RasDialer, the credentials should be retrieved from the entry automatically and then sent to the dialer internally.

Aug 24, 2012 at 4:22 PM
Edited Aug 24, 2012 at 4:23 PM

Thanks for your help yet again - new code:

        public static void CreateVPNConnection(string connectionName, string serverAddress, string username, string password){
            
            // create vpn connection
            RasDevice device = RasDevice.GetDeviceByName("(SSTP)", RasDeviceType.Vpn, false);
            if (device == null) throw new Exception("Cannot get RasDevice");
            RasEntry entry = RasEntry.CreateVpnEntry(connectionName, serverAddress, RasVpnStrategy.SstpOnly, device);
            
            // set vpn connection options
            entry.Options.RemoteDefaultGateway = false;
            entry.Options.IPv6RemoteDefaultGateway = false;
            entry.Options.ReconnectIfDropped = true;
            entry.Options.ShowDialingProgress = false;
            entry.Options.RequireMSChap2 = true;
            entry.Options.PreviewUserPassword = false;
            
            // add connection
            RasPhoneBook phoneBook = new RasPhoneBook();
            phoneBook.Open();
            if (phoneBook.Entries.Contains(connectionName))
            {// already exists
                // check if connected
                RasConnection rasConnection = RasConnection.GetActiveConnectionByName(connectionName, phoneBook.Path);
                if (rasConnection != null)
                    rasConnection.HangUp();
                phoneBook.Entries.Remove(connectionName);
            }
            phoneBook.Entries.Add(entry);
            
            // set credentials
            entry.UpdateCredentials(new System.Net.NetworkCredential(username, password), true);
        }

        public static void DialVPNConnection(string connectionName)
        {
            // dial
            RasDialer dialer = new RasDialer();
            dialer.AllowUseStoredCredentials = true;
            dialer.EntryName = connectionName;
            dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);
            dialer.Dial();
        }

Looks all good! Creating, connecting, disconnecting and reconnecting all perfectly. Thanks so much for your help - would probably be still working on the first problem without it!

Thanks,
Max. 

Aug 28, 2012 at 9:31 AM
Edited Aug 28, 2012 at 9:36 AM

Ok new error - manually connecting to the VPN in network connections works fine without having to specify credentials, however if I use "rasdial vpnname" it throws an error 691 - "The remote connection was denied because the user name and password combination you provided is not recognized, or the selected authentication protocol is not permitted on the remote access server". Any ideas?


Update

For some reason, using "rasphone -d vpnname" connects successfully without prompting for creds :)

Coordinator
Aug 28, 2012 at 1:09 PM

Those products aren't built by me, so they're not supported by this project. If you use them, you're on your own. The purpose of this project was to replace those within .NET applications so we didn't have to shell out to them to get our applications to connect.

Aug 29, 2012 at 8:20 AM

Fair enough - I thought it would have been some kind of configuration problem.

Thanks for your help