OpenSolaris vs Solaris

This weekend I went to install the new Communications Suite with Convergence and I decieded to install OpenSolaris 2008.5 on my machine and put the Comms Suite in a zone on it (so I could easily blow it away after my testing was done..)

Let me be probably not the first to say that OpenSolaris != Solaris.. I have been using Solaris 10 since it was in beta, and OpenSolaris through me for a couple of loops…

First are some of the cool things I liked:

1. The interface, it is updated and seemed a lot faster.

2. The ease of “patching” only took about half an hour to do a pkg image update.

3. Zfs root made it easy to roll back changes..

Now the parts that i had problems with and did not like too well.

1. I had to download a driver for my ethernet card as the one Sun delivers (sk98sol) is still too old and did not support my card which is one built on to a 3+ year old motherboard.

2. To create a zone, you MUST have a network connection (and at least to the internet for the time being). This really made me mad as I sometimes don’t have access to the Internet, and if I need to create a zone, I don’t want to have to wait for it to download 200+ Mb of packages, that are already on the machine in the first place.

3. No more “full root zones”, I created a zone in the hopes of installing the Comms Suite in it, only to find out that it was not a full root zone and stuff that is required by the Comms Installer to be there wasn’t and therefor I could not install it… Such simple things like unzip and perl are missing from the newly created zone.

In the end, I ended up reinstalling the box with Solaris 10 05/08, which was a task in itself. See when you install OpenSolaris it makes the root drive zfs, and did  some weird things to the VTOC. Therefore when I went in to do the install of the “older” Solaris 10 05/08, the installer would show me the disk, let me “carve” it up like I wanted in the gui and via command line, but when the install went to go on, the installer always came back saying that there was not enough disk to install Solaris. What I ended up having to do was go and do a “format -e” and then fdisk and delete the Solaris partition that was made by OpenSolaris, and let the Solaris installer create it’s own fdisk partition again.

So after finally getting Solaris 10 installed and the latest Recommended/Security/Sun Alert patches put on, I called it a night and left the Comms install for next weekend.

Overall I think OpenSolaris is going in the right direction, but there needs to be a lot of things fixed in it.. The biggest is the zones, there should be an option for “cloning” the already installed OS, since it is already on a ZFS pool. The second is that there should be an option when creating the zone as to what kind of zone it should be, whether a full (which would load every package, so you don’t have to try and do it  your self), sparse or maybe a new one called Jail which has everything in it read only.

Decoding Sun Fire 25K IO boat locations

Here is how to decode the Sun Fire E25K IO Boat locations. This is useful if you are trying to jumpstart a domain that has multiple ethernet cards in it. (Note even if you only have 1 physical card, there are other “ethernet” devices on the back side for the MAN and I2 networks).

So lets take this example. Here is the out put of show-nets from a domain.

{80} ok show-nets
a) /pci@bd,700000/network@1
b) /pci@bc,700000/network@3,1
c) /pci@bc,700000/pci@1/network@1
d) /pci@bc,700000/pci@1/network@0
e) /pci@9d,700000/network@1
f) /pci@9c,700000/network@3,1
g) /pci@9c,700000/pci@1/network@1
h) /pci@9c,700000/pci@1/network@0

The first step is to convert the hexadecimal agent id into binary. The agent id in the above example (line h for reference) is 9c. So 9c in binary is 00 1001 1100. The last 5 bits identify the IOC chip. A value of 0x1c is IOC0, whereas 0x1d is IOC1. So in the above, the last 5 bits is 11100 = 1c. The remaining first 5 bits of the agent id converted from binary to decimal will tell you the expander board. So 00 100 = 4 in decimal. So from this we can tell that the network card is in Expander 4 and IOC 0.

Next is to identify the bus, that is the part after the , in the above example they are all 700000, which is bus B. Whereas 600000 is bus A.

Bus A is the 33/66-MHz, where as Bus B is the 33MHz.

So as you are looking at an IO expander the B bus is the top 2 slots, and the A bus is the bottom 2 slots. The IO bridge 0 is the right and the IO bridge 1 is the left side.

So in our example this Card is in the Top Right slot of the IO boat in expander board 4. Next since this card has 2 ports, you will see a network@0, and network@1. Which correspond to the port 0 and 1 on the card (which happens to be a dual port ethernet/scsi card).

Now that I have explained how it works, here is a quick cheat sheet:

Device Agent ID Expander board
1c 0
3c 1
5c 2
7c 3
9c 4
bc 5
dc 6
fc 7
11c 8
13c 9
15c 10
17c 11
19c 12
1bc 13
1dc 14
1fc 15
21c 16
23c 17

Why everyone should use bart (AKA do the Bart Man)

If you are using Solaris 10, and you have not used bart yet, you should stop everything and take a look at it.

For those who don’t know what bart is, it is the Basic Auditing and Reporting Tool that is in Solaris 10.

In a quick synopsis bart will create a report that shows all files/directories on a solaris machine. This report contains the permissions, owners, sizes, modify times and md5 hashes of all files on the system, along with acl’s if you are using ZFS.

