Fabulous Adventures In Coding

Eric Lippert's Blog

Alas, Smith and Jones

We have a feature in C# which allows you to declare a "friend assembly". If assembly Smith says that assembly Jones is its friend, then code in Jones is allowed to see "internal" types of Smith as though they were public(*). It's a pretty handy feature for building a "family" of assemblies that share common implementation details.

The compiler enforces one particularly interesting rule about the naming of friendly assemblies. If assembly Smith is a strong-named assembly, and Smith says that assembly Jones is its friend, then Jones must also be strong-named. If, however, Smith is not strong-named, then Jones need not be strong-named either.

I'm occasionally asked "what's up with that?"

When you call a method in Smith and pass in some data, you are essentially trusting Smith to (1) make proper use of your data; the data might contain sensitive information that you don't want Smith to misuse, and (2) take some action on your behalf. In the non-computer world an entity which you share secrets with and then empower to take actions on your behalf is called an "attorney" (**).  That got me thinking, which usually spells trouble.

You want to hire an attorney. You go to Smith & Jones, Esqs. You meet with Smith, the trustworthy-looking man on the left of this photo:

alassmithandjones

Scenario (1):

You check Smith's ID. It really is Mel Smith. You are contemplating giving Smith a secret, and empowering Smith to act on your behalf with the knowledge of that secret. Smith says "I share my secrets with my partner Griff Rhys Jones, whose identity you may now verify, here is Jones and here is Jones' ID. Jones will also be acting on your behalf. Jones has full access to all secrets which are internal to this organization."

You decide that you trust both Smith and Jones, so you share your secrets with Smith. A series of wacky sketch comedy hijinks then ensues.

(Smith and Jones are both strong-named assemblies. That is, they have "ID" you can verify. Smith's internals are visible to Jones. Everything is fine.)

Scenario (2):

You check the ID. It is Mel Smith. Smith says "By the way, I share my internal secrets with everyone in the world who claims their name is Jones, I don't bother to check IDs, I just trust 'em, and you should too! Everyone named Jones is trustworthy! Oh, and that includes my partner over here, Jones. Good old Jones! No, you can't check Jonesie's ID. Doesn't have any ID, that Jones."

This is ludicrous. Obviously this breaks the chain of trust that you showed you were looking for when you checked Smith's ID in the first place.

(The compiler keeps you from getting into this terrible situation by preventing Smith from doing that; Smith, a strong-named assembly, can only state that it is sharing his internal details with another strong-named assembly. Smith cannot share its internals with any assembly named Jones, a weakly-named assembly in this scenario. We restrict Smith from exposing internals to weakly-named assemblies so that Smith does not accidentally create this security hole or accidentally mislead you into believing that Smith's internals are in any way hidden from partially-trusted code.)

Scenario (3):

You don't bother to check Smith's ID. In fact, you give your secrets and power of attorney to anyone named Smith, regardless of who they actually are or where they came from. The first Smith you pick off the street says "By the way, I'll give my internal secrets to anyone named Jones". 

Do you care?  Why would you?  You're already giving secrets away to anyone named Smith! If a con artist wants your secrets, he can pretend to be Jones and take them from Smith, or he can pretend to be Smith and get them from you directly, but either way, the problem is that you are giving away secrets and power of attorney to strangers off the street.

(Smith and Jones are both weakly named assemblies, Smith exposes internals to Jones. This is perfectly legal, because if you don't care enough about who you're talking to to check IDs then what's the point of the security system preventing those random strangers from talking to each other?)

**************
(*) Fully trusted assemblies of course can always use reflection to see private and internal details of other assemblies; that is what "full trust" means. And in the new CLR security model, two assemblies that have the same grant set can see each other's private and internal details via reflection. But friend assemblies are the only mechanism that allow compile time support for peering at the internal details of another assembly.

(**) or "delegate", which obviously I want to avoid because that means something technical in C#.

 

Published Thursday, June 04, 2009 7:04 AM by Eric Lippert

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

KodefuGuru said:

I've never needed to use friend assemblies. It breaks encapsulation, which is a no-no. At least you have to be explicit (in the case of strongly-named assemblies) in who can access the internals, but it still smells to me.

June 4, 2009 2:01 PM
 

pminaev said:

> It breaks encapsulation, which is a no-no.

It doesn't break encapsulation any more than "internal" does on its own. It simply defines another encapsulation boundary, which you still fully control (especially when it comes to signed assemblies).

June 4, 2009 2:06 PM
 

TheCPUWizard said:

1) How is this different than InternalsVisibleToAttribute? [Which I typcially use only for UnitTesting access]

2) Exposing internals across an assembly boundary is philosophically to using "partial" to expose class internals across a file boundary.

June 4, 2009 2:27 PM
 

TheCPUWizard said:

Pardon the first question, I had not followed the link abnd though this blog was about a NEW (aka .net 4.0) feature, rather than something that has been around for YEARS!!!!!

June 4, 2009 2:28 PM
 

marc.gravell said:

A good way of expressing it, as always.

Now if only the syntax for InternalsVisibleTo were prettier - perhaps using the public key *token* rathen than the full key...

June 4, 2009 6:20 PM
 

jcoehoorn said:

@KodefuGuru: I've found it actually improves encapsulation, by allowing you to mark some things as internal that would otherwise need to be given greater access to allow for unit testing.

June 4, 2009 6:59 PM
 

Matthew Jones said:

I love how you used Smith and Jones in this article :-)

