Sunday, July 29, 2007

SPSS.NET wrapper library now hosted on CodePlex

The C# library I wrote that wraps SPSS IO library (spssio32.dll) for managed applications is now hosted on CodePlex.  It hasn't been developed much in the last few years, but for what is already there it's quite useful and has (nearly) all the functions exposed by spssio32.dll.  Many developers have already started using it.  I recommend you try it out if you're interested in managed applications interfacing with SPSS Data files.

CodePlex project: http://www.codeplex.com/spss

Thursday, July 19, 2007

Finally, an OpenID provider that takes Information Cards as authentication

I don't know why this took so long to surface.  And maybe it just took a while to discover.  But honestly I don't know why there is only one service (that I can find) that offers this.  It's the perfect combination of phishing protection and usefulness in single sign-on that will make the web significantly safer.

Without going into a whole history of OpenID and InfoCard (aka Windows CardSpace as part of .NET 3.0), let me just draw the problem and solution for you.  OpenID is open to a variety of phishing attacks that are especially dangerous because "one login to rule them all", once stolen, can become as useful to the phisher (and dangerous for you) as the One Ring in the wrong hands.  All your sites immediately open up to the phisher of just one login.  What makes this especially precarious is that OpenID relies on the site taking your OpenID to redirect you to your own OpenID provider -- something that could be spoofed pretty easily so the site itself can steal your credentials.

Some OpenID providers (such as www.myopenid.com) have mitigated this threat by starting to place browser cookies on your computer so that if you don't see a picture you chose on your login screen then you have reason to be suspicious.  In my opinion, not good enough. 

Enter InfoCard: Microsoft's completely open and decentralized authentication solution that is completely phishing-proof because there are no credentials to steal.  If someone lured you into using your InfoCard on their phishing site, all they would get is a random series of characters from your InfoCard that they would find completely unhelpful in masquerading as you on other sites.

The problem with InfoCard is that there are (to date) almost no sites out there that accept InfoCard logins.  OpenID has a few hundred site lead on InfoCard.  So by combining these two technologies, you get the protection of InfoCard with the widerspread adoption of OpenID. 

All that has to be done is use an OpenID provider that accepts InfoCard as your login credentials.  Instead of the one username/password pair that you use at your OpenID provider to login, that could be stolen, you would just submit your InfoCard and you're in.  If someone who wasn't your OpenID provider was pretending to be, they wouldn't be any closer to masquerading as you.

So which OpenID providers have offered this elegant solution?  Just one that I can find: www.signon.com.  Hurrah for leading the way!  I'm switching my OpenID from MyOpenID.com to signon.com just for the InfoCard.  (Besides, it's faster to sign-on with a couple of InfoCard clicks than to type out a username and password).

Kim Cameron maintains an identity blog and discusses the theory behind combining these technologies if you want a more in-depth read.  I suggest adding Kim to your RSS feed.

For the record, I'd personally prefer to see all sites take InfoCard directly.  It would speed things up a bit.  But what I really want are Information Cards for my credit cards so I can transact business online without revealing my credit card numbers to every merchant.

Monday, July 02, 2007

How to (not) write an especially precarious app on .NET (Compact Framework)

As the .NET Compact Framework developers work to add features, fix bugs, and refactor code, we often have to determine whether a given change could break existing customer code.  The ideal is that NetCF 3.5 will run all apps that ran on NetCF 2.0 and 1.0.  We run hundreds of apps and many, many tests before shipping each product to check backward compatibility.  The .NET Framework (both desktop and CF) makes heavy use of internal classes to allow us the freedom to change the internals of the framework without breaking customer code.  But there are still ways that customers can write apps that may break on future versions.

Compare on exception text

Some exception types are very general and don't tell you much about the error.  One of these is InvalidOperationException, which can be thrown for a wide variety of reasons for many classes in our BCLs.  Developers usually look at the Exception.Message property to get an idea of what went wrong.  This is by design.  What is not by design is for developers to write code in their apps that looks at the Message property and makes code path decisions based on it.  Here is an example: (highly contrived, admittedly)

    class Program {
static void Main(string[] args) {
try {
XmlSerializer serializer = new XmlSerializer(typeof(MailAddress));
} catch (InvalidOperationException ex) {
if (ex.Message == "System.Net.Mail.MailAddress cannot be serialized because it does not have a parameterless constructor.") {
// Print message to user saying he chose a bad type to serialize
}
}
// Success!
}
}

