Protecting Critical Infrastructure: Process Control and SCADA

  Windows IT Pro
Windows IT Library
  - Advertise        
Windows IT Pro Logo

  Home  |   Books  |   Chapters  |   Topics  |   Authors  |   Book Reviews  |   Whitepapers  |   About Us  |   Contact Us  |   ITTV  |   IT Jobs

search for  on    power search   help
 






Protecting Critical Infrastructure: Process Control and SCADA
View the book table of contents
Author: Craig Schiller
Published: November 2007
Copyright: 2007
Publisher: Syngress Publishing
 


Mounting Disk Images
Memory disks can also be used to mount and access disk images. This is most useful for viewing the contents of CD images without burning them to disk. Just attach a memory disk to a file with the mdconfig(8) command’s -a flag. Here, I attach a FreeBSD ISO to a memory device:



We tell mdconfig(8) to attach a vnode-backed memory device to the file specified . mdconfig(8) responds by telling us the device. it’s attached to. Now we just mount the device with the proper mount command for the filesystem:
# mount -t cd9660 /dev/md0 /mnt 
One common mistake people make at this point is mounting the image without specifying the filesystem type. You might get an error, or you might get a successful mount that contains no data—by default, mount(8) assumes that the filesystem is FFS!

When you’re done accessing the data, be sure to unmount the image and destroy the memory disk device just as you would for any other memory device. While vnode-backed memory disks do not consume system memory, leaving unused memory devices around will confuse you months later when you wonder why they appear in /dev. If you’re not sure what memory devices a system has, use mdconfig -l to view all configured md(5) devices.
# mdconfig -l 
md0 md1 
I have two memory devices? Add the -u flag and the device number to see what type of memory device it is. Let’s see what memory device 1 (/dev/md1) is:
# mdconfig -l -u 1 
md1 vnode 456M /slice1/usr/home/mwlucas/iso/omsa-51-live.iso 
I have an ISO image mounted on this system? Wow. I should probably reboot some month. Nah, thats too much work, I’ll just unmount the filesystem.

Filesystems in Files

One trick used for jails (see Chapter 9) and homebrew embedded systems (see Chapter 20) is building complete filesystem images on a local filesystem. In the previous section, we saw how we could use memory disks to mount and access CD disk images. You can use the same techniques to create, update, and access FFS disk images. The downside of this is that each image takes up an amount of disk space equal to the size of the disk image. If you create a 500MB disk image, it takes up a full 500MB of space.

To use a filesystem in a file, you must create a file of the proper size, attach the file to a memory device, place a filesystem on the device, and mount the device.

Creating an Empty Filesystem File s
The filesystem file doesn’t initially contain any data; rather, it’s just a file of the correct size for the desired filesystem. You could sit down and type a whole bunch of zeroes to create the file, but FreeBSD provides a unlimited source of nothing to save you the trouble. The /dev/zero device is chock full of emptiness you can use to fill the file.

Use the same dd(1) command you used to copy the installation floppy images to your filesystem file. Here we copy data from /dev/zero and to the file filesystem.file:



We take our data from the input file /dev/zero and dump it to the output file filesystem.file . Each transfer occurs in blocks of 1K , and we do this one million times . This takes a few seconds to complete, but as /dev/zero doesn’t have to generate the next character, the file fills quickly . If you look in your current directory, you now have a 1GB file called filesystem.file.

One common source of confusion with dd(1) is the block size and count. Calculating the final size of a file with dd(1) is like moving a pile of sand; you break the job into loads and move a number of those loads. You can use several loads with a wheelbarrow, many loads with a bucket, or lots and lots of loads with a spoon. The size of each load is the block size, and the number of trips is the count. Perhaps you’re using your bare hands, which would correspond to a small block size and a high count. Maybe you have a wheelbarrow, for a medium block size and a moderate count. Perhaps you have a steam shovel and can do the whole job in one scoop. The larger the block size, the more load you put on the system with each block. dd(1) recognizes a variety of abbreviations for increasing block size and count, as shown in Table 8-2.

Suppose you want a 1GB file. Remember that 1k is actually one kilobyte. One megabyte is a thousand kilobytes, and one gigabyte is one thousand megabytes. If you use a block size of 1 byte, and a count of one gig, you’re asking your system to make 1,073,741,824 trips to the sand pile. Each trip is very easy, but there’s an awful lot of them! On the other hand, if you select a block size of one gig and a count of 1, you’re asking the system to pick up the whole pile at once. It will not be pleased. Neither will you. Generally speaking, a block size of 1m and a lower count produces reasonably quick results without overburdening your system. When you use a 1m block, the count equals the number of megabytes in the file. A count of 1k creates a 1GB filesystem, a count of 2k creates a 2GB filesystem, a count of 32 creates a 32MB filesystem, and so on.

Creating the Filesystem on the File
To get a filesystem on the file, you must first associate the file with a device with a vnode-backed memory disks. We did exactly this in the last section:
# mdconfig -a -t vnode -f filesystem.file 
md0
Now, let’s make a filesystem on this device. This is much like creating an FFS filesystem on a floppy disk with the newfs(8) command. We specify the -U flag to enable soft updates on this filesystem, as soft updates are useful on file-backed filesystems.
# newfs -U /dev/md0 
/dev/md0: 1024.0MB (2097152 sectors) block size 16384, fragment size 2048 
        using 6 cylinder groups of 183.77MB, 11761 blks, 23552 inodes. 
        with soft updates 