So why is bart so important? First, it can be used as a security tool. When you install a new Solaris 10 system, the first thing you should do after you get it installed and patched and before it is placed on the network is run a bart on the system and save the report to a cd. This will be the “baseline” image of the system. Then every week/month you should run a bart against the machine again and then use the compare option to see what files have changed, added or deleted from the system. Where this comes in really handy is if your think that your machine has been hacked or compromised. You can use the comparison to determine which files may have been modified by the hacker.

But there is a non-security use for bart as well that is VERY useful. This use is one that I had not thought of until I needed it the other day. So what is this use? Reseting the permissions on files that were accidentally changed by an in-experienced UNIX person thinking that a “chmod -R 777 *” is the best way to fix their problems.

The first thing that came to my mind when I saw this happen was oh no, the machine had not even been backed up yet, and a day’s worth of work would have been lost. Even if the machine had been backed up, do you realize how long it would take to restore a file system with 40,000+ files, just because the permissions were screwed up. ( Note, the permissions on the various files were very different and even included some setuid, and setgiud files which were wiped out as well.)

So how did bart save the day? Luckly I had taken a bart of the machine before the work had begun on the file system. So after the chmod command was issued, I then took a bart of the file system again. I now could run a bart compare against the control and test manifest and see exactly what all had changed.

Once I had this output, I could then create a script to change the permissions of the files/directories back to the original values. All told after I finished tweaking my script it took about 20 minutes to reset the permissions on all the files and directories.

So here is a quick start to getting your first bart manifest of your system:

1. Create a bart_rules file. If you do not create a rules file, your output will only have Files and not directories listed in it. My simple bart_rules file looks like this:

/
CHECK ALL
/home
IGNORE ALL

I ignore the /home file system as in my case it was nfs mounted. In reality you would want to include all local file systems.

2. Create the bart, I keep the rules file in /root/bart_rules so I would run the command:

bart create -R / -r /root/bart_rules > /tmp/bart.output

This will create a bart manifest and output it to /tmp/bart.output. Looking at the first couple of lines of it looks like this:

unixwiz@sungeek:/home/unixwiz> head -20 /tmp/bart.out
! Version 1.0
! Saturday, May 17, 2008 (21:24:27)
# Format:
#fname D size mode acl dirmtime uid gid
#fname P size mode acl mtime uid gid
#fname S size mode acl mtime uid gid
#fname F size mode acl mtime uid gid contents
#fname L size mode acl lnmtime uid gid dest
#fname B size mode acl mtime uid gid devnode
#fname C size mode acl mtime uid gid devnode
/ D 1024 40755 user::rwx,group::r-x,mask:r-x,other:r-x 481d0e43 0 0
/.ICEauthority F 310 100600 user::rw-,group::---,mask:---,other:--- 44c581c2 0 0 3eb63faf448e8a2b2c1a7b2019a8bde3
/.Xauthority F 99 100600 user::rw-,group::---,mask:---,other:--- 44c560e0 0 0 5ffe2e5f4b6f73e662001f62f7cae4d3
/.bash_history F 649 100600 user::rw-,group::---,mask:---,other:--- 481d1109 0 0 9132e0e798d5d05644cafc90c2aa876a
/.dt D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c560e0 0 0
/.dt/appmanager D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534d 0 0
/.dt/help D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534d 0 0
/.dt/icons D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534d 0 0
/.dt/sessionlogs D 512 40755 user::rwx,group::r-x,mask:r-x,other:r-x 44c5534c 0 0
/.dt/sessionlogs/sungeek_DISPLAY=:0 F 132 100644 user::rw-,group::r--,mask:r--,other:r-- 44c560e0 0 0 6d4e62fc972046a7a85fdb36a0ce21fd

The first part of the file, the part that begins with #fname is a legend as to how each type of line is formed.
So looking at the first actual line of the contents :
/ D 1024 40755 user::rwx,group::r-x,mask:r-x,other:r-x 481d0e43 0 0
We see that the fnmae is /, it is a directory, with a size of 1024. Its mode is 755, the last modified time is the “481d0e43” and it is owned by uid 0 and gid 0.

Looking at a file in particular we see this:

/httpd/htdocs/index.html F 10 100644 user::rw-,group::r--,mask:r--,other:r-- 463d4f4b 0 0 b7a9369d4cc9f82ed707bce91ced8af8

In the above, we see that the file is 10 bytes, has a permissions of 644 and is owned by root/root.

Now suppose that I for some reason by accident was in the /httpd/htdocs directory and did a chmod -R 777 *. Since I had my control manifest, I would then run another bart and then use the compare option. What I would get is something like this:

#bart compare /tmp/bart.output /tmp/bart.output2
/httpd/htdocs/index.html:
mode control:100644 test:100777
acl control:user::rw-,group::r--,mask:r--,other:r-- test:user::rwx,group::rwx,mask:rwx,other:rwx

Here we can see that the permissions has changed from 644 to 777. But the output is not really easy to parse with a script. So we need to use the “-p” option on the bart compare:

