Restricted variables

Richard Suchenwirth 2006-01-15 - In the Tcl chatroom it was asked how to restrict a variable in a namespace, so that it could be read from outside, but changed only by a specific proc. Here's my experiments. First, we create a namespace:

 namespace eval secret {}

The keeper of the secrets, the proc that may change values:

 proc secret::keeper {name val} {
    variable $name $val
    protect [namespace current]::$name $val

The (oversimplified) protection mechanism:

 proc protect {name val} {trace add variable $name write [list check $val]}
 proc check {val name el op} {
      if {[info level]<2 || [lindex [info level -1] 0] ne "secret::keeper"} {
           uplevel 1 [list set $name $val]
           error "forbidden"

Testing - first set such a variable:

 % secret::keeper foo 42

Trying to change it directly:

 % set secret::foo 45
 can't set "secret::foo": forbidden

The variable is unchanged.

 % set secret::foo 

Now let's build a little attacker proc that tries the same:

 % proc intruder {name value} {set secret::$name $value}

and testing:

 % intruder foo 666
 can't set "secret::foo": forbidden

Checking whether we still have the original value:

 % set secret::foo 

But the keeper of the secret can still change it to his heart's delight:

 % secret::keeper foo 123
 % set secret::foo 

Of course this isn't really secure - you just have to know the privileged name secret::keeper ...

Arts and crafts of Tcl-Tk programming