super-block backups (for fsck -b #) at: 
160, 376512, 752864, 1129216, 1505568, 1881920 
newfs(8) prints out basic information about the disk such as its size, block and fragment sizes, and the inode count.

Now that you have a filesystem, mount it:
# mount /dev/md0 /mnt 
Congratulations! You now have a 1GB file-backed filesystem. Copy files to it, dump it to tape, or use it in any way you would use any other filesystem. But in addition to that, you can move it just like any other file. We’ll make use of this when we talk about jails in the next chapter, and it’s a vital technique for building your own embedded systems.

File-Backed Filesystems and /etc/fstab
You can mount a file-backed filesystem automatically at boot with the proper entry in /etc/fstab, much like you can automatically mount any other memory disk. You simply have to specify the name of the file with -F, and use -P to tell the system to not create a new filesystem on this file but just to use the one already there. Here we mount the file-backed filesystem we created on /mnt automatically at boot time. (I told you we’d see /etc/fstab entries uglier than the one we created for generic memory disks, didn’t I?)
md    /mnt    mfs    rw,-P,-F/home/mwlucas/filesystem.file   0    0 
Miscellaneous Filesystems

FreeBSD supports several lesser-known filesystems. Most of them are useful only in bizarre circumstances, but bizarre circumstances arise daily in system administration.

devfs(5) is the device filesystem used for /dev. You cannot store normal files on a devfs filesystem; it only supports device nodes. The kernel and the device filesystem daemon devd(8) directly manage the contents of a device filesystem.

procfs(5) is the process filesystem; it contains lots of information about processes. It’s considered a security risk and is officially deprecated on modern FreeBSD releases. You can learn a lot about processes from a mounted process filesystem, however. A few older applications still require a process filesystem mounted on /proc; if a server application requires procfs, try to find a similar application that does the job without requiring it.

If you’re using Linux mode (see Chapter 12), you might need the Linux process filesystem linprocfs(5). Much Linux software requires a process filesystem, and FreeBSD suggests installing linprocfs at /compat/linux/proc when you install Linux mode. I’d recommend only installing linprocfs if a piece of software complains it’s not there.

fdescfs(5), the file descriptor filesystem, offers a filesystem view of file descriptors for each process. Some software is written to require fdescfs(5). It’s less of a security risk than procfs, but still undesirable.


WIRING DOWN DEVICES

SCSI disks don’t always power up in the same order, but FreeBSD numbers SCSI drives in the order that they appear on the SCSI bus. As such, if you change the devices on your SCSI bus, you change the order in which they’re probed. What was disk 0 when you installed FreeBSD could become disk 1 after you add a new disk drive. This change would cause partitions to be mounted on the wrong mount points, possibly resulting in data damage. You can have similar problems with SCSI buses—if you add another SCSI interface, your buses can be renumbered! What was /dev/da0 when you installed FreeBSD could become /dev/da1 or even /dev/da17 after you add a new tape drive. This causes FreeBSD to mount partitions on the wrong mount points.

To prevent this problem, you can hard-code disk numbering into the kernel, a process called wiring down the SCSI devices. To wire down the device you need the SCSI ID, SCSI bus number, and LUN (if used) of each device on your SCSI chain, available in /var/run/dmesg.boot. For example, on a test system I have the following dmesg entries for my SCSI adapter:
ahc0: <Adaptec 2940B Ultra2 SCSI adapter> port 0xe000-0xe0ff mem 0xe80420000xe8042fff 
irq 11 at device 20.0 on pci0 
aic7890/91: Ultra2 Wide Channel A, SCSI Id=7, 32/253 SCBs 
The first line shows that the main SCSI card is an Adaptec 2940B Ultra2 adapter. The second line gives us more information about the chipset on this card. This is really only one physical card. The host adapter is using SCSI ID 7, and no LUN.

A little later in dmesg.boot I have entries for all SCSI disks. While these entries include things such as disk capacity, model, speed, and features, the first line for each disk looks much like these:



This tells us that the disk da0 is on SCSI card ahc0 , on SCSI bus 0 , at SCSI ID 8 , at LUN 0 . Disk da1 is on the same card and bus, at SCSI ID 9 .

To wire down a drive, tell the kernel exactly what SCSI bus number to attach to which SCSI card, and then the SCSI ID and LUN of each disk. Do this with kernel hints in /boot/device.hints:


Here, we’ve told FreeBSD to attach SCSI bus number 0 to card ahc0 . Disk da0 is attached to SCSI bus 0 at SCSI ID 8 , and disk da1 is attached to the same bus at SCSI ID 9 . On your next reboot the drives will be numbered as you configured. If you add another SCSI card, or more SCSI hard drives, FreeBSD configures the new drives and buses with unit numbers other than those you’ve reserved for these devices. You can also use lun hints if you have targets with multiple LUNs.


ADDING NEW HARD DISKS

Before you can use a new hard drive, you must slice it, create filesystems, mount those filesystems, and move data to them. While FreeBSD has command-line tools that can handle all this for you, the simplest and fastest way is with sysinstall(8). We’ll assume that you are adding disks to an existing system, and that your eventual goal is to move a part of your data to this disk.

BACK UP, BACK UP, BACK UP!

Before doing anything with disks, be sure that you have a complete backup. A single dumb fat-finger mistake in this process can destroy your system! Whie you rarely plan to reformat your root filesystem, if it happens you want to recover really, really quickly.

Creating Slices

Your first task in preparing your new hard disk is to create a slice and partition it. Follow these steps:
  1. Become root and start sysinstall(8). Choose Configure, and then Disk.


  2. This menu should look somewhat familiar; you used it when you installed FreeBSD. (You can see screenshots in Figure 2-4 in Chapter 2.) You’ll see your existing FreeBSD disks and your new disk. Choose the new disk.


  3. If this disk is recycled from another server, you might find that it has a filesystem on it. It’s usually simplest to remove the existing partitions and start over. Use the arrow keys to move to any existing partitions, and press D to delete them.


  4. Either create a slice by pressing C, or just use the whole disk by pressing A. In a server, you almost certainly want to use the entire disk. When you’ve chosen your slices, make the changes effective immediately by pressing W. You’ll see a warning like this:
    WARNING: This should only be used when modifying an EXISTING installation. If you are installing FreeBSD for the first time then you should simply type Q when you're finished here and your changes will be committed in one batch automatically at the end of these questions. If you're adding a disk, you should NOT write from this screen, you should do it from the label editor.
  5. Are you absolutely sure you want to do this now?


  6. Yes, you’re absolutely sure. Tab over to Yes and hit ENTER.


  7. You’ll then be asked if you want to install a boot manager on this disk. Additional disks don’t need boot managers, so arrow down to Standard and press the spacebar. The sysinstall program tells you that it has written out the fdisk information successfully. You now have a FreeBSD slice on the disk. Hit Q to leave the fdisk part of sysinstall.
Creating Partitions

To create partitions on your disk, follow these steps:
  1. Choose the Label option of sysinstall(8), on the same submenu as FDISK. Select your new disk to reach the disklabel editor. Here you can create a new partition with the C command, specifying its size in either megabytes, gigabytes, disk blocks, or disk cylinders. You can also decide if each new partition will be a filesystem or swap space. When you’re asked for a mount point, use /mnt for the moment. Sysinstall temporarily mounts the new partition at that location.


  2. When the disk is partitioned as you need, press W to commit the changes. You’ll get the same warning you saw in the fdisk menu, and then messages from newfs(8).
Once newfs(8) finishes, exit sysinstall.

Configuring /etc/fstab

Now tell etc/fstab about your new disks. The configuration differs depending on whether the new partition is a filesystem or swap space. Every swap space entry in etc/fstab looks like this:
devicename     none     swap     sw     0     0 
If your new swap partition is /dev/da10s1b, you would add this line to etc/fstab:
/dev/da10s1b     none     swap     sw     0     0 
Upon your next reboot, FreeBSD will recognize this swap space. You can also use swapon -a devicename to activate new swap without rebooting.

If you created a data partition, add a new entry as described earlier in this chapter, much like this:
/dev/da10s1d     /usr/obj     ufs     rw     2     2 
Now you can just unmount the new partition from its temporary location, run mount /usr/obj, and your new disk is ready for files.

Installing Existing Files onto New Disks

Chances are that you intend your new disk to replace or subdivide an existing partition. You’ll need to mount your new partition on a temporary mount point, move files to the new disk, then remount the partition at the desired location. In our example above, we’ve mounted our new partition on /mnt. Now you just need to move the files from their current location to the new disk without changing their permissions. This is fairly simple with tar(1). You can simply tar up your existing data to a tape or a file and untar it in the new location, but that’s kind of clumsy. You can concatenate tar commands to avoid that middle step, however.
# tar cfC - /old/directory . | tar xpfC - /tempmount 
If you don’t speak Unix at parties, this looks fairly stunning. Let’s dismantle it. First, we go to the old directory and tar up everything. Then pipe the output to a second command, which extracts the backup in the new directory. When this command finishes, your files are installed on their new disk. For example, to move em/usr/src/em onto a new partition temporarily mounted at /mnt, you would do this:
# tar cfC - /usr/src . | tar xpfC - /mnt 
Check the temporary mount point to be sure that your files are actually there. Once you’re confident that the files are properly moved, remove the files from the old directory and mount the disk in the new location. For example, after duplicating your files from /usr/src, you would run:
# rm -rf /usr/src/* 
# umount /mnt 
# mount /usr/src 
MOVING LIVE FILES

You cannot safely move fies that are changing as you copy. For example, if you’re moving your email spool to a new partition, you must shut down your mail server first. Otherwise, files change as you’re trying to copy them. Tools such as rsync/usr/ ports/net/rsync can hep reduce outage duration, but an interruption is still necessary.

Stackable Mounts

Suppose you don’t care about your old data; you simply want to split an existing disk to get more space and you plan to recover your data from backup. Fair enough. All FreeBSD filesystems are stackable. This is an advanced idea that’s not terribly useful in day-to-day system administration, but it can bite you when you try to split one partition into two.

Suppose, for example, that you have data in /usr/src. See how much space is used on your disk, and then mount a new empty partition on /usr/src. If you look in the directory afterwards, you’ll see that it’s empty.

Here’s the problem: The new partition is mounted "above" the old disk, and the old disk still has all that data on it. The old partition has no more free space than before you moved the data. If you unmount the new partition and check the directory again, you’ll see the data miraculously restored! The new mount obscured the lower partition.

Although you cannot see the data, data on the old disk still takes up space. If you’re splitting a disk to gain space, and you just mount a new disk over part of the old, you won’t free any space on your original disk. The moral is: Even if you are restoring your data from backup, make sure that you remove that data from your original disk to recover disk space.


NETWORK FILESYSTEMS

A network filesystem allows accessing files on another machine over the network. The two most commonly used network filesystems are the original Network File System (NFS) implemented in Unix, and the CIFS (aka SMB) filesystem popularized by Microsoft Windows. We’ll touch on both of these, but start with the old Unix standard of NFS.

Sharing directories and partitions between Unix-like systems is perhaps the simplest Network File System you’ll find. FreeBSD supports the Unix standard Network File System out of the box. Configuring NFS intimidates many junior system administrators, but after setting up a file share or two you’ll find it not so terribly difficult.

Each NFS connection uses a client-server model. One computer is the server; it offers filesystems to other computers. This is called NFS exporting, and the filesystems offered are called exports. The clients can mount server exports in a manner almost identical to that used to mount local filesystems.

One interesting thing about NFS is its statelessness. NFS does not keep track of the condition of a connection. You can reboot an NFS server and the client won’t crash. It won’t be able to access files on the server’s export while the server is down, but once it returns, you’ll pick up right where things left off. Other network file sharing systems are not always so resilient. Of course, statelessness also causes problems as well; for example, clients cannot know when a file they currently have open is modified by another client.

NFS INTEROPERABILITY

Every NFS implementation is slightly different. You’ll find minor NFS variations between Solaris, Linux, BSD, and other Unix-like systems. NFS shoud work between them all, but might require the occasional tweak. If you’re having problems with another Unix-like operating system, check the FreeBSD-net mailing list archive; the issue has almost certainly been discussed there.

Both NFS servers and clients require kernel options, but the various NFS commands dynamically load the appropriate kernel modules. FreeBSD’s GENERIC kernel supports NFS, so this isn’t a concern for anyone who doesn’t customize their kernel.

NFS is one of those topics that have entire books written about them. We’re not going to go into the intimate details about NFS, but rather focus on getting basic NFS operations working. If you’re deploying complicated NFS setups, you’ll want to do further research. Even this basic setup lets you accomplish many complicated tasks.

Enabling the NFS Server
Turn on NFS server support with the following rc.conf options. While not all of these options are strictly necessary for all environments, turning them all on provides the broadest range of NFS compatibility and decent out-of-the- box performance.


First, tell FreeBSD to load the nfsserver.ko kernel module, if it’s not already in the kernel. rpcbind(8) maps remote procedure calls (RPC) into local network addresses. Each NFS client asks the server’s rpcbind(8) daemon where it can find a mountd(8) daemon to connect to. mountd(8) listens to high-numbered ports for mount requests from clients. Enabling the NFS server also starts nfsd(8), which handles the actual file request. rpc.lockd(8) ensures smooth file locking operations over NFS, and rpc.statd(8) monitors NFS clients so that the NFS server can free up resources when the host disappears.

While you can start all of these services at the command line, if you’re just learning NFS it’s best to reboot your system after enabling NFS server. Afterwards, you’ll see rpc.lockd, rpc.statd, nfsd, mountd, and rpcbind listed in the output of sockstat(1). If you don’t see all of these daemons listening to the network, check /var/log/messages for errors.

Configuring NFS Exports
Now tell your server what it can share, or export. We could just export all directories and filesystems on the entire server, but any competent security administrator would have a (justified) fit. As with all server configurations, permit as little access as possible while still letting the server fulfill its role. For example, in most environments clients have no need to remotely mount the NFS server’s root filesystem.

Define which clients may mount which filesystems and directories in /etc/exports. This file takes a separate line for each disk device on the server and each client or group of clients that access that device. Each line has up to three parts:
  • Directories or partitions to be exported (mandatory)
  • Options on that export
  • Clients that can connect
Each combination of clients and a disk device can only have one line in the exports file. This means that if /usr/ports and /usr/home are on the same partition, and you want to export both of them to a particular client, they must both appear in the same line. You cannot export /usr/ports and /usr/home to one client with different permissions. You don’t have to export the entire disk device, mind you; you can export a single directory within a partition. This directory cannot contain either symlinks or double or single dots. Of the three parts of the /etc/exports entry, only the directory is mandatory. If I wanted to export my home directory to every host on the Internet, I could use an /etc/exports line consisting entirely of this:
/home/mwlucas   
We show no options and no host restrictions. This would be foolish, of course, but I could do it.3

After editing the exports file, tell mountd to reread it:
# /etc/rc.d/mountd restart 
mountd(8) logs any problems in /var/log/messages. The log messages are generally enigmatic: While mountd(8) informs you that a line is bad, it generally doesn’t say why. The most common errors I experience involve symlinks.

Enabling the NFS Client
Configuring the client is much simpler. In /etc/rc.conf, put:
nfsclient="YES" 
Then, reboot or run /etc/rc.d/nfsclient start. Either will enable NFS client functions.

Now we can mount directories or filesystems exported by NFS servers. Instead of using a device name, use the NFS server’s host name and the directory you want to mount. For example, to mount the directory /home/ mwlucas from my server sardines onto the directory /mnt, I would run:
# mount sardines:/home/mwlucas /mnt 
Afterwards, test your mount with df(1).
# df 
Filesystem             1K-blocks     Used    Avail Capacity Mounted on 
/dev/ad4s1a              1012974   387450   544488    42%     / 
devfs                          1        1        0   100%     /dev 
/dev/ad4s1f            109009798 12959014 87330002    13%     /usr 
/dev/ad4s1e            1012974      42072   889866     5%     /var 
sardines:/home/mwlucas 235492762 150537138 66116204   69%     /mnt 
The NFS-mounted directory shows up as a normal partition, and I can read and write files on it as I please. Well, maybe not entirely as I please . . .

NFS and Users
File ownership and permissions are tied to UID numbers. NFS uses UID to identify the owner. For example, on my laptop the user mwlucas has the UID of 1001. On the NFS server, mwlucas also has the UID 1001. This makes my life easy, as I don’t have to worry too much about file ownership; I have the same privileges on the server as on my laptop. This can be a problem on a large network, where users have root on their own machines. The best way around this is to create a central repository of authorized users via Kerberos. On a small network or on a network with a limited number of NFS users, this usually isn’t a problem; you can synchronize /etc/master.passwd on your systems or just assign the same UID to each user on each system.

The root user is handled slightly differently, however. An NFS server doesn’t trust root on other machines to execute commands as root on the server. After all, if an intruder breaks into an NFS client you don’t want the server to automatically go down with it. You can map requests from root to any other username. For example, you might say that all requests from root on a client will run as the user nfsroot on the server. With careful use of groups, you could allow this nfsroot user to have limited file access. Use the -maproot option to map root to another user. Here, we map UID 0 (root) on the client to UID 5000 on the server:
/usr/home/mwlucas -maproot=5000
If you really want the root user on the client to have root privileges on the server, you can use -maproot to map root to UID 0. This might be suitable on your home network or on a test system.

If you do not use a maproot statement, the NFS maps a remote root account to nobody:nobody by default.

Don’t forget to restart mountd(8) after editing the exports file.

Exporting Multiple Directories
Many directories under /usr would make sensible exports. Good candidates include /usr/src, /usr/obj, and /usr/ports/distfiles. List all directories of the same partition on the same line in /etc/exports, right after the first exported directory, separated by spaces. My /etc/exports now looks like this:
/usr/home/mwlucas /usr/src /usr/obj /usr/ports/distfiles -maproot=5000 
There are no identifiers, separators, or delimiters between the parts of the line. Yes, it would be easier to read if we could put each shared directory on its own line, but we can’t; they’re all on the same partition. The FreeBSD team could rewrite this so that it had more structure, but then FreeBSD’s /etc/exports would be incompatible with that from any other Unix.

As with many other configuration files, you can use a backslash to break a single line of configuration into multiple lines. You might find the above configuration more readable as:
/usr/home/mwlucas \ 
   /usr/src \ 
   /usr/obj \ 
   /usr/ports/distfiles \ 
-maproot = 5000 
Restricting Clients
To allow only particular clients to access an NFS export, list them at the end of the /etc/exports entry. Here, we restrict our share above to one IP address:
/usr/home/mwlucas /usr/src /usr/obj /usr/ports/distfiles \ 
    -maproot=5000 192.168.1.200 
You can also restrict file shares to clients on a particular network by using the -network and -mask qualifiers:
/usr/home/mwlucas /usr/src /usr/obj /usr/ports/distfiles \ 
    -maproot=5000 -network 192.168.0 -mask 255.255.255.0 
This lets any client with an IP address beginning in 192.168.0 access your NFS server. I use a setup much like this to upgrade clients quickly. I build a new world and kernel on the NFS server, then let the clients mount those partitions and install the binaries over NFS.

Combinations of Clients and Exports
Each line in /etc/exports specifies exports from one partition to one host or set of hosts. Different hosts can have entirely different export statements.
/usr/home/mwlucas /usr/src /usr/obj /usr/ports/distfiles \ 
    -maproot=5000 192.168.1.200 
/usr -maproot=0 192.168.1.201 
Here, I’ve exported several subdirectories of /usr to the NFS client at 192.168.1.200. The NFS client at 192.168.1.201 gets to mount the whole of /usr, and may even do so as root.

NFS Performance and Options
FreeBSD uses conservative NFS defaults, so that it can work well with any other Unix-like operating system. If you’re working in a pure FreeBSD environment or if your environment only contains higher-end Unix systems, you can improve NFS performance with mount options.

First of all, NFS defaults to running over UDP. The tcp or -T option tells the client to request a mount over TCP.

Programs expect the filesystem to not disappear, but when you’re using NFS it’s possible that the server will vanish from the network. This makes programs on the client trying to access the NFS filesystem hang forever. By making your NFS mount interruptible, you will be able to interrupt processes hung on unavailable NFS mount with CTRL-C. Set interruptibility with intr. FreeBSD can tell clients if and when a filesystem is no longer accessible.

Programs will fail when trying to access the filesystem, instead of hanging forever.

Finally, you can set the size of read and write requests. The defaults are well-suited to networks of the early 1990s, but you can set the read and write size to more modern values with the -r and -w options. I find that 32768 is a good value for both. So, putting this all together, I could have my client mount an NFS file system like this:
# mount -o tcp,intr,soft,-w=32768,-r=32768 server:/usr/home/mwlucas /mnt 
The same entry in /etc/fstab looks like this:
server:/usr/home/mwlucas /mnt nfs rw,-w=32768,-r=32768,tcp,soft,intr 0 0 
This general NFS configuration gives me good throughput speed on a local network, limited only by hardware quality.

While NFS is pretty straightforward for simple uses, you can spend many hours adjusting, tuning, and enhancing it. If you wish to build a complicated NFS environment, don’t rely entirely on this brief introduction but spend time with a good book on the subject.


FREEBSD AND CIFS

If you’re on a typical office network, the standard network file sharing protocol is Microsoft’s Common Internet File Sharing, or CIFS. (CIFS was once known as Server Message Block, or SMB.) This is the "Network Neighborhood" that Windows users can access. While originally provided only by Microsoft Windows systems, this protocol has become something of a standard. Thankfully, today there’s an open source CIFS file sharing server called Samba. Many commercial products provide services via this protocol. FreeBSD includes kernel modules to support the filesystem and programs to find, mount, and use CIFS shares.

Prerequisites

Before you begin working with Microsoft file shares, gather the following information about your Windows network:
  • Workgroup or Windows domain name
  • Valid Windows username and password
  • IP address of the Windows DNS server
Kernel Support

FreeBSD uses several kernel modules to support CIFS. The smbfs.ko module supports basic CIFS operations. The libmchain.ko and libiconv.ko modules provide supporting functions and load automatically when you load smbfs.ko. You can compile these statically in your kernel as:
options     NETSMB 
options     LIBMCHAIN 
options     LIBICONV 
options     SMBFS 
Of course, you can load these at boot time with the appropriate entries in /boot/loader.conf.

Configuring CIFS

CIFS relies on a configuration file, either $HOME/.nsmbrc or /etc/nsmb.conf. All settings in /etc/nsmb.conf override the settings in user home directories. The configuration file is divided into sections by labels in square brackets. For example, settings that apply to every CIFS connection are in the [default] section. Create your own sections to specify servers, users, and shares, in one of the following formats:
[servername] 
[servername:username] 
[servername:username:sharename] 
Information that applies to an entire server goes into a section named after the server. Information that applies to a specific user is kept in a username section, and information that applies to only a single share is kept in a section that includes the share name. You can lump the information for all the shares under a plain [servername] entry if you don’t have more specific per-user or per-share information.

Configuration entries use the values from the CIFS system—for example, my Windows username is lucas_m, but my FreeBSD username is mwlucas, so I use lucas_m in nsmb.conf.

nsmb.conf Keywords

Specify a nsmb.conf configuration with keywords and values under the appropriate section. For example, servers have IP addresses and users don’t, so you would only use an IP address assignment in the server section. To use a keyword, assign a value with an equal sign, as in keyword=value. Here are the common keywords; for a full list, see nsmb.conf(5).

workgroup=string
The workgroup keyword specifies the name of the Windows domain or workgroup you want to access. This is commonly a default setting used for all servers.

addr=a.b.c.d
The addr keyword sets the IP address of a CIFS server. This keyword can only appear under a plain [servername] label.

nbns=a.b.c.d
The nbns keyword sets the IP address of a NetBIOS (WINS) nameserver. You can put this line in the default section or under a particular server. If you have Active Directory (which is based on DNS), you can use DNS host names. Adding a WINS server won’t hurt your configuration, however, and helps in testing basic CIFS setup.

password=string
The password keyword sets a clear-text password for a user or a share. If you must store passwords in /etc/nsmb.conf, be absolutely certain that only root can read the file. Storing a password in $HOME/.nsmbrc is a bad idea on a multi-user system. You can scramble your Windows password with smbutil crypt, generating a string that you can use for this keyword. The scrambled string has double dollar signs ($$) in front of it. While this helps prevent someone accidentally discovering the password, a malicious user can unscramble it easily.

CIFS Name Resolution

Let’s build a basic nsmb.conf file. As an absolute minimum, we first need to find hosts, which means we need a workgroup name. We’ll set the domain controller as the WINS server. I also have a user set up on the Windows-based servers to share files, so I’m going to use that as a default in nsmb.conf.
[default] 
workgroup=BIGLOSER 
nbns=192.168.1.66 
username=unix 
Armed with this information, we can perform basic SMB name queries.
# smbutil lookup ntserv1 
Got response from 192.168.1.66 
IP address of ntserv1: 192.168.1.4 
If this works, you have basic CIFS functionality.

Other smbutil(1) Functions

Before you can mount a filesystem from a Windows host, you must log into the host. Only root can perform this operation.
# smbutil login //unix@ntserv1 
Password: 
So, our configuration is correct. Let’s see what resources this server offers with smbutil’s view command.
# smbutil view //unix@ntserv1
Password:
Share Type Comment
IPC$ pipe Remote IPC 
ADMIN$ disk Remote Admin 
C$ disk Default share 
unix disk 
4 shares listed from 4 available 
You’ll get a list of every shared resource on the CIFS server. Now, assuming you’re finished, log out of the server.
# smbutil logout //unix@ntserv1 
Mounting a Share

Now that you’ve finished investigating, let’s actually mount a share with mount_smbfs(8). The syntax is as follows:
# mount_smbfs //username@servername/share /mount/point 
I have a share on this Windows box called MP3 that I want to access from my FreeBSD system. To mount this as /home/mwlucas/smbmount, I would do this:
# mount_smbfs //unix@ntserv1/MP3 /home/mwlucas/smbmount 
mount(8) and df(1) show this share attached to your system, and you can access documents on this server just as you could any other filesystem.

Other mount_smbfs Options

mount_smbfs includes several options to tweak the behavior of mounted CIFS filesystems. Use the -f option to choose a different file permission mode and the -d option to choose a different directory permission mode. For example, to set a mount so that only I could access the contents of the directory, I would use mount_smbfs -d 700. This would make the FreeBSD permissions far more stringent than the Windows privileges, but that’s perfectly all right with me. I can change the owner of the files with the -u option, and the group with the -g option.

Microsoft filesystems are case-insensitive, but Unix-like operating systems are case sensitive. CIFS defaults to leaving the case as it finds it, but that may not be desirable. The -c flag makes mount_smbfs(8) change the case on the filesystem: -c l changes everything to lowercase and -c u changes everything to uppercase.

Sample nsmb.conf Entries

Here are samples of nsmb.conf entries for different situations. They all assume they’re part of a configuration where you’ve already defined a workgroup, NetBIOS nameserver, and a username with privileges to access the CIFS shares.

Unique Password on a Standalone System
You would use something like the following if you have a machine named desktop with a password-protected share. Many Windows 9x systems have this sort of password-protection feature.
[desktop:shareusername] 
password=$$1789324874ea87 
Accessing a Second Domain
In this example, we’re accessing a second domain, named development. This domain has a username and password different from those at our default domain.
[development] 
workgroup=development 
username=support 
CIFS File Ownership

Ownership of files between Unix-like and Windows systems can be problematic. For one thing, your FreeBSD usernames probably won’t map to Windows usernames, and Unix has a very different permissions scheme compared to Windows.

Since you’re using a single Windows username to access the share, you have whatever access that account has to the Windows resources, but you must assign the proper FreeBSD permissions for that mounted share. By default, mount_smbfs(8) assigns the new share the same permissions as the mount point. In our earlier example, the directory /home/mwlucas/smbmount is owned by the user mwlucas and has permissions of 755. These permissions say that mwlucas can edit what’s in this directory, but nobody else can. Even though FreeBSD says that this user can edit those files, Windows might still not let that particular user edit the files it’s sharing out.


SERVING CIFS SHARES

Just as FreeBSD can access CIFS shares, it can also serve them to CIFS clients with Samba. You can find Samba in /usr/ports/net/samba3. You’ll find the Samba website at http://www.samba.org, along with many useful tutorials. Serving CIFS shares from FreeBSD is much more complicated than accessing them, so we’ll end our discussion here before this book grows even thicker. devfs(5) is a dynamic filesystem for managing device nodes. Remember, in a Unix-like operating system everything is a file. This includes physical hardware. Every device on the system has a device node under /dev.

Once upon a time, the system administrator was responsible for making these device node files. Lucky sysadmins managed an operating system that came with a shell script to handle device node creation and permissions. If the OS authors had not provided such a shell script, or if the server had unusual hardware not included in that shell script, the sysadmin had to create the node with black magic and mknod(8). If any little thing went wrong, the device would not work. The other option was to ship the operating system with device nodes for every piece of hardware imaginable. System administrators could be confident—well, mostly confident—that the desired device nodes were available, somewhere, buried within the thousands of files under /dev.

Of course, the kernel knows exactly what characteristics each device node should have. With devfs(5), FreeBSD simply asks the kernel what device nodes the kernel thinks the system should have and provides exactly those—and no more. This works well for most people. You and I are not "most people," however. We expect odd things from our computers. Perhaps we need to make device nodes available under different names, or change device node ownership, or configure our hardware uniquely. FreeBSD breaks the problem of device node management into three pieces: configuring devices present at boot, global availability and permissions, and configuring devices that appear dynamically after boot with devd(8).

DEVICE MANAGEMENT AND SERVERS

For the most part, device node management on servers works without any adjustment or intervention. The place I most often need to muck with device nodes is on laptops and the occasional workstation. FreeBSD’s device node management tools are very powerful and flexible, and incude support for things I wouldn’t expect to use in a century. We’ll ony touch upon the basics. Don’t think that you must master devfs(5) to get your server running well!


devfs at Boot: devfs.conf
The big problem sysadmins have with a dynamic devfs is that any changes made to it disappear on reboot. When device nodes were permanent files on disk, the sysadmin could symlink to those nodes or change their permissions without worrying that his changes would vanish. With an automated, dynamic device filesystem, this assurance disappears. (Of course, you no longer have to worry about occult mknod(8) commands either, so you’re better off in the long run.) The device node changes could include, for example:
  • Making device nodes available under different names
  • Changing ownership of device nodes
  • Concealing device nodes from users
At boot time, devfs(8) creates device nodes in accordance with the rules in /etc/devfs.conf.

devfs.conf
The /etc/devfs.conf file lets you create links, change ownership, and set permissions for devices available at boot. Each rule has the following format:
action    realdevice    desiredvalue 
The valid actions are link (create a link), perm (set permissions), and own (set owner). The realdevice entry is a preexisting device node, while the last setting is your desired value. For example, here we create a new name for a device node:



We want a symbolic link to the device node /dev/acd0 (an ATAPI CD drive), and we want this link to be named /dev/cdrom . If we reboot with this entry in /etc/devfs.conf, our CD device at /dev/acd0 also appears as /dev/cdrom, as many desktop multimedia programs expect.

To change the permissions of a device node, give the desired permissions in octal form as the desired value:
perm         acd0         666 
Here, we set the permissions on /dev/acd0 (our CD device, again) so that any system user can read or write to the device. Remember, changing the permissions on the /dev/cdrom link won’t change the permissions on the device node, just the symlink.

Finally, we can also change the ownership of a device. Changing a device node’s owner usually indicates that you’re solving a problem the wrong way and that you may need to stop and think. FreeBSD happily lets you mess up your system if you insist, however. Here, we let a particular user have absolute control of the disk device /dev/da20:
own         da20         mwlucas:mwlucas 
This might not have the desired effect, however, as some programs still think that you must be root to carry out operations on devices. I’ve seen more than one piece of software shut itself down if it’s not run by root, without even trying to access its device nodes. Changing the device node permissions won’t stop those programs’ complaints when they are run by a regular user.

Configuration with devfs.conf(5) solves many problems, but not all. If you want a device node to simply be invisible and inaccessible, you must use devfs rules.

Global devfs Rules

Every devfs(5) instance behaves according to the rules defined in devfs.rules. The devfs rules apply to both devices present at boot and devices that appear and disappear dynamically. Rules allow you to set ownership and permissions on device nodes and make device nodes visible or invisible. You cannot create symlinks to device nodes with devfs rules.

Similar to /etc/rc.conf and /etc/defaults/rc.conf, FreeBSD uses /etc/devfs.rules and /etc/defaults/devfs.rules. Create an /etc/defvs.rules for your custom rules and leave the entries in the defaults file alone.

devfs Ruleset Format
Each set of devfs rules starts with a name and a ruleset number between square brackets. For example, here are a few basic devfs rules from the default configuration:



The first set of rules is called devf s_hide_all and is ruleset number 1 This ruleset contains only one rule .

Ruleset Content
All devfs rules (in files) begin with the word add, to add a rule to the ruleset. You then have either a path keyword and a regex of device names, or a type keyword and a device type. At the end of the rule, you have an action, or a command to perform. Here’s an example of a devfs rule:
add path da* user mwlucas 
This rule assigns all device nodes with a node name beginning with da to the ownership of mwlucas. On a multi-user system, or a system with SCSI hard drives, this would be a bad idea. On a laptop, where the only device nodes beginning with da are USB storage devices, it’s not such a bad idea.

Devices specified by path use standard shell regular expressions. If you want to match a variety of devices, use an asterisk as a wildcard. For example, path ad1s1 matches exactly the device /dev/ad1s1, but path ad*s* matches every device node with a name beginning with ad, a character, the letter s, and possibly more characters. You could tell exactly what devices are matched by a wildcard by using it at the command line.
# ls /dev/ad*s* 
This lists all slices and partitions on your ATA hard drives, but not the devices for the entire drive.

The type keyword indicates that you want the rule to apply to all devices of a given type. Valid keywords are disk (disk devices), mem (memory devices), tape (tape devices), and tty (terminal devices, including pseudoterminals). The type keyword is rarely used exactly because it’s so sweeping.

If you include neither a path nor a type, devfs applies the action at the end of the rule to all device nodes. In almost all cases, this is undesirable. The ruleset action can be any one of group, user, mode, hide, and unhide. The group action lets you set the group owner of the device, given as an additional argument. Similarly, the user action assigns the device owner. Here, we set the ownership of da disks to the username desktop and the group usb:
add path da* user desktop 
add path da* group usb 
The mode action lets you assign permissions to the device in standard octal form:
add path da* mode 664 
The hide keyword lets you make device nodes disappear, and unhide makes them reappear. Since no program can use a device node if the device is invisible, this is of limited utility except when the system uses jail(8). We’ll look at that specific use of hide and unhide in the next chapter. Once you have a set of devfs rules you like, enable them at boot in /etc/rc.conf. Here, we activate the devfs ruleset named laptoprules:
devfs_system_rulesets="laptoprules" 
Remember, devfs rules apply to the devices in the system at boot and the devices configured dynamically after startup. To finish up, let’s look at dynamic devices.

Dynamic Device Management with devd(8)

Hot-swappable hardware is much more common now than it was even ten years ago. In the last century, laptop network cards were considered cuttingedge. While you might drop a new CD into the workstation’s cup holder, you wouldn’t hot-plug a whole CD drive into your desktop. Today, that’s entirely different. Flash drives are essentially USB-based hard drives that you can attach and detach at will, and other USB hardware lets you add keyboards, mice, and even network cards on a whim.

FreeBSD’s devfs dynamically creates new device nodes when this hardware is plugged in and erases the nodes when the hardware is removed, making using these dynamic devices much simpler. devd(8) takes this a step further by letting you run userland programs when hardware appears and disappears.

devd Configuration
devd(8) reads its configuration from /etc/devd.conf and any file under /usr/local/etc/devd/. I recommend placing your local rules in /usr/local/etc/ devd/devd.conf to simplify upgrades. You could also add different rules files for different types of devices, if you find your devd(8) configuration becoming very complicated. You’ll find four types of devd(8) rules: attach, detach, nomatch, and notify.

attach rules are triggered when matching hardware is attached to the system. When you plug in a network card, an attach rule configures the card with an IP address and brings up the network.

detach rules trigger when matching hardware is removed from the system. detach rules are uncommon, as the kernel automatically marks resources unavailable when the underlying hardware disappears, but you might find uses for them.

The nomatch rules triggers when new hardware is installed but not attached to a device driver. These devices do not have device drivers in the current kernel. devd(8) applies notify rules when the kernel sends a matching event notice to userland. For example, the console message that a network interface has come up is a notify event. Notifications generally appear on the console or in /var/log/messages.

devd(8) rules also have priority, with 0 being the lowest. Only the highest matching rule is processed, while lower-priority matching rules are skipped. Here’s a sample devd(8) rule:



This is a notify rule, which means it activates when the kernel sends a message to userland. As a priority 0 rule, this rule can only be triggered if no rule of higher-priority matches the criteria we specify. This rule only triggers if the notification is on the network system IFNET (network), and only if the notification type is ATTACH —in other words, when a network interface comes up. Under those circumstances, devd(8) takes action and runs a command to configure the network interface .

devd(8) supports many options to handle all sorts of different situations. If you want to automatically mount a particular USB flash disk on a certain mount point, you can do that by checking the serial number of every USB device you put in. If you want to configure Intel network cards differently than 3Com network cards, you can do that too. We’ll do enough with devd(8) to introduce you to its abilities, mainly through examples, but we won’t delve deeply into it.

devd(8) Example: Laptops
I use my laptop both at work and at home. At work I use a wired connection, while at home I use wireless. Both require very particular setups, different DNS servers, and different configurations all around. I could cheat by renumbering my home network to match my work network, but experience tells me that my home network will last much longer than my attachment to any one job. (Maybe I’m wrong.4) I want the laptop to configure itself for home when I plug in my wireless card. I want the laptop to configure itself for work when I plug in the CAT5 cable to the integrated network interface.

If a wired interface is configured to use DHCP, plugging in the cable tells FreeBSD to start dhclient(8) and configure the network. When I plug in a wireless card, FreeBSD checks for a configuration and tries to start the network. Here’s my wireless configuration from /etc/rc.conf (this is all one line in the configuration, but it is broken to fit in this book):
ifconfig_wi0="inet dhcp ssid WriteFaster wepkey 
0xdeadbeefbadc0decafe1234567 weptxkey 1 wepmode on channel 1" 
When I insert my wireless card, the kernel attaches the card to the driver wi0. This is an attach event, and devd(8) searches its configuration for a corresponding rule. The following entry in /etc/devd.conf matches:



We inserted a card into the laptop, and FreeBSD attached the wi(4) driver to it. This is an attach event. This rule has a priority of 0 , so any other matching rule will run before this default rule. Anything with a media type of 802.11 (wireless) matches this rule. When an attach event matches this rule, FreeBSD runs a command to configure the network. I could run a custom script instead of using the built-in FreeBSD support, but why bother when the default configuration does everything I need?

Unlike the wireless I use at home, the Ethernet interface I use at work is always attached to my system. The interface might not be plugged into a network, but the card itself is always attached. I don’t want to configure this interface every time the system boots, because if the interface isn’t plugged in I’ll have a long delay while my laptop’s SSH daemon and other services time out on DNS queries. At work I have a variety of NFS mounts, as well as custom client/server settings not available from the DHCP server. This means that I need to run a custom shell script to configure my network for work, but only when the network cable is plugged in. I want devd to watch for a notification that the interface has come up and then run my custom shell script. I’ve written the custom entry below and placed it in /usr/local/etc/devd/devd.conf:



This is a notification rule, which means it triggers when the kernel sends a matching notification message to the system. It also has a priority of 10 , so it runs before any of FreeBSD’s default rules. This rule triggers on the network system, when a link comes up (i.e., when we plug in a network cable), if the link is Ethernet . When all of these conditions are met, FreeBSD runs a shell script in my home directory.

Note that this rule has a commented-out line . When I said I wrote this rule, I lied. I actually copied the default entry from /etc/devd.conf and modified it slightly. FreeBSD already has rules for handling network interfaces coming up, but I wanted to do something a little different. Instead of coming up with all these conditions myself, I found a entry that was almost right and modified it. I suggest you do the same. Just be sure to give your customized rule a higher priority than the default rule, so FreeBSD uses your rule instead of its own.

Another devd Example: Flash Drives
Copying an entry is cheating, I hear you cry. Well, let’s try an example where FreeBSD doesn’t have any infrastructure in place. On my laptop, I want any USB storage mounted on /media automatically. The first USB storage device plugged into a laptop shows up in FreeBSD as /dev/da0, but the device name is umass0. (If you already have other USB or SCSI devices, these numbers will differ for you.) Generally speaking, all flash media is formatted with the FAT32 fileystem, so you would use mount -t msdosfs to mount it.

When the device is plugged in, FreeBSD attaches it to the kernel, so we use an attach rule:



I assign this rule a priority of 10, so it overrides any new priority 0 functions FreeBSD might install during an upgrade. (If FreeBSD grows the ability to do this automatically, I’ll probably use that instead, but I don’t want an upgrade to change my system behavior unless I know about it.) Here, we match on the device name . When the device appears, a shell script in my directory runs.

Why not just run the mount(8) command? USB devices need a moment or two to warm up and stabilize before they can be accessed. Also, some USB flash drives need to be poked before they really start to work. The shell script I use here is terribly simpleminded, but it suffices:
#!/bin/sh 
sleep 2 
/usr/bin/true > /dev/da0 
/sbin/mount -t msdosfs /dev/da0s1 /media 
While this handles mounting the device for me, devd(8) won’t unmount the device. FreeBSD expects the sysadmin to unmount filesystems before removing the underlying devices. It’s no different from unmounting a CD or floppy disk before ejecting it.

While devd(8) has many more advanced features, these two examples cover all the features I’ve needed or wanted to use in several years. Please read the manual page if you seek further enlightenment. Now that you have a little bit too much understanding of FreeBSD filesystems, let’s look at its more advanced security features.


  1. Why is there no safeguard against shooting yourself in the foot like this? Well, Unix feels that anyone dumb enough to do this doesn’t deserve to be its friend. Various people keep trying to put Unix in therapy for this type of antisocial behavior, but it just isn’t interested.


  2. It would be nice, some day, to have employment that didn’t end with four corporate security gorillas dragging me to the door in chains, with my new ex-boss screeching in the background about federal regulators, crème brûlée, and caffeinated lemurs. I’m certain this is just coincidence, mind you, as nobody’s ever pressed charges.




Page: 1, 2



ADS BY GOOGLE SPONSORED LINKS FEATURED LINKS

WinConnections Conference Fall 2008
Don’t miss the premier event for Microsoft IT Professionals in Las Vegas, November 10-13. Register and book your room by August 25 and receive a FREE room night (based on a three night minimum stay).

Maximize your SharePoint Investment – 8 Cities
Discover best practices and tips for both architecting and administering SharePoint. Early Bird Price of $99 through Sept 15th.

Find a new job now on the all new IT Job Hound!
Search jobs, post your resume, and set up job e-mail alerts!

Master SharePoint with 3 eLearning Seminars
Learn how to build a better SharePoint infrastructure and enable powerful collaboration with MVPs Dan Holme and Michael Noel. Register today!

Top Tools for Virtualization Disaster Recovery & Replication
View this web seminar on August 14th to learn about two tools that will result in faster backup and restore with P2V disaster recovery.

SharePointConnections Conference Fall 2008
Don’t miss the premier event for Microsoft IT Professionals in Las Vegas, November 10-13. Register and book your room by August 25 and receive a FREE room night (based on a three night minimum stay).

VMworld 2008 - Sign Up Today!
Join your peers on September 15-18 at The Venetian Hotel in Las Vegas as VMware hosts VMworld 2008, the leading Virtualization event.



When managing just VMware isn’t enough
Plan/Manage/Secure – NetIQ VMware management. Download whitepaper.

What’s up with your network? Find out with ipMonitor
Availability monitoring for servers, applications and networks – FREE trial

Microsoft® Tech•Ed EMEA 2008 IT Professionals
Advance your thinking with new ideas and practical real-world solutions at Microsoft’s FIVE day technical infrastructure conference 3-7 Nov., 2008. Register before 26 September 2008 to save €300.

Order Your Fundamentals CD Today!
Gain an introduction to Exchange, learn server security requirements, and understand how unified communications can play a role in your messaging strategies with this free Exchange CD.

Are You Really Compliant with Software Regulations?
View this web seminar that will help you with compliance best practices and check out a management solution to assure that you won’t be in jeopardy of an audit.

Virtualization Congress Oct. 14-16 in London
Don't miss Virtualization Congress, the premiere EMEA conference dedicated to hardware, OS and application virtualization. Oct. 14-16 in London.
Windows IT Pro Home Register FAQ for Windows WinInfo News
Europe Edition About Us Contact Us/Customer Service Media Kit Affiliates / Licensing  
SQL Server Magazine Office & SharePoint Pro Windows Dev Pro IT Job Hound ITTV
IT Library Technical Resources Directory Connected Home Windows Excavator Windows SuperSite 
 
 Windows IT Pro is a Division of Penton Media Inc.
 Copyright © 2008 Penton Media, Inc., All rights reserved. Terms and Use | Privacy Statement | Reprints and Licensing