NullifyNetwork

The blog and home page of Simon Soanes
Skip to content
[ Log On ]

Archive - Historical Articles

You are viewing records from 12/24/2008 19:58:56 to 11/15/2009 11:00:20. I'll be adding support for selecting a date range in future.

With development getting more and more complex and thousands of lines of code being required to do things that used to take a couple of hundred, it's nice to see a simpler approach to things.  Sometimes the complexity has great benefit (like reuse and flexibility), but when learning that isn't necessarily first on your mind...

I just noticed a blog post on the Microsoft Small Basic blog and have since had a quick try... It looks like an awesome educational tool - easy to use and I certainly remember playing with logo and basic when I was younger - this provides both of those combined (along with decent graphics and no overhead).

So the blog is here:-

http://blogs.msdn.com/smallbasic/

And the program itself (which is basically a tiny IDE) is at http://smallbasic.com/ - hopefully it will let a new generation of children find programming as fun as it was for me when I was young.

Edit: Yes this is no match for C# which is a wonderful language and has a vast framework beside it, but this IS able to make a logo turtle move around in three lines on screen...

Permalink  3 Comments 

For those that don't know me, I work in an education sector linked business - which means that when the schools/colleges and universities go back we always get a vast increase in the amount of calls and number of issues that people raise.

So I've been trying to make up for the development time that was lost doing support by working later here and there.  Thankfully September is now over so I can return to having a personal life and possibly doing more research/blogging!

I have several projects I am investigating right now and hopefully one of them is getting closer to being something I can talk about and that will be able to have a bit of an ecosystem sit on top of it.  For all those people that were disappointed that Oslo wasn't a platform, this might make up for it, depending on what you were expecting :)

Permalink 

I am looking to merge both a P2P WCF service (for LAN support and accessible hops) and a publish-subscribe server to coordinate everything, this is just a post to keep track of the URL's related to doing this as I find them :)

WCF can't use its PeerChannel to connect to both hosts on the internet and local network at the same time, so there'll need to be two PeerChannel's and a Publish-Subscriber service bus connection to work out where everything else is.

Publish-Subscriber: http://msdn.microsoft.com/en-us/library/ms752254.aspx
PeerResolvers: http://msdn.microsoft.com/en-us/library/aa702771.aspx
Writing a custom peer resolver (new one needs to handle non-local hosts by requesting from the publish subscribe service): http://msdn.microsoft.com/en-us/library/ms751466.aspx
Sample WCF P2P chat app: http://msdn.microsoft.com/en-us/library/ms751502.aspx

(This post will be updated with more links as I find them)

Update: What I didn't realise when I started looking into this is that the PeerResolver service is not a magic 'find everything on your network' concept, but rather just a WCF service you register and unregister at, so it's basically already the public-subscriber list I was looking at.  That leaves the question of if the PeerResolver service does that, how on earth is it supposed to find things on the local network?  Well that would be the PNRP service, which happens to not be compatible with loads of OS' and isn't installed by default.  Great one there guys!

So instead I'll just make my own UDP transport for the peer resolver, and if anything I'll get to learn how to make a new transport :).

Permalink 

So this is a little different to my normal posts that are all 100% technical, but via the Omnima site (company who sell some embedded components) there's a link to a review of one of the products they sell which is used for monitoring stuff, which links to a specialist site on aquariums.

Well, it has some amazing photos of reefs on it which I thought were worth linking to.

Permalink 

Downloading Windows 7 slowly from MSDN since around 6.30PM here and it has been getting gradually slower.

So please wait before downloading it ;)

Edit: And Server 2008 R2 is out too as of the 14th August 2009!

Permalink 

This is a moan mostly, but has anyone else noticed that the developer story for silverlight development is totally utterly rubbish?