I didn't know you guys over in the US knew who Smith and Jones are.  I'm from the UK and grew up with them on TV, they're awesome aren't they :-)

I didn't think I'd ever see them used to illustrate a programming related concept, kudos to you sir ;-)

My introduction to Smith and Jones was the London Weekend Television adaptation of "Wilt", which was a favourite novel of mine in my younger days. Jones completely nails the character of Wilt. -- Eric

June 5, 2009 4:13 AM
 

Bruno Martinez said:

"We restrict Smith from exposing internals to weakly-named assemblies so that Smith does not accidentally create this security hole or accidentally mislead you into believing that Smith's internals are in any way hidden from partially-trusted code."

IMO, the chain of trust of strong naming is a mistake. Nothing prevents that Smith gives away a key so that anybody can build a Jones account. I asked this here http://stackoverflow.com/questions/868799/why-cant-strongly-named-assemblies-use-assemblies-that-arent-signed

June 5, 2009 9:28 AM
 

George Spofford said:

@jcoehoorn: +1.  Unit tests often need to test things otherwise marked as private or internal, and contorting the design or the visibility for the sake of enabling a unit test seems unnecessary. (I know some people believe that you should only unit test public interfaces, but when they rely on sufficiently interesting private information, the goal of confirming correct behaviors and states is greatly simplified, and therefore more cheaply and correctly performed, by testing private methods and asserting on private properties/member variables as well.) As stated, friend assemblies don't seem to solve the problem of unit-testing private methods, but it will help a great deal nonetheless.

It has always struck me that public, private, protected, internal are simply coarse access control mechanisms, and for ORM and unit-testing purposes we would benefit from finer-grain access control.

June 5, 2009 6:12 PM
 

Gabe said:

Is it wrong that I first read the title of this post as "Alias, Smith and Jones" (like the old TV show)?

No, not at all. Smith and Jones named their comedy show "Alas Smith and Jones" as a pun on "Alias Smith and Jones" -- Eric

 

June 5, 2009 11:29 PM
 

Mark Rendle said:

I find the InternalsVisibleTo attribute extremely useful for n-Tier solutions, especially those with interchangeable assemblies providing interop with different database servers or other external solutions.

The thing I'd really like would be GUI support for it in VS 2010. Many of the AssemblyInfo.cs attributes are exposed in the Project Properties pages, so why not InternalsVisibleTo? Especially useful for the strongly-named assemblies.

June 6, 2009 5:30 AM
 

Charlie Calvert's Community Blog said:

Welcome to the 49th edition of Community Convergence. The big excitment of late has been the recent release

June 9, 2009 4:45 PM
 

Невероятные приключения в коде (перевод блога Эрика Липперта) said:

В C# есть возможность объявить « дружественную сборку ». Если сборка Смит говорит, что сборка Джонс –

June 10, 2009 7:19 AM
 

Chris said:

Mel Smith's career didn't last much longer than the TV series, Griff Rhys Jones however is still everywhere on the BBC.

I've found InternalsVisible great for whitebox testing, if you're a believer in that.

June 12, 2009 7:23 PM

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required
Submit

About Eric Lippert

Eric Lippert is a senior developer on the Microsoft C# compiler team. Before that he worked on the framework of Visual Studio Tools For Office. Before that, he worked on the compilers, runtimes and tools for VBScript, JScript, Windows Script Host and other Microsoft Scripting technologies. He lives in Seattle and spends his free time editing books about programming languages, playing the piano, and trying to keep his tiny sailboat upright in Puget Sound.

This Blog

Syndication


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker