Mac

Using the Keychain in MonoMac

The keychain is a great feature in OS X, allowing you to store passwords securely. In this tutorial I’ll outline how to store passwords in the keychain so your apps don’t have to worry about securely storing the passwords themselves.

Before I start, you can skip straight to the code on github here.

A few pointers

The MonoMac binding of the OS X keychain is somewhat basic at this moment in time, however it should be enough for basic password storage. OS X supports multiple keychains, as well as multiple types of passwords. At the moment the MonoMac bindings limit you to the system (well, user’s login) keychain, and only the ‘Internet Password’ keychain type.

Additionally you’ll want to sign your app to ensure your passwords are uniquely identified, without signing I’ve noticed that other MonoMac apps authored by myself seem to conflict with each other.

Relevant Classes

We store keychain records in a class of SecRecord, while the SecKeyChain static class handles the interaction with the keychain itself. When searching for records, you’ll fill in a SecRecord with the fields you need to match, then get SecKeyChain to return a matching record. You need to be careful not to try and insert duplicate records, if you do it’ll be difficult to pull out the record you want – it’s undefined which one you’ll get. This can lead to odd bugs where one second you get the correct password, and the next you get the wrong one.

The password for Internet Passwords is stored in the ValueData property, this is of NSData type rather than the string you’re probably expecting.

Selecting

To fetch a record, you need to provide a record with the fields you want to filter by set. At a minimum you’ll want to specify the service and account (username):

var searchRecord = new SecRecord(SecKind.InternetPassword)
{
    Service = ServiceName,
    Account = username
};

SecStatusCode code;
var data = SecKeyChain.QueryAsRecord(searchRecord, out code);

if (code == SecStatusCode.Success)
    return data;
else
    return null;

This code will return a matching record, or NULL if none are found. If more than one record matches your search criteria, you’ll get a random record. For this reason make sure you never accidentally insert duplicate records, or you’ll get unpredictable behaviour in your app. Remember, the search record you specify will be used as the search criteria – the filled in fields will be used for the search.

To get the password from the record use the following code:

password = NSString.FromData(record.ValueData, NSStringEncoding.UTF8);

Remember, the ValueData property is NSData, not a string. If MonoMac allows you to use a record type of ‘Generic Password’, the password will be stored in the Generic property rather than ValueData. Generic is also an NSData type.

Inserting

Inserting a password involves filling out a SecRecord, and then calling Add() on SecKeyChain:

var record = new SecRecord(SecKind.InternetPassword)
{
    Service = ServiceName,
    Label = ServiceName,
    Account = username,
    ValueData = NSData.FromString(password)
};

SecKeyChain.Add(record);

However, if you remember from earlier – you never want to insert a record without checking for an existing one because you’ll risk adding a duplicate record. Once inserted, you’ll see your password in the keychain utlity:

For code on how to perform a check and then update / insert as necessary, check the sample code.

Updating

Updating involves sending in the existing record (or at least one that’ll uniquely identify the record you’re after), and a new record to replace it:

record.ValueData = NSData.FromString(password);
SecKeyChain.Update(searchRecord, record);

The first parameter is handled in exactly the same was as when querying for an existing record, the second parameter is your newly updated record.

Deleting

Deleting is remarkably similar to updating, except you only send in your search record:

var searchRecord = new SecRecord(SecKind.InternetPassword)
{
    Service = ServiceName,
    Account = username
};

SecKeyChain.Remove(searchRecord);

Finishing Up

This guide has demonstrated how to interact with the OS X keychain using MonoMac. Make sure to check out the sample project for a simple utility class that wraps up all of the necessary functionality with a friendly interface.

Posted by Dan in C#, Mac, Tutorials, 2 comments

Running multiple instances of MonoDevelop on Mac

By default OS X will only let you run a single instance of any app, which is OK if the app is designed with multiple windows & a single instance in mind. MonoDevelop is a different beast, and sooner or later you’re going to want to run at least 2 instances of it, here’s how:

First run the AppleScript editor, and enter the following code:

do shell script "open -n /Applications/MonoDevelop.app/"