I had hoped that Microsoft would fix it for Silverlight 3 so that developers had a first class UI editor rather than having to go use a trial copy of Expression Blend with the worst user interface I have ever come across (I have MSDN but there's only ever an old version of it available and the current version appears to always be the CTP/Beta), or some third party app just to put down some buttons (with the 'run an app locally' addition and loads of other great features why has no time been spent on a decent design-time experience?).

I don't want to write XAML, I wouldn't mind adding controls using some C# code but I really hate XML, it's neither intuitive nor functional (can't easily call/make functions to draw X number of controls but must declare them individually).  I might be able to do Silverlight using 100% C# but it still comes down to the point of why is there no decent designer!???

I know this is supposed to be fixed in Visual Studio 2010 but it's really annoying.

Update: Now it's released I've had a chance to play with Expression Blend 3 and it's quite a bit better than the previous incarnations, and controls are now visible in a seperate section, so I think they are let off there as they've fixed the UI problems quite a bit; but the developer story for Silverlight is still terrible.

Permalink 

My ASP.NET server/composite controls were not getting events from child controls, but only on the real pages, they worked fine on test ones.  It turned out that I had a master page enabled but didn't have an ID set for it, so it was auto generating it.

Just add this to your master pages code file:-

protected override void OnInit(EventArgs e) 
{ 
	base.OnInit(e); 
	this.ID = "SomeName"; 
}

And child controls will start working as expected.  I don't often do web development so this stumped me for quite a while...

Permalink 

This is a story of how to handle a customer who could have ended up sending something back and getting expensive.

So: I've been interested in getting an Aeron chair or Freedom Task Chair or similar for a while now and only been put off by the price.  Eventually Amazon being the amazing pool of data it is made a suggestion of a similar one called a Cobham mesh back chair, which looked like it would fit the bill but only cost £270.

I obviously googled for more information, and found that whilst there weren't any reviews there was a place called chairoffice.co.uk selling the exact same Cobham mesh back chair for almost a hundred pounds less than the other suppliers out there (around £150 with VAT and delivery, or £119 ex VAT).  A quick background check to see if they were legitimate showed they were based really close to the actual manufacturer - Teknikoffice and happened to have their site hosted on the same server which explains the price difference a bit!!  I ordered after a particularly bad day at work in a sort of shopping to make myself feel good mood.

I was really impressed when it arrived the next day after ordering (very speedy dispatch), and I got right down to assembly after work - which was remarkably simple compared to a few other chairs.  Right after assembling it though I sat down in it and tried to adjust the headrest - and noticed that the back part had a hairline fracture, which when the headrest was extended was completely sheered through in shipping!!!!  I was gutted as the chair was really comfortable and I had that sick feeling of looking forward to a painful argument with a customer service rep.

I immediately sent a photo to the manufacturer and chairoffice customer service asking if they could supply me with the part that had broken and Mark in teknikoffice's customer service department replied almost immediately (appreciate this is around 10PM at night) and shipped me the entire back of one of the chairs as a replacement without any questions (which I got and fitted yesterday evening).

This is such good customer service it has made me want to talk about them.  Sometimes a faulty product can actually make you happier with the company if they deal with it correctly - and this is one of those cases; I don't think I have EVER encountered that good a customer service from any other company, so I would fully recommend if you're interested in a mesh back chair like an Aeron but a lot cheaper you get one from chairoffice.co.uk.

Permalink 

I even put OpenID on my own site in the latest iteration of its software as it is slowly growing in momentum, Scott Hanselman has details of how to implement OpenID support here.

This works particularly well with sites like Yahoo, where you can just put in the URL and be logged in near-instantly.

Permalink 

Very quick snippet that I just made use of to allow users to remotely change passwords over the web.  Just leave the domainname and username black to change the current users password.  This works great from ASP.NET and requires no special permissions, unlike some solutions that use LDAP or impersonation.

[DllImport("netapi32.dll", CharSet = CharSet.Unicode, 
   CallingConvention = CallingConvention.StdCall, SetLastError = true)]

static extern uint NetUserChangePassword(string domainname, string username, string oldpassword, string newpassword);
Permalink 

Just a quick example:-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Policy;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Reflection;
using System.IO;

namespace RestrictedAppDomainTest
{
    class Program
    {
        /// <summary>
        /// Example program demonstrating AppDomains with restrictive security
        /// Note that it requires the existance of C:\windows\win.ini to actually demonstrate it, but you 
        /// can modify this to any other file.
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            //we want to define a level of access for this appdomain to have
            PolicyLevel levelOfAccess = PolicyLevel.CreateAppDomainLevel();

            //now we grant the permissions to do something specific:-
            PermissionSet executeOnly = new PermissionSet(PermissionState.None);

            //bare minimum to run at all
            executeOnly.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

            //if you wanted to grant the rights to read files then you need to grant FileIO:-
            //uncommenting this means that the appdomain created can complete its task rather than erroring 
            //as intended:-
            //  executeOnly.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, "C:\\Windows\\"));

            PolicyStatement executeOnlyStatement = new PolicyStatement(executeOnly);
            UnionCodeGroup applicablePolicy = new UnionCodeGroup(new AllMembershipCondition(), 
		executeOnlyStatement);
            //and tie the code group we defined to the level of access
            levelOfAccess.RootCodeGroup = applicablePolicy;
            
            //now we could add rights for things we trust, so they can assert that they
	     //want to perform operations that the appdomain normally can't:-
            /*
             * This is commented out because it grants the running assembly those rights, but this is an 
             * example of how to do it:-
             * 
             * After using this, you can use a MessageBox or form from inside the plugin.
             * 
             * (Change to a using multiple assemblies to restrict each one seperately)
             *
            
            //this example results in the UI being available
            PermissionSet displayUI = new PermissionSet(PermissionState.None);
            displayUI.AddPermission(new UIPermission(PermissionState.Unrestricted));
            //wrap the permission set in a statement
            PolicyStatement displayUIPolicyStatement = new PolicyStatement(displayUI);
            //And only grant this permission when the assembly has been strong named
            AssemblyName exampleAssembly = Assembly.GetExecutingAssembly().GetName();
            UnionCodeGroup selectPolicy = new UnionCodeGroup(new StrongNameMembershipCondition(
                        new StrongNamePublicKeyBlob(exampleAssembly.GetPublicKey()
                    ), exampleAssembly.Name, exampleAssembly.Version
                ), displayUIPolicyStatement);
            
            //and finally we add this new policy to the previous one so there's a chain
            applicablePolicy.AddChild(selectPolicy);
            
             */

            //create the appdomain with our basic permission set!
            AppDomain domain = AppDomain.CreateDomain("RestrictedDomain", null, 
		  AppDomain.CurrentDomain.SetupInformation); //do not supply the level permission using this
// constructor, you can't change it later using//SetAppDomainPolicy
            
            //define the total security policy here
            domain.SetAppDomainPolicy(levelOfAccess);

            //now we load our example class from below, for this example we are using the currently executing 
            //assemblies name this can be replaced with another filename, or full assembly name to load a 
            //particular one from the GAC for example
            string thisAssemblyName = Assembly.GetExecutingAssembly().GetName().Name;
            IPlugin examplePlugin = (IPlugin)domain.CreateInstanceAndUnwrap(thisAssemblyName, 
		"RestrictedAppDomainTest.ExampleClass");

            //this starts running a thread and doing other things that are potentially dodgy.
            examplePlugin.DoSomething();
            //(note that if this didn't choose to start a thread it would still run in a seperate thread anyway)

            //no (security) exception here, just to show we are unaffected by the appdomain's restrictions!
            string dummyData = File.ReadAllText("C:\\windows\\win.ini");

            Console.WriteLine("An app domain is now started and running in the background.");
            Console.WriteLine();
            Console.WriteLine("Press any key to terminate and unload the restricted appdomain!");                    
            Console.ReadKey();

            //This results in the termination of the thread the AppDomain//started, and unloading of
            //any resources (including locked files or assemblies).
            AppDomain.Unload(domain);
            
            Console.WriteLine("Domain has been unloaded.  Press any key to end.");
            Console.ReadKey();
        }
    }

    /// <summary>
    /// Defines an example plugin
    /// </summary>
    public interface IPlugin
    {
        void DoSomething();
    }

    /// <summary>
    /// An example (malicious) plugin
    /// </summary>
    public class ExampleClass : MarshalByRefObject, IPlugin
    {
        /// <summary>
        /// This is called from the unrestricted AppDomain
        /// </summary>
        public void DoSomething()
        {
            voidDelegate startDoingThings = new voidDelegate(longNaughtyOperation);
            //run the method on a different thread to demonstrate we can  	     //even start threads here
            startDoingThings.BeginInvoke(null, null);
        }

        private delegate void voidDelegate();

        private void longNaughtyOperation()
        {
            while (true)
            {
                try
                {
                    //this is denied so will fail
                    string dummyData = File.ReadAllText("C:\\windows\\win.ini");
                    //this won't ever happen hopefully :)
                    Console.WriteLine("Restricted AppDomain completed its work!!!");
                    //stop looping if the above works!
                    break;
                }
                catch (SecurityException)
                {
                    Console.WriteLine("Security exception as expected, trying  again so you can terminate this thread... :)");
                }
                Thread.Sleep(1000);
            }
        }
    }
}
Permalink 

