Re: Parsing Login Scripts
by jasonk (Parson) on Dec 08, 2003 at 21:37 UTC
|
This is going to be a much harder problem than you anticipate. As an example, my .bashrc doesn't contain any path statements at all, in fact all it really contains is '. $HOME/.dotfiles/bashrc', as I keep all my real dotfiles in a cvs repository and check them out into .dotfiles on each machine I work on.
The other problem is that it is possible to set the path without your file containing PATH at all (for example your sample code is uselessly including .tcshrc and .cshrc, where the path statements are in lower case).
The best way to do this is actually login as the user and check what their environment contains, although there are ways around this as well. (how would your code deal with: eval 'echo RATH="RATH:." | sed s/R/P/g'?) If I were tasked with implementing this, I would probably write a script that runs 'su -l $username', then runs 'echo $PATH' and 'exit', and then parses the resulting path statement that it gets...
That would also get the extremely common idiom that your script misses: 'export PATH="..."'.
| We're not surrounded, we're in a target-rich environment! |
|---|
| [reply] [d/l] |
Re: Parsing Login Scripts For Variable Assignment
by holo (Monk) on Dec 08, 2003 at 21:38 UTC
|
FOO=.
PATH=$FOO:~/bin
export PATH
There are various other workarounds.
Update: Some are even stealthy and don't even mention PATH at all:
eval `perl -e'print"y~ozf"^"]....=."'`
Update 2: What you could do is add this line to /etc/login.defs:
FAKE_SHELL /usr/bin/fakeshell
The script should call echo "command $$" | at 1 minute and then exec a shell. The "command" should then access /proc/"$$"/environ, locate PATH=... and do a simple split and test for a "." or "./". I assume you're on a linux box. | [reply] [d/l] [select] |
Re: Parsing Login Scripts For Variable Assignment
by Corion (Patriarch) on Dec 08, 2003 at 21:41 UTC
|
Luckily, with this method you'll never get my way of putting '.' into my $ENV{PATH}:
source '~/.dot_path'
where ~/.dot_path contains mostly
PATH=${PATH}:.
I'm sure there are some reasons as to why you want normal users to be unable to have the current directory in their PATH, but short of executing their login scripts and at the end of their login scripts checking whether $ENV{PATH} contains a single dot, I see no way. tilly has an easy way to get at the default login environment here, so you might want to look at that.
perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The
$d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider
($c = $d->accept())->get_request(); $c->send_response( new #in the
HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
| [reply] [d/l] [select] |
Re: Parsing Login Scripts For Variable Assignment
by waswas-fng (Curate) on Dec 08, 2003 at 22:49 UTC
|
Not perl but if you are running linux or a bsd, you can compile the shells to disallow the . in path. I think trusted solaris shell kits have this option too.
| [reply] |
|
|
the Mandatory Access Controls not only allow only programs known to be installed by somone with that clearance to be run, but also would restrict the access of '.' for execution because the other permissions that would need to be on the object.
Besides this, I use esh, scsh, zsh and rc! where is parsing for the _alternative_ shells! =)
| [reply] |
|
|
I don't think L~R is able to say where he works but I am pretty sure he has no obligation or ability to support or allow any shells that are not standard. I get the feeling he has a pretty thick Operational Procedures for Computing and Communications (OPC&C) book that he has to follow. Although I could be wrong.
| [reply] |
Re: Parsing Login Scripts For Variable Assignment
by Paladin (Vicar) on Dec 08, 2003 at 21:42 UTC
|
You can clean up your parsing of continuation lines a bit with something like the following:
LINE: while (<LOGIN>) {
chomp;
if (s!\\$!!) {
$_ .= <LOGIN>;
redo LINE;
}
# At this point, we have gathered all the continuation lines into
+1 line.
# Now do the rest of the processing.
next unless /PATH/;
# here you have your PATH line, and can do whatever you need with
+it.
}
But, as jasonk, holo and Corion have noted, this isn't the biggest problem. | [reply] [d/l] |
|
|
Paladin,
Thanks! I still think it looks ugly, but with your suggestion I was able to do away with some code. Here is the modified code:
my $path;
while ( <LOGIN> ) {
chomp;
if ( s|\\$|| ) {
$_ .= <LOGIN>;
redo;
}
if ( /^\s*(export)?\s+PATH=(.*)/ ) {
$path .= ':' if $path && substr($path, -1, 1) ne ':';
$path .= $2;
}
}
Cheers - L~R | [reply] [d/l] |
Re: Parsing Login Scripts For Variable Assignment
by etcshadow (Priest) on Dec 08, 2003 at 22:04 UTC
|
Well, reliably "examining" a program like this for its behavior is tantamount to solving the halting problem (read: impossible).
Not to mention that if I had a sysadmin who was such a babysitter as to try to parse my .profile for environment vars deemed "unsuitable", I'd probably start screwing wiht 'em just for the sake of pissing them off.
Maybe a better way of dealing with it is to validate that everyone's profiles' last line is something like:
source /etc/cleanup_profile
which, itself, just parsed PATH, and pulled out "." if it was there.
Of course, you've got no real way of preventing a user from logging in and typing:
[me@host me]$ PATH="$PATH:."
[me@host me]$
------------
:Wq
Not an editor command: Wq
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
[root@host /]# cat > ~me/sl <<EOF
rm -rf ~me
EOF
Trial by fire... of course, nice sysadmins would back their home directory up first. ;-)
Disclaimer: don't try this at home kids! Playing with rm without adult supervision is dangerous.
Cheers, -- Dave :-)
$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
| [reply] [d/l] [select] |
Re: Parsing Login Scripts For Variable Assignment
by etcshadow (Priest) on Dec 10, 2003 at 05:00 UTC
|
Here's another approach: Don't try to parse the .rc and .profile files of the users, just scan their process's environments!
#!/usr/bin/perl
use strict;
$/ = "\0";
opendir PROC,"/proc" or die "cannot open /proc for read: $!\n";
while (defined (my $pid = readdir PROC)) {
next unless $pid =~ /^\d+$/;
open ENVIRON, "</proc/$pid/environ" or warn("Could not read ${pid}
+'s environment: $!\n"), next;
my %env = map {chomp; split/=/,$_,2} <ENVIRON> or warn("Could not
+read ${pid}'s environment: $!\n"), next;
close ENVIRON;
print "UID ".((stat "/proc/$pid")[4])." is a violator! (pid $pid)\
+n" if grep /^\.$/, split /:/, $ENV{PATH};
}
closedir PROC;
Cron that and email yourself the output.
------------
:Wq
Not an editor command: Wq
| [reply] [d/l] |