#bart compare -p /tmp/bart.output /tmp/bart.output2
/httpd/htdocs/index.html mode 100644 100777 acl user::rw-,group::r--,mask:r--,other:r-- user::rwx,group::rwx,mask:rwx,other:rwx

In the above, since the only thing that was changed was the mode, that is the only thing that is listed.

here are some other examples:

/var/samba/locks/browse.dat mtime 482f8544 482f8800
/var/samba/locks/unexpected.tdb contents 7c3404e9622749702e3df56caf26fe72 72983947ada3260a236394a51aef0d31

The first line shows that the file browse.dat modify time changed, but nothing else. The second line shows that the unexpected.tdb had it’s contents change. This can been see by the 2 different hashes.

Here is another example of the index.html file above, after it had been edited:

bash-3.00# bart compare /tmp/bart.out /tmp/bart.out3
/httpd/htdocs/index.html:
size control:10 test:26
mode control:100644 test:100777
acl control:user::rw-,group::r--,mask:r--,other:r-- test:user::rwx,group::rwx,mask:rwx,other:rwx
mtime control:463d4f4b test:482f8b89
contents control:b7a9369d4cc9f82ed707bce91ced8af8 test:1567caf683e3859cb5da7335c35438f7

Once again this is in the “human” readable format, the “machine” readable looks like :

bash-3.00# bart compare -p /tmp/bart.out /tmp/bart.out3
/httpd/htdocs/index.html size 10 26 mode 100644 100777 acl user::rw-,group::r--,mask:r--,other:r-- user::rwx,group::rwx,mask:rwx,other:rwx mtime 463d4f4b 482f8b89 contents b7a9369d4cc9f82ed707bce91ced8af8 1567caf683e3859cb5da7335c35438f7

(the above is actually all on one line.)

Once you have the output of the bart after the “oops” you will need to run the bart compare with options to ignore some items. Since I am only interested in the mode, the size, mtime and contents can be ignored. I used the following:

bash-3.00# bart compare -i size,mtime,contents,uid,gid -p /tmp/bart.out /tmp/bart.out2

This only shows files that have had their mode changed:

bash-3.00# bart compare -i size,mtime,contents,uid,gid -p /tmp/bart.out /tmp/bart.out2
/httpd/htdocs/index.html mode 100644 100777 acl user::rw-,group::r--,mask:r--,other:r-- user::rwx,group::rwx,mask:rwx,other:rwx

You should redirect this output to a file, so that it can then be used to generate a script.
With the output in a file I then did this:

cat /tmp/bart.compare | awk '{print "chmod "$3" "$1}' > /tmp/CHANGEPERMS

So basicly I cat the file and print the chmod command allong with the 3rd field (100644) and then the first field (/httpd/htdocs/index.html) and redirect this to a new file. Once I spot check this file, you can then run it and it will “reset” the permissions back.

Now everything I have shown above is based on the machine having a UFS file system. If you run bart against a file system that is ZFS, you will get a manifest that looks something like this:


/home/unixwiz/bin/php F 10587732 100755 owner@::deny,owner@:read_data/write_data/append_data/write_xattr/execute/write_attributes/write_acl/write_owner:allow,group@:write_data/append_data:deny,group@:read_data/execute:allow,everyone@:write_data/append_data/write_xattr/write_attributes/write_acl/write_owner:deny,everyone@:read_data/read_xattr/execute/read_attributes/read_acl/synchronize:allow 4743a7fa 100 14 9b8cfb15ed069bd6e43d7c2ae11a3e23

It shows the ZFS extended acl’s.

So if you haven’t started using bart, you should start as soon as possible.

How to calculate yesterday

I was working on a shell script last night and needed to calculate the value for yesterday. I did not have access to GNU date, so using that is out of the question. All I could use was what was available to me in a default install of Solaris 10. So I decided to use Perl as such (note that the YESTERDAY should all be on one line):


#!/bin/bash
YESTERDAY=$(perl -e '@y=localtime(time()-86400);
printf "%04d%02d%02d",$y[5]+1900,$y[4]+1,$y[3];$y[3];')

What this will do is store the value of yesterday in a shell variable called YESTERDAY
Now I have not done perl in a long while so here is an explanation of what it does:
1. Runs the perl function time which will find the current time, then subtract 86400 from it (24 hours).
2. Next it is run through the localtime function which creates an array that has the following values:

Array Element Value
0 Seconds
1 Minutes
2 Hour
3 Day of Month
4 Month of year (0=January)
5 Year (starting at 1900)
6 Day of week (0=sunday)
7 Day of Year (0..364 or 0..365 if leap)
8 Is Daylight savings time active

So in my little script above, we are looking for fields 5, 4 and 3. I add 1900 to the value of 5 (in this case 5 = 108). I add 1 to the value of 4 to get the current month (3+1 = 4 = April). The values are then pushed through printf so that we have a 4 digit year with leading 0’s, a 2 digit month with leading 0’s and a 2 digit day with leading 0’s. So the value of my YESTERDAY variable will now show 20080418.

Hope this helps some one else.