I am not much of a Linux fan and mostly run Windows even for servers, but while that is true I appreciate both a wide ecosystem of operating systems incase something bad happens to Windows or a particular component, love the vastly lower cost of purchase and like both the freedom and opportunity to change things if you need to. I have one Linux server right now for example, and with Mono it can even host the same sites as the Windows servers.

My choice for Linux has been Debian since about 2001, when I settled on it after moving away from Mandrake and Redhat and their terrible RPM dependency chains. (I did try SUSE in the middle and found that to be extremely polished and usable but the reality is that I have Windows for polished.)

Anyway, I am glad to see that Debian finally has a graphical installer and the ability to run live from the CD/DVD!  You can get it from here for 32bit x86 CPU's:-

http://cdimage.debian.org/debian-cd/5.0.0/i386/

And from here for 64bit x86 CPU's:-

http://cdimage.debian.org/debian-cd/5.0.0/amd64/

The folders with BT in the name contain the bittorrent distribution files. 

Permalink 

TribesNext have released a patch (and a full free download!) to work around the shutting down of the login servers for Tribes 2 in late 2008, so it's now finally possible to play again.

The patch also fixes the sierra update errors that were intentionally created and means that new accounts no longer require a CD key (Vivendi gave the game away for free to promote a sequel but stopped giving out keys and shut down the servers even for those that originally bought the game back in 2001 when it was released).