Now save the script somewhere easily accessible, make sure to set the ‘File Format’ to ‘Application’. I chose the name ‘MonoDevelop Launcher’:

Now the only problem left is the icon, it’s most likely the AppleScript icon, rather than the MonoDevelop one:

Use ‘Get Info’ to get the info for both your new launcher, and MonoDevelop. Click on the icon for MonoDevelop and press CMD+C. Now click on the icon for your script, and press CMD+V. The icon should now be correct:

References: Based on answer by ‘Subfuzion’ as StackOverflow

Posted by Dan in Guides, Mac, Programming, 0 comments

Getting Back / Forward mouse buttons working in Mac OS X

If you want to use mouse buttons #4 and #5 to go forward / backward in Mac OS X out of the box you’re going to be disappointed, and end up with just a scroll icon appearing.

There’s a few utilities you can use to fix this:

  • Microsoft IntelliPoint – Only works with MS mice, doesn’t seem to work in Mountain Lion
  • Logitech Control Centre – Only works with Logitech mice, apparently quite buggy now
  • Razer software – not tested, will only work with Razer mice anyway
  • Steermouse – Getting increasingly flakey with new OS X versions
  • USB Overdrive – Not been in development since Snow Leopard, doesn’t seem to work 100% of the time anymore
  • ControllerMate – Works!

ControllerMate to the rescue!

ControllerMate is actively developed & maintained, and offers an incredible amount of customisation for all HID peripherals. So not only will it sort out your back / forward issue, it’ll also solve the mouse acceleration issue – if that’s a problem for you. This guide will cover back / forward only, though.

1. First download and install ControllerMate.

2. Reboot and launch ControllerMate.

You’ll now be presented with a scary as hell screen that looks like you’re laying out circuit boards, rather than fixing a major limitation in OS X.

The diagrams in place on first launch are a kind of mini tutorial, telling you how you can do a few things. You can either leave them in place for future reference, or delete them to clean up the view.

The first step is to create a new Programming Group:

3. To do this, right-click in the sidebar and select ‘Create Programming Group”.

4. Afterwards, right-click on the new group, and select ‘Create Programming Page’.

5. Now right-click on the new group again, point to ‘Create Driver Configuration’, then select your mouse.

You can name your new items in the ‘Inspector’ window to the right.

6. Click on your programming page to display an empty grid.

7. In the ‘Palette’ to the right, select ‘Controllers’ from the drop down list. Find your mouse, then drag button #4, and button #5 to the grid.

8. Now select ‘Output’ from the drop down list in the Palette. Drag an instance of ‘Keystrokes Building Block’ underneath each of your mouse button instances.

You should now have something like this (without the green lines):

9. Link the blocks, by dragging from the button’s green hotspot, to the action’s green hotspot. Just as in the screenshot above.

10. Click on the keystroke block for button #4. In the Inspector window, click on the ‘Keys’ tab, then click on ‘Capture’. Enter they key combination for ‘Back’ (Command + [), then press stop.

If the command doesn’t appear correctly, click on ‘Open Keystrokes Palette’, and drag the buttons from the virtual keyboard to the window, as seen above.

11. Do the same for button #5’s keystroke block, but this time use the command for forward (Command + ]).

12. Click on the driver configuration item in the sidebar, and set buttons #4 and #5 to ‘None’.

You’re now done! Backward / Forward should work immediately in all apps.

But now my VM / Other App doesn’t respond to buttons #4 and #5!

This is a problem as a result of disabling the buttons and remapping them to forward / back. Fortunately there is a solution!

  1. Click on the group in the sidebar
  2. In the ‘Inspector’ window, check ‘Activate items when these applications are:’, select ‘running’
  3. Add all of the apps that you want to add back / forward support to the list.

Now the mouse will work in all applications. If an app supports backward / forward, remember to add it to the list above.

More VM

Not all VMs support the extra mouse buttons, even if they’re receiving them. If you’re having trouble, try following my follow-up guide for Parallels.

Posted by Dan in Guides, Mac, 20 comments