Re: untainting PATH in mod_perl
Sorry, getting out of good ideas.. Surprise, surprise: I found out that my code does not work under mod_perl 1.23 either! And I found the real solution: one has to add PerlSetupEnv Off to the Apache configuration file. Now the untainting mumbo-jumbo in perl section works. Warning: this has the consequence of breaking the part of the CGI environment emulation that deals with environment (e.g. instead of $ENV{HTTP_USER_AGENT}, you now have to check Apache-request()-subprocess_env(HTTP_USER_AGENT)). Glancing at its source code, I don't think CGI.pm will survive that... BTW, I finally got around to reading mod_perl's source, and it is now clear to me that the environment, when being copied from -subprocess_env() into %ENV, gets tainted (around line 704 in src/modules/perl/mod_perl.c). The whole %ENV gets tainted, not just the HTTP_USER_AGENT and such from the CGI context, so PATH is tainted as well. This explains our now common problem - and also guarantees that there is no easy way out of it if you use CGI.pm yourself :-(. Hope I'm being helpful at last, -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: untainting PATH in mod_perl
I need some help with this. Can you share the code you use w/in your Perl section? Sure! Here is how I untaint a selected range of variables from the WWW server's %ENV, and discard all the others (good move to ease debugging anyway): # From httpd.conf PerlTaintCheck On perl BEGIN { # Untaint environment. Those variables come from # Apache; even if they didn't, they would come from the root # user who launched Apache. No security problems here. my %cleanenv; foreach my $var (qw(PATH GATEWAY_INTERFACE MOD_PERL)) { ($cleanenv{$var})=($ENV{$var} =~ m/^(.*)$/g); } %ENV=%cleanenv; } /perl I'm pretty confused because I was able to untaint my PATH var. by putting $ENV{PATH} = '/bin'; in the ***same scope*** where I was getting the error. Makes sense to me: if you are using Apache::Registry (for example), your script only gets compiled once and the BEGIN blocks run at that time. In fact Apache::Registry reads your cgi, then cooks it into something like this: package Some::Name::Made::Up::By::Apache::Registry::To::Isolate::Your::cgi; sub handler { # Your script here } Then it evals that (by that time, the BEGIN blocks run), then calls Some::Name::...::handler(). The purpose of these steps is caching: the next time the CGI is hit, the evalling needs not be redone, only the handler call. Now, my guess was that %ENV gets reset between the eval and the handler call. As you mention, putting the untainter in the same scope solves the problem, because you now circumvent the cleaning. Putting it in the perl section should also solve the problem once for all, because the perl section runs before the default %ENV value is stashed (even before Apache forks, in fact). -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: untainting PATH in mod_perl
Thanks for sharing your code; unfortunately, it's not working for me. I copied it into my httpd.conf file, stopped/started the server and I still get the same error: Sorry, getting out of good ideas.. I'm not using mod_perl 1.99, this probably explains why my code does not work, and also it prevents me from further investigating your problem. There was a thread recently on the list about perl ... /perl section only being implemented recently, do you run the latest version of mod_perl? Insecure $ENV{PATH} while running setgid While running setgid? That's odd (although I don't think this nterfers with your problem in any way) foreach my $release (`/bin/ls $path`) { # $path is already untainted do stuff } TI (still) MTOWTDI: why not try use IO::Pipe; my $pipe = new IO::Pipe()-reader(/bin/ls,$path); while($pipe) { } (although this will not save you from having to review all your codebase) -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: untainting PATH in mod_perl
In plain CGI, I normally do this inside a BEGIN block; in mod_perl however, this doesn't work. This would work if this was done in a Perl section of the httpd.conf file (this is what I do). I am not sure why the BEGIN block is not executed, but my guess is that the environment gets automatically restored at the end of every script run under Apache::Registry, including the tainted PATH. -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: Single login/sign-on for different web apps?
I hadn't really taken a look at personal certificates until this thread came up. It looks like thawte is offering personal certificates at no charge. http://www.thawte.com/getinfo/products/personal/contents.html Yep, and the society I work in develops a GPLed PKI, which is a Perl+PHP+LDAP app for rolling your own certificates (both user and server): http://idx-pki.idealx.com/ Certificates are indeed a straightforward way of getting SSO - but you have to carry your certificate with you whenever you change workstations. Here are reasonable solutions (trading security for convenience): * most secure: use USB crypto tokens (slow and extra per-user price, but will safeguard the private key and destroy it upon attack); * very secure: use dedicated workstations, one per user (impractical), or laptops (expensive but may be amortized with other needs); * not so secure (equivalent of password SSO): carry the key on a floppy, and keep it password-encrypted at all times. On the server side, you have to get your Apache to grok certificates (easy with recent versions of openssl), and the authentication info then gets passed down to PHP and Perl scripts as environment variables (OK, this guy is called CN=John Doe, OU=sales, O=yourcompany - trust me on this). You have to patch your apps, sure, but all the burden of binding a bunch of crypto bits to a name is removed from you in a highly secure fashion. -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
Re: RFC: Exception::Handler
One of the things I don't like about traditional try/catch handling is that it doesn't allow for class level programming. You need to allow any subroutine to try/catch exceptions (die). It's also nice to notify any object in the stack that there is an unhandled exception passing through its code. I'm afraid I don't get it - isn't it what the finally functionality in Error.pm (CPAN) does ? try { stuffThatMayThrow(); } finally { releaseResources(); }; This eliminates a lot of explicit try/catches. Well, destructors are of some help too in that issue. (not lighting up a flamewar, just trying to understand the issues - I don't know much about Aspects, but I find exception handling with Error.pm a breeze, even for big projects) -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
Re: Can't pipe to external programs
Hey list, We're trying to turn some xml into a pdf using fop. A wrapper has been written for fop so that we can pass it xml on the stdin, and get the pdf from the stdout. We're using IPC::Open2 to set this up: I remember having lots of trouble with the implicit redirection that mod_perl performs (IIRC, STD[IN|OUT|ERR] streams don't map to file descriptors 0, 1 and 2 under mod_perl and this confuses IPC::Open[23]). I ended up recoding my very own fork() - pipe() - dup() - exec() - exit() stuff, using POSIX::close(), POSIX::dup2() (that don't get confused) and POSIX::SYS_exit() instead of exit() in the child process (so that global variables representing e.g. a database connection don't get destroyed, causing shutdown messages to get sent to the remote server). use IPC::Open2; open2(*README, *WRITEME, $progname); print WRITEME $thexml or warn problem writing to $progname: $!\n; my $pdf = README; close(WRITEME); close(README); You should close WRITEME before attempting to read, or deadlock may occur because either 1) WRITEME wasn't flushed from Perl's stdio buffers and $progname didn't see any input yet, or 2) $progname doesn't see end-of-file and thus expects more data. -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
Re: Are global variables truly global?
I have some state data that I need to persist between requests. At the moment these are COM objects, but they'll be ported to Perl Classes. It is quite important that only one of these instances exist per web server. These instances are too large to write and read to file on every request. So I have defined the variable as a package level variable. Package level variables are shared upon fork(), in the sense that the memory segment(s) they use is made available to all child processes. BUT the memory itself isn't shared, and any subsequent write to the variable in one of the children will not reflect in the others. So unless your state data is a constant, this is not what you want. -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
Re: Mod_perl component based architecture
also does modperl support object oriented programming? Well yes it does indeed (see any good book on Perl, such as «advanced Perl programming» from O'Reilly). As for the remaining of the question, I've been wondering for myself if there is a MVC (model-view-controller) framework for WWW publishing in Perl ? I gather there exist quite a few for Java, but I couldn't find anything significant under Perl. -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
Re: startup.pl for configuration
Hello, I would like to have a config file like /etc/mywebapp.conf where I would put all my modules configuration. Yep, that's what we do too. Then I would have a WebApp::LoadConfig module that would run from startup.pl, and initialize my Perl modules default variables at Apache start. I'd rather think of it as a WebApp::Config _object class_ than a WebApp::LoadConfig _module_ (see below). My config file would be some like : ### /etc/mywebapp.conf ### ### MyPackageOne::Default_Value_One = 1 MyPackageOne::Default_Value_One = 2 How about the Config::Ini module from CPAN, that implements m/Win...s/ .INI format ? It's versatile and quite easy to understand even for your newbie users. Plus it's already done and well tested, and it has write support (comments are discarded). Here at IDEALX we use a subclass that goes like this: -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= package My::Hierarchy::Config; use strict; use Config::Ini; use vars qw(@ISA); @ISA=qw(Config::Ini); # new My::Hierarchy::Config() called with no args returns a # config opened on the default configuration file. sub new { my ($class,$filename)=@_; return $class-SUPER::new($filename or '/etc/mywebapp.conf'); } -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= And then in every script: my $config=new My::Hierarchy::Config; $config-get(['somesection','somekey']); This allows for maximum flexibility: by adding code to My::Hierarchy::Config, you can provide convenience functions to do just about anything that suits your needs (e.g. there could be one to export the whole config file to random variables in all packages). and my startup.pl would have : ### startup.pl WebApp::LoadConfig-run(/etc/mywebapp.conf) [...] Would this be a good idea ? What do you think about? does somebody already use it ? Well, it depends. We find it quite useful to stay in the CGI context for our scripts, since unit tests are much easier with CGI.pm's debugging code. And for that reason, we choose not to specialize mod_perl's environment more than it already is (e.g. $r et al.). We put the above boilerplate in every script, perhaps wrapped in a convenience function (e.g. ``use My::Hierarchy::CGI;''). But if you intend to jump the gap and have a totally ad-hoc structure for your Perl pages (e.g. you use HTML::Mason or something alike), then yes, why not make $config a global variable accessible to all Perl WWW pages ? -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
Re: [BUG] $r-subprocess_env() leaking to %ENV
Can't all these modules (your scripts, The environment leak in my test case was just to make my point clear, not a programmatic example of course mod_ssl, etc) just use the request object and/or Apache notes to communicate? That's exactly what they're there for! I get it now: there is a kind of lost-update (actually, lost-delete) problem because both mod_ssl and mod_perl try to write into the environment, and cleanup in the wrong sequence (update 1-update 2-cleanup 1-cleanup 2). Thank you for helping me pointing it out. At least mod_perl can be told not to mess with the environment: Directory /my/modperl/webroot PerlSetupEnv Off /Directory Well sure, I even tried it but I use CGI.pm from Perl 5.6 and CGI.pm $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'}); CGI.pm [...] CGI.pm # If $meth is not of GET, POST or HEAD, assume we're being debugged offline. And there comes a funny message in my error log telling me to enter name=value pairs on the standard input :-) Your proposition, however righteous, means a lot of work for a lot of people... Or perhaps Apache::Registry::handler should do some tie()ing ? (yuck) In the meantime, I will be cutting the StdEnvVars off from mod_ssl configuration. Thanks again ! -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]
[BUG] $r-subprocess_env() leaking to %ENV
Hello, I found the following behaviour in mod_perl, which is clearly unexpected: I use an Apache that can serve both mod_perl and PHP pages. I run it -X ; first I request the URI for this scriptlet (under mod_perl's Apache::Registry): #!/usr/bin/perl $ENV{LEAKING}=oops; Then I visit a PHP page that contains just phpinfo() - the LEAKING variable is passed to it, I can see it in the HTTP_ENV_VARS. So far, so good - a remanent environment may not be what I want, but it certainly is not a bug. It becomes worse with a module that sets things in the CGI namespace ($r-subprocess_env()), such as mod_ssl : if I request the Perl scriptlet through SSL, all variables in the subprocess_env (HTTPS, SERVER_CERTIFICATE et al., that normally show up as HTTP_SERVER_VARS in phpinfo()) are somehow promoted as environment variables, and become remanent in the server process environment as shown above (i.e. they now appear as HTTP_ENV_VARS for subsequent requests). This seems to happen at the time the first (I didn't test more) request to an Apache::Registry script is made in the life of an httpd : requesting phpinfo() pages beforehand doesn't show any spurious environment data, even through SSL. Using a debugger shows (as expected from %ENV modifications) that the real environment (char **__environ) is modified in both scenari, so this is not due to a bug in PHP. I ended up writing a cleanup handler that restores %ENV to what it was at server startup time, and everything works fine now. Platform: RH 7.1, mod_perl 1.24_01, Apache 1.3.19, PHP 4.0.4pl1. Sorry I cannot investigate any further by myself, because I know next to nothing in XS and mod_perl uses it heavily. I just saw that %ENV is tied by C code, but I hear it is related to tainting and I don't see how this could cause the observed behaviour. -- Tout n'y est pas parfait, mais on y honore certainement les jardiniers Dominique Quatravaux [EMAIL PROTECTED]