Thursday, February 25, 2010

bash vs. -bash

Spent the last two days running around in circles, trying to figure out why this stupid script wouldn't work.  It's one line, and I was testing it from the command line.  Worked fine in a script:

root@dg scripts]# cat foo
#!/bin/bash
ERR="Error from $(basename $0)";echo $ERR
[root@dg scripts]# foo
Error from foo
Failed miserably by itself:

[root@dg scripts]# ERR="Error from $(basename $0)";echo $ERR
basename: invalid option -- b
Try `basename --help' for more information.
Error from

The good folks at Linuxquestions.org were a big help.  Seems that if the file is executed, it'll behave as you think it should:

[root@tolstoy scripts]# cat foo
#! /bin/bash
  echo $0

[root@tolstoy scripts]# foo
/usr/local/scripts/foo

but if it's ever sourced - as your shell might be, after passing through /etc/profile, ~.bash_profile, etc.:

[root@tolstoy scripts]# . foo
-bash

In fact:

[root@tolstoy scripts]# echo $0
-bash

so my basename $0 became basename -bash, and it failed because it didn't know what the -b option is.

Wednesday, February 24, 2010

Cfengine 2 to 3 conversion tool

I've been using Cfengine 2 for a number of years now, and it's a great configuration tool.  They've recently put out version 3, and the changes are... extensive.  As in, Java vs. C++ extensive.

I'm very tentatively trying to move over to 3.  Yesterday, they put a big help up on their website:



Now on line at our Technical Corner is a conversion sampler, that
enables you to perform a limited conversion of portions of configuration
from Cfengine 2 to Cfengine 3. To convert larger samples more
completely, you can arrange professional services with Cfengine AS/Inc.

https://cfengine.com/inside/config_convert
--
Mark Burgess

Wednesday, February 17, 2010

Stupid bash tricks: when is a null string not a null string?

I've done this more than once, and it still seems to me there ought to be an error.

The 'test' command says:

      -n STRING
              the length of STRING is nonzero

       STRING equivalent to -n STRING

       -z STRING
              the length of STRING is zero

 So something like this should work:

$ /home/tim>TEST=""
$ /home/tim>if test -z $TEST; then echo "null"; else echo "not null";fi
null

and it does.   But this should not work:

$ /home/tim>if test -n $TEST; then echo "not null"; else echo "null";fi  
not null

Hang on.  It can't be both!  Let's check out the length:

$ /home/tim>expr length $TEST
expr: syntax error

Huh?  How about feeding it a real string:

$ /home/tim>expr length "" 
0

Here's the problem.   Absent quotes around the $TEST, expr sees this as a command missing a parameter.  So this works just fine:

$ /home/tim>expr length "$TEST"
0

as does this:

$ /home/tim>if test -n "$TEST"; then echo "not null"; else echo "null";fi
null

So sometimes putting quotes around a string variable does make a difference...

Tuesday, February 16, 2010

bad interpreter: Permission denied

So I'm doing the Symantec live update installation on the servers, and they all work - except one.  The only one I really care about, our main server.

It goes about halfway through the install script, and then dies:

[root@dg tmp]# /opt/Symantec/symantec_antivirus/sav liveupdate -u
Command failed: Problem with LiveUpdate.
Check that java directory is in PATH
Unable to perform update 

Crud.

The log's pretty good, though, and it showed which file it failed on:

16-Feb-10 10:24:58 AM Making /tmp/1266333784179/1266333839866/navuphub.dis executable ...
16-Feb-10 10:24:58 AM Running /tmp/1266333784179/1266333839866/navuphub.dis ...
16-Feb-10 10:24:58 AM Error running /tmp/1266333784179/1266333839866/navuphub.dis with reason: java.io.IOException: java.io.IOException: Permission denied. 

Huh?  Permission denied?  I'm running as root! I trace the file down in /tmp, and try to execute it.  The top line says

#!/bin/sh
like it should, so there shouldn't be any problem:

[root@dg 1266333839866]# ./navuphub.dis
-bash: ./navuphub.dis: /bin/sh: bad interpreter: Permission denied

Uh-oh.  So I try executing /bin/sh - it works.  I unlink and link back to it - it's a symbolic link to bash in RHEL.  It still works.  Now I'm getting nervous.

I copy that little .dis file over to ~, and... the file executes.

I slap myself upside the head.  I do a mount -l, and sure enough:

/dev/hda5 on /tmp type ext3 (rw,nodev,noexec) [/tmp]

In a fit of paranoia a few years ago, I made /tmp unable to execute programs.  That's what that 'noexec' parameter in /etc/fstab does - no programs, no scripts. A remount of temp fixed it.

Friday, February 12, 2010

Configuring a local Liveupdate repository with Symantec Endpoint and Linux

Seven or eight years ago, I decided to finally dump all the individual antivirus packages around here and go with a centralized system. I wasn't sure what I wanted, but I knew what I didn't want - Symantec. I knew they were the evil empire.

After going through two different vendors, this year I finally decided to try Symantec Endpoint Protection Small Business Edition, v. 12. I'm a convert. Incredibly lightweight, responsive, and... cost effective. As in, under $15 a seat cost effective. I love it.

Never bothered with their Linux version, even though it was included with my purchase. ClamAV has been doing just fine for us for years, thank you.

Until last month. For some reason - I assume the definition file - ClamAV is now taking forever to make a scan:

Data scanned: 803.16 MB
Data read: 240.92 MB (ratio 3.33:1)
Time: 8035.814 sec (133 m 55 s)

100K a second?  Let's see, to scan our home directory would take... about a week.

So, easy solution - I've got plenty of SEP licences left; it runs on Linux; it's very easy to administer on Windows - I'll just install SEP on my Linux boxes!

Well, as easy as the Windows install/administration was, the Linux install is that complex. First of all, the Linux download is hard to find. Once I had it I wanted to set up a local LiveUpdate server on the Windows box. Easy enough. Then, I had to point the Linux server towards the LiveUpdate server. That's when things got crazy.

The docs say that you should change the server name in /etc/liveupdate.conf, but there are at least two documented ways of doing so. In addition, they changed the port from 8080 to 7070 in the most recent LiveUpdate Administration release. So I got all of that sorted out in the file, ran liveupdate... and nothing happened.

Well, something happened, actually:

Command failed: Failure in pre processing of micro definitions before update.
Unable to perform update

and the /etc/liveupdate.conf file was nulled out.

After a couple of days of back-and-forth with Symantec (Linux? What's that?), I finally found someone who gave me this link:

http://service1.symantec.com/SUPPORT/ent-security.nsf/docid/2008050713154648


Cause:
Once executed, JLU reads the contents of the unencrypted liveupdate.conf file, runs LiveUpdate, and then encrypts the liveupdate.conf file to prevent tampering. The encryption level used is above the maximum encryption level allowed by default in Sun Java. JLU requires the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files be applied to the version of Java being used to execute JLU.


Solution:
To allow JLU to properly encrypt the liveupdate.conf file, you must apply the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files to the installation of Java being used to execute JLU.

Ah.  I need super-secret crypto, available only to true believers.  So I went to Sun, eventually found the
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files, downloaded them and replaced the on my system.  It consists of two files, local_policy.jar and US_export_policy.jar.  Replaced the files on my system with those, made a mental note not to ever let these machines leave the country, and...

Still didn't work.  Crud.

OK, one more tech request.  They sent me to this link on 'Configuring JavaLiveUpdate':

http://service1.symantec.com/support/ent-security.nsf/docid/2006021007250213

which was wrong in an interesting way.  The table it's got is off by one row - the 'Parameter' column lines up with the 'Description' of the row above it.

But it did give me a hint - it pointed me to a Liveupdt.hst file.  I'd seen this before on the Windows side; the LiveUpdate Administration docs told me how to generate this file, but not what to do with it.  This seemed to imply that I pointed 'hostfile=' to it.  So I generated it on the Windows side (Configure/Client Settings/Export Java Settings), moved it over, and put it into my /etc/liveupdate.conf file, which now reads:

hostfile=/opt/Symantec/symantec_antivirus/liveupdt.hst
logfile=/var/log/symantec/liveupdt.log

Hah!  That worked!

And it's slightly faster.  That 133-minute clamav scan finished in just under 8 minutes.

Sheesh.  But worth it, I think.

Tuesday, February 9, 2010

Samba 0-day

Samba has announced a 0-day exploit that's caused the computing world to sit up and... yawn. Details here: http://www.samba.org/samba/news/symlink_attack.html

I think SANS says it best:

"When is a 0day not a 0day? When the exploit ends up being just a poor default configuration issue. It can lead to files being read, that the user has permission to read."

So what we have here is an exploit that allows users to read files that... they have permission to read. No privilege escalation.

Yawn. If this really bothers you, add

[global]
wide links = no

to your smb.conf file, and restart. Of course, this will break allowing symlinks in an exported share.

Monday, February 8, 2010

Windows 2008 NTP problem?

I've got a Windows 2008 R2 server sitting as a guest on our RHEL 5.4 server.  I just happened to notice that the time was off.  Way off, like about six minutes.

The w32tm.exe utility has some interesting switches.  I used one to stripchart against the main time server:

C:\Users\Administrator>w32tm /stripchart /computer:buran
Tracking buran [192.168.1.200:123].
The current time is 2/8/2010 12:12:44 PM
12:12:44 d:+00.0077832s o:+416.5745527s
12:12:46 d:+00.0029019s o:+417.0718254s
12:12:48 d:+00.0019183s o:+417.5564322s
12:12:51 d:+00.0019141s o:+418.0448887s
12:12:53 d:+00.0019232s o:+418.5206214s
12:12:55 d:+00.0019154s o:+419.0251265s
12:12:57 d:+00.0019209s o:+419.5642993s
12:12:59 d:+00.0019262s o:+420.0780252s
12:13:01 d:+00.0019133s o:+420.5655424s
12:13:03 d:+00.0019161s o:+421.0448077s
12:13:05 d:+00.0028745s o:+421.5292839s
12:13:07 d:+00.0019101s o:+422.0110611s

Wow.  I'm losing a second every four seconds.  Not good.

I've got w32time set up in NTP mode on the Windows server, so I'm not quite sure what's going on here.  Until I figure it out, I'm going to set the system up to resync time once a minute.  That'll at least keep me within 15 seconds of reality.  Change

HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config\TimProviders\NTPClient\SpecialPollIntercval

to 60, and start/stop w32time

C:\Users\Administrator>w32tm /stripchart /computer:buran
Tracking buran [192.168.1.200:123].
The current time is 2/8/2010 12:26:40
12:26:40 d:+00.0048590s o:+09.2796603s
12:26:42 d:+00.0009300s o:+09.8433852s
12:26:44 d:+00.0019293s o:+10.4054516s
12:26:46 d:+00.0019263s o:+10.9600696s
12:26:48 d:+00.0019241s o:+11.4967021s
12:26:50 d:+00.0019256s o:+12.0280363s
12:26:52 d:+00.0019269s o:+12.5750087s
12:26:54 d:+00.0019231s o:+13.1260536s
12:26:56 d:+00.0019243s o:+13.6663052s
12:26:58 d:+00.0018872s o:+14.2191757s
12:27:15 d:+00.0009443s o:+00.1400540s
12:27:17 d:+00.0019228s o:+00.6581759s

Better.  Not perfect, but better, and the network will be able to handle an NTP request every minute.  Now, all I have to do is find out what's wrong...