When I said flag, I meant a _shared_ flag. If I set the flag on "foo", all strings "foo" anywhere in the program would be treated as secret by %O. One needs a function to set the flag, but normal programs should never try to clear it.
As for objects, a C module that wants to operate on strings need a way to dig out a char * from the internal representation. You don't want to support more than one internal representation. Typical examples may be Stdio.file->write and Crypt.md5()->update (both may well be invoked with sensitive information as input).
For the general case, the C code would have to allocate a new char (or wchar_t, or whatever) array, probably on the stack, and then copy the contents of the general string object character by character using the `[] operator. You can't do it the easy way by casting the object to a normal pike string, as that defeats the entire purpose of SecretString.
And in the paranoid case, it should of course clear its copy again before it's deallocated. That's one of the uglier aspects: You'd like to put the knowledge that a string should be wiped from memory after it's used in the SecretString class, but still every single C module that handles strings will need to know about that.
/ Niels Möller ()
Previous text:
2003-01-30 14:54: Subject: Re: OpenSSL wrapper vs Pike's SSL (Was: Bz2)
For starters, the basic strings are shared. They don't have any identity in the way objects have and there thus isn't any place to put a flag on them that will propagate in a sane way. Introducing it would add a level of indirection that affects all strings, not only those that uses the flag. It'd also be incompatible with the current strings and we'd have to find seek out every place in the C code that compares strings for equality with svalue1->u.string == svalue2->u.string.
The compatibility issue aside, I think it's designwise ugly to clutter up the default string implementation with features that are needed only rarely, especially if it adds complexity when it isn't used. Objects impersonating strings is a fairly elegant way to avoid that, and I don't see any serious problems handling such objects (speaking from some experience of the Locale.DeferredLocale class which implements localized strings that choose language when they are printed).
Objects are also useful since they provide better typing, e.g. functions like crypt() could only accept a SecretString as the password and thus force the user to not make the mistake of using a normal string for it which is likely to get shown in cleartext in a backtrace. Granted, that can be fixed for builtin strings too by introducing a new builtin type, perhaps "secret_string" or "string(secret)", for them.
/.../ If the builtin strings aren't good enough and pople start coding their own "SecretString" and "FooString" and "BarString", then we'll get the same mess as C++, where the common cry of war is "Death to all strings but basic_string<>!!!"
I suspect this has more to do with C++ strong typing and exceedingly complex operator overloading semantics. What problems are there that we'd get in Pike too?
When adding support for arbitrary string-like objects to all C modules (in particular the I/O and the Crypto code), I fear you get enough added complexity that you end up with more security bugs than you started with.
In what way? The SecretString class appears to be a self-contained data type, and it's fairly easy to reason about the operations it implements.
- A global runtime flag that clears all memory at deallocation
time.
That would cause quite a lot of unnecessary overhead since a program typically handles a lot more strings that don't need it. But of course, given that one adds a flag field to strings (which probably will never happen considering the implementation difficulty), it's not hard to a flag for that too on a per-string basis.
/ Martin Stjernholm, Roxen IS