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 42Trying to change it directly:
% set secret::foo 45 can't set "secret::foo": forbiddenThe variable is unchanged.
% set secret::foo 42Now 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": forbiddenChecking whether we still have the original value:
% set secret::foo 42But the keeper of the secret can still change it to his heart's delight:
% secret::keeper foo 123 % set secret::foo 123Of course this isn't really secure - you just have to know the privileged name secret::keeper ...
Arts and crafts of Tcl-Tk programming