Yet Another Vss2Svn Import Tool

March 28, 2012. Posted by Eugene Ivakhiv

The year is 2012 but still there is some source code left in old SourceSafe repositories which needs to be imported into new-generation source control systems like Subversion.

There are numerous tools doing the same thing each having its pros and cons, limitations and issues.

Closest to our needs was the following tool: http://vss2svn.codeplex.com/

However the way it was importing sources was not "good" in terms of atomic commits of Subversion. Each file was committed separately creating own commit which cluttered SVN and you could not easily trace related files from the same logical revision. I know that there are some patches to the tool packing revisions to atomic SVN commits however there was still need to make some operation similar to labeling.

So, long story short, we've decided to make own version meeting our requirements and sufficient to our specific needs.

Feature highlights:

  • Analyzes revision tree prior to commit and packs revisions into one atomic revision.
  • Tool has UI allowing you to review analyzed VSS project tree before any commits.
  • Works with both VSS versions: VSS 6d and VSS 2005.
  • Updates commit metadata with original author, date-time and comment.
  • Creates formatted tags for labels. Label name is put into commit comment. Unlike Label, tag is created for whole trunk not only for original labeled files subset.
  • Files with last version only (VSS flag "Store latest version only" is set) are treated as one-revision files with creation date of last change. For example file with two revisions of March 20 and March 25 will be added to SVN and committed only once with its last change date March 25.

 

Limitations:

  • Deleted files are not supported.
  • Files with their location changed not supported.
  • Branching not supported. At least yet.

 

Known issues:

  • VSS6 automation in its original version has had some serious bugs causing "Version not found" errors. So, basically you could not obtain full revision tree programmatically. This is fixed in VSS hotfix 822845 which should be applied before running import, however there is no direct download link to this fix available on Microsoft site so you can grab it from here: vss6d.hotfix.822845.zip (3.94 mb)
  • To update metadata it is necessary to add SVN PreRevPropChange hook. The one I am using is included into download package. Not setting this hook will give you SVN exception during commit if you'll select "Update author, date, log" option.

 

Download: ArtfulBitsCZ.Vss2Svn.120420-001.7z (2.02 mb)

Installation: unpack and run on machine where VSS is installed. Tool uses SharpSvn library which latest version 1.7 is included.

It is highly recommended to make import to test repository before importing project to your main one. If you are using TortoiseSVN it has nice feature of local repository which you can create in a matter of seconds and check whether import will succeed.

Development , , , ,

ASP.NET High Trust Versus Reflection

March 25, 2012. Posted by Eugene Ivakhiv

Companies across the world are using services of third-party web hosting providers. However such choice leads to certain limitations caused by restrictive policies on web hosting side. For example a lot of providers hosting ASP.NET are enforcing High or Medium trust levels. These trust levels give a lot of headaches to ASP.NET developers forcing them to adapt their solutions to such restrictions.

In one of our ASP.NET applications we are using WCF service hosted on different server and connecting to this service using wsHttpBinding. Originally the connection was using security mode TransportWithMessageCredential but it was quite a disappointment to find out that in High trust this security mode cannot be used.

So, the minimal requirements was to at least ensure secure connection to WCF service in which case we've downgraded wsHttpBinding security mode to Transport. However another obstacle was on our way: secure connection to service could not be established with the following error Could not establish trust relationship for SSL/TLS secure channel.

Certificate used on WCF service end is perfectly valid in terms of CN name, expiration and trust chain. But for some reason its validation failed in ASP.NET application running in production High trust environment. I assume this was related to validation of certificate chain on hosting machine. In testing Full trust environment certificate validation passed with no problems. Digging around has shown that in High trust certain .NET classes related to X509 certificate validation are simply not working due to unmanaged code used internally which is not allowed in High trust. For example X509Chain class we've tried to use directly to validate certificate simply throws an exception when trying to build certificate chain.

First idea was to abandon built-in validation mechanisms in favor of manual certificate validation which is available via ServicePointManager.ServerCertificateValidationCallback static property, but unfortunately you cannot set your callback function in High trust. In ServerCertificateValidationCallback setter there are two lines of code: first one is demanding permissions and second one is the actual setting of provided callback function. So, bypassing first line would give us ability to use manual certificate validation.

In our particular case client's hosting provider altered High trust level with additional permissions to give more freedom for application developers. Among such alterations was ReflectionPermission set to Unrestricted="true".

Since we have unrestricted Reflection permissions we could put our callback directly into ServicePointManager static field s_ServerCertValidationCallback. I am not a big fan of such low level hacks which could break at the first change of internals, but in our case it was an acceptable solution.

The code was put into Global.asax Application_Start event handler:

protected void Application_Start(object sender, EventArgs e)
{
	// In High trust SSL certificate validation may fail due to inability to traverse certificate chain.
	// So the idea is to bypass certificate validation by putting custom RemoteCertificateValidationCallback.
	// In High trust this is not allowed so we are trying to achieve this using reflection.
	try
	{
		Type typeMgr = typeof(ServicePointManager);
		Type typeCallbackInternal = typeMgr.Assembly.GetType("System.Net.ServerCertValidationCallback");
		if (null != typeCallbackInternal)
		{
			// get constructor of internal class ServerCertValidationCallback
			var constructor = typeCallbackInternal.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null,
				new Type[] { typeof(RemoteCertificateValidationCallback) }, null);
			if (null != constructor)
			{
				// body of our validation function
				var callbackValidation = new RemoteCertificateValidationCallback(CertificateValidationCallback);

				// construct instance of ServerCertValidationCallback with our callback function
				var instanceCallbackInternal = constructor.Invoke(new object[] { callbackValidation });
				// set ServicePointManager.s_ServerCertValidationCallback field value
				var fld = typeMgr.GetField("s_ServerCertValidationCallback", BindingFlags.Static | BindingFlags.NonPublic);
				fld.SetValue(null, instanceCallbackInternal);
			}
		}
	}
	catch (Exception)
	{
	}
}

private static bool CertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
	bool bValid = true;
	// do your validation here
	return bValid;
}

In our case we compare public key set in application web.config to public key of certificate passed in validation callback. That did the trick and SSL connection was established.

 

By the way, welcome to our new blog!

Development , , , , ,