Now I'm just hoping that someone can update the engine to the latest version of the Torque engine from Garage Games (this is the game that gave me the incentive to buy a license for it originally).

Permalink 

I needed to get the unmanaged container name of an X509Certificate2 in order to be able to get access to the equivalent private key for it on Windows Mobile (I also wanted to be able to use the same routine on Windows CE and Win32 so this works as-is on all platforms).

No decent commentary but hopefully it will help someone else who is stuck without the container name or something.


#region Structures
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CRYPT_KEY_PROV_INFO
{
      [MarshalAs(UnmanagedType.LPWStr)]
      public string pwszContainerName;
      [MarshalAs(UnmanagedType.LPWStr)]
      public string pwszProvName;
      public uint dwProvType;
      public uint dwFlags;
      public uint cProvParam;
      public IntPtr rgProvParam;
      public uint dwKeySpec;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CRYPTOAPI_BLOB
{
    public uint cbData;
    public IntPtr pbData;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CERT_DSS_PARAMETERS
{
    public CRYPTOAPI_BLOB p;
    public CRYPTOAPI_BLOB q;
    public CRYPTOAPI_BLOB g;
}
#endregion

[DllImport("crypt32.dll")]
public static extern bool CertGetCertificateContextProperty(IntPtr pCertContext, 
	uint dwPropId, IntPtr pvData, ref uint pcbData);

public CRYPT_KEY_PROV_INFO GetCertificateContextProperty(X509Certificate2 certificate)
{
     //call once to get the size, call again to get the data
     try
     {
         IntPtr certhandle = certificate.Handle;
         uint pcbData = 0;
         if (CertGetCertificateContextProperty(certhandle, 2, IntPtr.Zero, ref pcbData))
         {
             IntPtr memoryChunk = Marshal.AllocHGlobal((int)pcbData);
             try
             {
       		    if (CertGetCertificateContextProperty(certhandle, 2, memoryChunk, 
			ref pcbData))
                  {
                    CRYPT_KEY_PROV_INFO context = 
				(CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(memoryChunk, 
				typeof(CRYPT_KEY_PROV_INFO));
                     return context;
                  }
                  else
                  {
                      throw new Exception("Failed to fetch the Certificate Context 
Property, possibly due to the certificate being modified during the call.  Please try again!");
                  }
              }
              finally
              {
                  Marshal.FreeHGlobal(memoryChunk);
              }
          }
      }
      finally
      {
          //dispose of certhandle or not??
      }
      throw new Exception("Failed to fetch the Certificate Context Property");
}

(Incidentally the extra structures are handy for doing other operations with the certificate so I left them there - the blob particularly is used in a lot of places in the CryptoAPI)

Permalink 

(This post is getting updated as I use things and need to be able to find things easier)

Generate a new private key (but no x509 public cert yet):-

openssl genrsa -aes128 -out selfsignedprivkey.key 2048

And then generate the public certificate to go with it:-

openssl req -new -x509 -days 7300 -key selfsignedprivkey.key -out selfsignedpubkey.cer

To convert from a pkcs12 key (sometimes called a .pfx file) to an OpenSSL key without a password to protect it:-

openssl pkcs12 -in file.p12 -out file.pem -nodes

(Handy for various open source servers that don't take pcks12 keys or use CryptoAPI on Windows, including stunnel, openvpn, hmailserver 5, webmin/apache, etc - omit -nodes if the system you are exporting for supports passwords on the private key.)

The converse when using OpenSSL to make a pkcs12 bundle is:-

openssl pkcs12 -export -inkey privkey.pem -in pubcert.cer -out combined.p12

And make a new certificate request:-

openssl req -new -out request.txt

And then there's sign certificate requests with the above key (assuming you edited your openssl.cfg file to point to certificates and keys that could have been generated above):-

openssl ca -in request.txt -out response.cer

The response is effectively the public certificate for the key file saved during the request generation, just use the two as-is.  To use the cert and key you just generated in windows, use the pkcs12 -export line above.

Note that if you want to sign request that include details of the subjectAltName (for multiple hostnames or e-mail addresses for example) then you need to make sure that "copy_extensions = copy" is not commented out in the openssl.cfg file.  If you do this though watch out, someone can make themselves a sub-CA with their certificate then if you don't check every request carefully.

And finally make a CRL for it (you should edit the openssl.cfg file to set the location of this on certificates prior to signing any requests as it's included in the certificate - use crlDistributionPoints = URI:http://www.yourdomain.net/ca-crl.crl in addition to nsCaRevocationUrl  = http://www.yourdomain.net/ca-crl.crl as otherwise windows won't think there is one there):-

openssl ca -gencrl -out mycrl.crl

Other things to note when using OpenSSL CA mode: index.txt needs to be completely empty, the serial needs to have 01 and a carriage return line feed ( echo 01>serial ) and you need to create crlnumber as being 01.

Permalink 

The multiple minute delay where Visual Studio freezes doing this is easy to fix and related to checking for necessary components on the target; it's actually down to the Platform Verification Task defined in the MS Build targets for the compact framework, but in .NETCF 3.5 you can just skip it by adding the following build rule (or you can set this up to apply to your entire system using the environment variables screen):-

set SkipPlatformVerification=true

Pre .NETCF 3.5 I think you need to manually add this as a constraint on the target, just google for SkipPlatformVerification for an example of how to do that.

Permalink