Updated 2006-01-15 20:56:22 by suchenwi

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 var $name w [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