This can break in at least two instances:

  1. The text in Exception.Message is localized to the computer running your app, so this code will break if it was run on, say a Spanish computer for example.
  2. A subsequent version of .NET Framework may change the Exception.Message text to be more descriptive, accurate or whatever. 

Either one of these likely cases may cause your code path to take a wrong turn (in this case to assume success).  Instead, you should write code that can analyze exceptions based primarily on exception type and/or error code (enumerable or integer) where available.

Note: It is generally ok to display the Exception.Message to a user of an app in the form of a MessageBox or a log file (there are security considerations in doing this, however) and let the user choose how to proceed.

Compare on Exception type

Another bad way of doing exception handling is to do absolute equality checking on exception types.  Here's another bad (and contrived) example:

    class Program {
static void ThrowBadArgument(int positiveValue) {
if (positiveValue <= 0)
throw new ArgumentException("Must be positive", "positiveValue");
}
static void Main(string[] args) {
try {
ThrowBadArgument(-5);
} catch (Exception ex) {
if (ex.GetType() == typeof(ArgumentException)) {
// Oops, the user provided a non-positive number!
}
}
}
}

Now suppose that the developer (or vendor) supplying you with your ThrowBadArgument method decided it was more appropriate to throw an ArgumentOutOfRange exception.  This would break your code and again cause your program to inappropriately assume success.

Here is a corrected example:

    class Program {
static void ThrowBadArgument(int positiveValue) {
if (positiveValue <= 0)
throw new ArgumentOutOfRangeException("Must be positive", "positiveValue");
}
static void Main(string[] args) {
try {
ThrowBadArgument(-5);
} catch (ArgumentException ex) {
// Oops, the user provided a non-positive number!
}
}
}

Note in this latter example how the throwing method is using the derived class.  But catching the base class in this way allows us to catch either ArgumentException or ArgumentOutOfRangeException equally well.

And if you need to check the exception type using an if statement (to check the type of Exception.InnerException for example) be sure to use the is keyword rather than Exception.GetType() == typeof(...).  For example:

// good example
if (ex.InnerException is ArgumentException) {
// do stuff based on inner exception
}
// Another good example (albeit harder to read)
if (typeof(ArgumentException).IsInstanceOfType(ex.InnerException)) {
}

// BAD example
if (ex.InnerException.GetType() == typeof(ArgumentException)) {
// do stuff based on inner exception
}

Finding public methods using reflection and parameter names

There's no good way to do this.  You should only find methods based on the parameter types, not parameter names.  The reflection API makes it easy to do it right, and harder to do it wrong.  Here is an example on how to do it right, and wrong:

    class Program {
static void Main(string[] args) {
// Good example
MethodInfo m = typeof(int).GetMethod("ToString", new Type[] { typeof(CultureInfo) });
Console.WriteLine(m.Invoke(3, new object[] { CultureInfo.CurrentCulture }));

// Bad example
foreach (MethodInfo method in typeof(int).GetMethods()) {
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length == 1 && parameters[0].Name == "provider") {
m = method;
break;
}
}
Console.WriteLine(m.Invoke(3, new object[] { CultureInfo.CurrentCulture }));
}
}

You should not take a dependency on parameter names of methods you call.  The .NET compilers take care of this for you, but if you go around them by using reflection and use parameter names rather than parameter types to find the method overload you want, you're asking to be broken if those method parameter names ever change (and they can!)

Finding internal-only methods or types using reflection

Again, there is no right way to do this.  Getting into the internals of a library by using reflection requires full trust and means you're just asking for your app to break in the next version of the library when those internals get changed.

In conclusion...

If you follow these tips, your apps will be more likely to perform well on current and future versions of the .NET Framework, on your own as well as your customers' locales.