Cover V11, I10

Article

oct2002.tar

Questions and Answers

Amy Rich

Q We run a number of FreeBSD 4.5-STABLE machines and access them with OpenSSH. Instead of rebuilding world every time there's a new OpenSSH hole, we want to exclusively use the OpenSSH in the ports collection. Unfortunately, the ports version of OpenSSH installs into /usr/local, and we really want to avoid having multiple copies of OpenSSH. On those occasions when we do a make installworld, the base OpenSSH will get reinstalled. I really wish that the FreeBSD folks would make everything a package, much like Solaris or AIX. Until then, though, is there a clean way around this?

A It would be nice if everything were a package, but there is a way around this particular problem. If you have a recent version of the ports collection, you can install the openssh-portable port on top of the system default OpenSSH by doing:

cd /usr/ports/security/openssh-portable
make -DOPENSSH_OVERWRITE_BASE install
This will also use whatever openssl came with the base system instead of trying to install the latest.

To be sure that you don't overwrite your openssh-portable port when you do a make installworld, put the following line in /etc/make.conf on all your machines:

NO_OPENSSH=yes
Q I've been asked to whip up a Perl script for our accounting department. One of the design requirements is to create new variable names out of two existing variable names:

$Customer = 'bob';
$ID = '0145829';
$CustomerID = 'b9485760';
I'm not sure how to join the two variable names together. I've tried doing:

$Customer$ID = 'something else';
but that doesn't work. Any suggestions?

A The cleanest way to implement this is to use a hash:

my %info;
$info{Customer} = 'Bob';
$info{ID} = '0145829';
$info{$info{Customer} . $info{ID}} = 'b9485760';
Avoid the simpler looking:

$Customer = 'bob';
$ID = '0145829';
${$Customer. $ID} = 'b9485760';
The latter uses symbolic references, and so doesn't work with my variables or use strict. See the question on "How can I use a variable as a variable name?" from http://www.perldoc.com/perl5.6/pod/perlfaq7.html. If you're using symbolic references and you generate them on the fly like this, something unexpected could happen with your data. You may wind up doing some very unpleasant things in your code, and it would be very difficult to track down such bugs. For more information on references in Perl, do a perldoc on perlref.

Q Our company has many offices on multiple continents. One way we send out company communications is via a private news hierarchy. As part of my job, I run the "master" news server where all of the new groups are created and from which most of the corporate content originates. I do not control the news servers at each office, though. Sometimes other offices get behind on managing group additions or deletions, so I'd like to send out an automated message each month or so just to make sure everyone is on the same page. Is there some special way to do this?

A Ideally, you'd have your own local control group where you send all group creation and removal messages or a config group where newsgroup discussion takes place. Let's say your company is the fictitious Yoyodyne Systems, your domain is yoyodyne-systems.com, and your local hierarchy is yoyodyne.*. Since you control the "master" server, you presumably have an authoritative newsgroups file with all of the local groups and their descriptions. You can post a checkgroups message to the control or config group each month by invoking inews from news's crontab. The script to do the posting would look something like this (replace command paths where necessary, or set PATH at the beginning of the script):

#!/bin/sh

TMP=/usr/local/news/tmp/article.$$ # a tmp file created someplace only
                                   # the news user has write access
NEWSGROUPS=/usr/local/news/etc/newsgroups  # your newsgroups file
MINLINES=50    # This is some arbitrary number so you make sure that
               # you actually got a decent grep.  It should be somewhat
               # close to the number of groups you actually have.

 if [ -r ${NEWSGROUPS} ] && [ ! -e ${TMP} ] &&  /usr/bin/touch ${TMP};
 then
   echo 'From: <news@yoyodyne-systems.com>' >> ${TMP}
   echo 'Subject: checkgroups yoyodyne.*' >> ${TMP}
   echo 'Newsgroups: yoyodyne.config' >> ${TMP}
   echo 'Organization: Yoyodyne Systems' >> ${TMP}
   echo 'Distribution: yoyodyne' >> ${TMP}
   echo '' >> ${TMP}

   /usr/bin/grep '^yoyodyne' ${NEWSGROUPS} |/usr/bin/sort -u >> ${TMP}

   LENGTH='/usr/bin/wc -l ${TMP} | /usr/bin/awk '{ print $1}''

   if [ ${LENGTH} -gt ${MINLINES} ]; then
     /usr/local/bin/inews -h < ${TMP}
   fi
   rm ${TMP}
 fi
