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 42
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 42
But the keeper of the secret can still change it to his heart's delight:
% secret::keeper foo 123 % set secret::foo 123
Of course this isn't really secure - you just have to know the privileged name secret::keeper ...