Q I have a number of Windows users that have just been migrated to FreeBSD, and they're looking for a decent graphical newsreader. They'd ideally like something that resembles Outlook, so something like Xrn or a curses-based newsreader in an xterm doesn't fit the bill. Any suggestions?

A I've never actually used a graphical newsreader, but I've heard good things about Pan: http://pan.rebelbase.com/. There's a port for it in /usr/src/news/pan/ if you have the ports collection on your machine.

Another option might be Mahogany, though it may be in more of a beta stage than your users want to deal with. Mahogany is available from http://mahogany.sourceforge.net/ or in the ports collection /usr/ports/mail/mahogany/. You may also want to do a search for newsreaders on http://sourceforge.net/search/.

Q For security and load purposes, our mail infrastructure is distributed amongst several machines. A couple of these machines are designated as reader only and they do only POP and IMAP. These machines should only accept SMTP connections from the feeder machines and not any other internal or any external machines. Is there an easy way to do this?

A You don't say what version of Sendmail you're using or what operating system your reader machines are running, so some of these suggestions may not work for you. There are three fairly simple ways you can achieve what you want. You can:

1. Use a packet filter like ipchains, ipfw, or ipfilter to block all incoming port 25 connections except from your feeder machines.

2. If you're running Sendmail from inetd (not really recommended, but some people still do anyway), you can wrap it with tcp wrappers and block connections that are not from your feeder machines. If you have a lot of traffic, you'll see a performance hit if you run Sendmail from inetd.

3. Depending on which version of Sendmail you're running, you can have Sendmail itself do the blocking. To use this method, you'd need to compile Sendmail with access_db support and set up your access file to individually reject all 256 of the class A-sized networks and then explicitly allow the few IP addresses you want to connect. Your access database would look similar to:

 * block all 256 class A sized networks
 0    ERROR:550 "This host does not accept external mail"
 1    ERROR:550 "This host does not accept external mail"
 2    ERROR:550 "This host does not accept external mail"
 [...]
 255    ERROR:550 "This host does not accept external mail"
 * accept connections from the feeder machines
 aaa.bbb.ccc.ddd OK
Q I've been trying to set up password authentication with INN, but I'm not having much luck. It seems like the authentication section is being ignored since I can read and post without a valid authentication. These are the relevant bits of readers.conf:

auth "test" {
  hosts: "*"
  auth: "ckpasswd -f /usr/local/news/etc/.nnrpasswd"
  default: "<LOCAL>"
}

access "test" {
  users: "*"
  newsgroups: "*,!control*"
  access: "rpa"
}
A Your problem is the default keyword in your auth section. If authentication fails or hasn't happened yet, the user is assigned a username of <LOCAL>. Because <LOCAL> matches *, the user is allowed rpa access to all the newsgroups except control* according to your access section. If you want to force users to authenticate before they're allowed access, remove the default: "<LOCAL>" line from your auth section.

Q When I try to suspend my FreeBSD 4.6-STABLE VAIO Z505-RX laptop using apm, I get the following error message:

apm: can't open /dev/apm: Device not configured
The same happens when I just run apm without any arguments at all. How do I configure apm to function correctly?

A First, be sure that you've enabled apm in /etc/rc.conf:

apm_enable="YES"
You also need to have apm compiled into the kernel or loaded at boot time. Either modify your kernel configuration file and rebuild your kernel, or change /boot/kernel.conf.

apm is disabled in the GENERIC kernel by default, so if you want to compile in support, create your own customized kernel file and add the line:

device apm0 at nexus?
If you find that you're having issues with suspend and resume, you may need some extra flags to the above statement. Take a look at /usr/src/sys/i386/conf/LINT, the FreeBSD mailing lists, or the comp.unix.bsd.freebsd newsgroup hierarchy for information on getting your specific model of machine working.

If you don't want to customize your kernel configuration file and rebuild, add the following line to /boot/kernel.conf instead:

en apm0
After you reboot, apm should work.

Q I want to generate my own Apache SSL cert for use with https, but I'm not sure how to go about it. After I create the cert, do I have to start Apache by hand every time so I can type in the passphrase?

A Creating your own SSL certificate for Apache isn't overly difficult, it just takes a few steps. This assumes that you've already installed apache+mod_ssl correctly. First, be sure you know the FQDN of your Webserver, the one that people will be accessing it by. Second, pick a name to go by as a certificate authority. We'll assume that you're installing Apache in the GNU style and that you're keys are stored in /usr/local/etc/apache, and you're going to use my_ca as your CA name and put your CA certs in /usr/local/etc/my_ca.

The first step to making your own SSL cert is to become a Certificate Authority. Create the directory /usr/local/etc/my_ca and cd into it:

1. Create a RSA private key for your Certificate Authority, my_ca. The resulting key will be Triple-DES encrypted and PEM formatted:

openssl genrsa -des3 -out my_ca.key 1024
2. Create a self-signed CA Certificate (X509 structure) that's good for 10 years with the RSA key of the Certificate Authority. The resulting file will be PEM formatted:

openssl req -new -x509 -days 3650 -key my_ca.key -out my_ca.crt
Next, create the actual Apache certificate. Create the directory /usr/local/etc/apache/ssl.key and cd into it.

3. Create the certificate for Apache:

openssl genrsa -des3 -out <servername>.key 1024
4. Create the certificate-signing request (CSR). Use the FQDN of your Web server for the CommonName:

openssl req -new -key <servername>.key -out <servername>.csr
5. Sign your new certificate with the CA certificate you created above. Use the sign.sh distributed with the mod_ssl distribution to sign the certificate. I prefer to keep a copy in the CA directory (/usr/local/etc/my_ca in this example) for ease of use:

/usr/local/etc/my_ca/sign.sh/usr/local/etc/apache/ssl.key/<servername>.csr
6. Move the resulting certificate into /usr/local/etc/apache/ssl.crt:

mv /usr/local/etc/apache/ssl.key/<servername>.crt/usr/local/etc/apache/ssl.crt/
To keep from typing in the password every time Apache starts, remove the encryption from the key file and make it readable only by root:

cd /usr/local/etc/apache/ssl.key
mv <servername>.key <servername>.key.encrypted
openssl rsa -in <servername>.key.encrypted -out <servername>.key
chmod 400 <servername>.key
chown root <servername>.key
Modify your httpd.conf to use mod_ssl and set up your SSL hosts. Use apachectl startssl to start Apache with -DSSL, or remove the SSL requirements from your httpd.conf and use apachectl start.

Q I just upgraded from FreeBSD 4.5-STABLE to 4.6-STABLE using the binary upgrade option of sysinstall, as mentioned in the release notes for 4.6. When I run mergemaster, I get the following errors:

     *** Creating the temporary root environment in /var/tmp/temproot
      *** /var/tmp/temproot ready for use
      *** Creating and populating directory structure in /var/tmp/temproot

     cd: can't cd to /usr/src/etc
     make: don't know how to make distrib-dirs. Stop

       *** FATAL ERROR: Cannot 'cd' to /usr/src/etc and install files to
           the temproot environment
What's the issue here, and how do I successfully merge my config files with those from the upgrade?

A It sounds like you don't have the source distribution installed. Use cvsup to sync most of, if not the entire, source tree (you can leave out the games collection, for example). Information on using cvsup can be found at:

http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/cvsup.html
There's also the possibility that you did install the source somewhere, but not in the default location of /usr/src. If this is the case, you can use the -m switch to mergemaster to specify your alternate src directory.

Amy Rich, president of the Boston-based Oceanwave Consulting, Inc. (http://www.oceanwave.com), has been a UNIX systems administrator for more than five years. She received a BSCS at Worcester Polytechnic Institute, and can be reached at: qna@oceanwave.com.