Monday, December 22, 2008

When other sites discard or refuse your email

We've covered setting up your sendmail to act as a relay for certain computers. Now, we look at another relaying problem.

You like running your own sendmail, you're using it to manage your own email accounts. You could use your ISP's mail server for all outbound messages, but let's say you're not doing that. Now, some third party, maybe another ISP, let's call them "Dogers", decides to silently discard all email coming from IP blocks owned by your ISP unless the sending IP number is one of the mail servers of your ISP. Even if you're running a responsible sendmail on a static IP number, messages sent to "Dogers" just vanish.

The solution is to arrange your sendmail so that, when sending to certain domains, it relays the messages through your ISP's servers. We'll need two more features for this. First, the mailertable function will allow you to use a different mailer for certain addresses. Second, depending on your ISP, you may have to authenticate yourself with the ISP's server before it will relay your messages. This configuration will show how to perform that authentication.

Make sure your sendmail.mc contains the following two lines before the first "MAILER" line:
FEATURE(`authinfo',`hash /etc/mail/auth/client-info')dnl
FEATURE(`mailertable')

Also, add the following line anywhere in the file:
define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl

You will need to have cyrus-sasl installed, and configured for logins. Here is a sample cyrus-sasl configuration invocation:
./configure --prefix=/usr/local --enable-anon --enable-plain \
--enable-login --disable-krb4 --with-mysql \
--with-saslauthd=/var/state/saslauthd --with-openssl=/usr/local/ssl \
--with-plugindir=/usr/local/lib/sasl2/ --enable-cram \
--enable-digest --enable-otp --without-des

OK, now the mailertable entry. Add a line for the dogers domain, telling your sendmail to forward mail for those addresses through your ISP's server:
dogers.com      smtp:smtp.<MY>.<ISP>

Now, to authenticate with the ISP. We told sendmail that our credentials would be stored in /etc/mail/auth/client-info, so we create a file there:
AuthInfo:smtp.<MY>.<ISP> "U:root" "I:wintertoad@<MY>.<ISP>" "P:<password>" "M:LOGIN"

Then, we just have to rehash the mailertable and authentication files with a command like this:
# makemap hash file.db < file

Now, assuming you've rebuilt your sendmail.cf after the changes we made to the .mc file above, you can just send a SIGHUP to the sendmail processes, and you should be able to send email to anybody at the dogers.com domain by relaying those messages through your ISP's mail server.

Sunday, July 13, 2008

A Curious Permissions Problem with ALSA

While I'm waiting for kde4 to reach everyday usability (defined for my purposes as supporting panel auto-hiding), I periodically check out an updated subversion tree of kde4, compile it, and try it out.

There's some pain with switching between kde3 and kde4 and back again, so I try kde4 with a different login, specially created for testing kde4.

There are still bugs in kde4, particularly when you compile subversion trees, and not specific tagged releases. In my latest foray into kde4, several applications did crash, including amarok, the audio media player.

After spending some time in kde4, I logged out and switched back to kde3 with my regular username. Once there, I found that there was no audio from ALSA applications. So, the usual course when this happens is to examine the permissions on the appropriate audio devices. In this case, however, all of the permissions looked fine.

So, what was preventing ALSA applications from running? When I ran strace on an ALSA application, I found that I was getting permissions problems (reported as EPERM on the return from a syscall) on semctl() syscalls. So, the next step is to run ipcs. This shows the SYSV IPC resources currently in use. There, I found two shared memory segments and two semaphores that were owned by the "kde4" username. Since all kde4-owned processes had exited, this indicated that some process had experienced an abnormal exit without releasing some SYSV IPC resources.

ALSA uses such resources when applications want to generate sound, and it is not possible for an unprivileged user to obtain or release the resources of another user. This produced the permission problems and prevented the applications from working correctly with ALSA.

The solution was to become the root user, and use the ipcrm command to release all resources owned by the kde4 user. Once that was done, ALSA applications run as my regular username could, once again, produce sound.

Thursday, May 29, 2008

When distributions patch wrongly

Events of recent weeks have provided another reason one might be inclined to avoid the use of distributions. Let's call this the "debian SSL bug". A patch applied by a well-meaning Debian coder made cryptographic keys generated by numerous applications on that distribution entirely useless. Details can be found here.

The Debian patch affected derived distributions as well, such as Ubuntu. For almost two years, many cryptographic transactions were severely compromised. The biggest problem was that the patch was not correctly passed back to development team of the OpenSSL project. Had it been, they would have pointed out its fatal security implications, and this entire headache would have been avoided.

I always feel uncomfortable when I see distributions applying patches against the original sources. There can be several reasons for these patches.
  1. They may be back-porting selected bugfixes to an earlier version of a library rather than including the latest version of the library with all of its new, and possibly untested features.
  2. They may be modifying a logo or informational string to include something specific to the distribution.
  3. They may be changing some default pathnames or other resources to mesh more well with the idiosyncracies of their own distribution.
  4. They may be changing the appearance of the interface to make it more consistent with other applications.
  5. They may be applying changes that the original maintainers of the package do not consider necessary, but which the distribution maintainers find desirable.
  6. Other...
None of these motivations will usually convince me to apply foreign patches. Your opinion may differ.

Sunday, April 27, 2008

Web browsing behind the great firewall of China

I sometimes spend time in China, and while there, I work remotely to my office and to my home computer. I do somewhat technical work that sometimes requires online research, and it's annoying that a significant fraction of non-Chinese sites are unreachable from China.

The thing to remember is that the firewall isn't there to keep me from working. I'm a Canadian passport holder, and they really don't care what I read while in China. That explains certain curious omissions, such as the fact that TCP port 22 (ssh) is not blocked.

So, here I am, in China, with a Linux laptop, and I'd like to browse the web. Rather than take my chances with the firewall, I proxy the connection through my home computer's apache daemon.

So, first I set up the proxy service on my apache. Make sure you've built the httpd with these configuration options:
--enable-mods-shared="proxy proxy-http proxy-connect"

These settings turn on the proxy service and set it to proxy HTTP traffic. The "proxy-connect" flag allows the httpd to be used as a reflector for SSL connections. If you want to visit a banking website, the data still travels as SSL between your laptop and the home machine, but the home machine just reflects the traffic to the bank without knowing what's in the data stream (the home machine cannot decode that data, if it could, it would count as a man-in-the-middle compromise of the SSL stream).

Next, add some lines to the httpd configuration file. Mine's in /etc/apache/httpd.conf.
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so

<IfModule mod_proxy.c>
ProxyRequests On

<Proxy *>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Proxy>
</IfModule>

What this does is to enable proxying, but only on connections from localhost. I don't want my httpd to be a proxy for any random person in the outside world.

Next, I set up my ssh on connections to my home computer. You can either add a switch like this to the invocation:
-L 8080:127.0.0.1:80

or you can add a line to your ~/.ssh/config entry for the connection to the home computer:
LocalForward 8080 127.0.0.1:80


Now, you ssh into your home computer.

Finally, you start up firefox, and select the menu item:
Edit->Preferences->Advanced->Network->Settings
Select "Manual proxy configuration", and point your HTTP and SSL proxies at "localhost" with the port number 8080.

That's it, now when you browse websites, the HTTP-related data stream appears simply as a pile of encrypted bits over your ssh connection. The firewall cannot know what websites you're visiting, it can't even tell that you're visiting a website at all.

Important note: this system proxies the HTTP data. That means web pages, frames, images in the page, RSS feeds, and so on. It does not proxy UDP or post-connection traffic, like youtube videos. If your web browser has a plugin that downloads data from an external site, that plugin may not be using your proxy.

If you want to know what data is not passing through your proxy, you can run tcpdump in another window. Something like this:
tcpdump 'host <IPNUM> and not port 22'

where is the IP number of your external interface (not 127.0.0.1). You may have to add a "-i" switch if your laptop has more than one network interface. This command will show you all traffic that is not going over the ssh connection.

Wednesday, April 2, 2008

Fixing sound in Linux Civ:CTP

When my old 64-bit motherboard died, and I replaced it with the DP35DP, one of the surprises I ran into was that the sound was badly broken on "Civilization:Call To Power". All other applications that I tried worked well, any programs using the ALSA interface, as well as a few 32-bit binaries on the OSS interface, like Quake 2 and Heroes 3. However, with Civ:CTP, the sound stuttered and looped horribly. I couldn't use the aoss wrapper because Civ:CTP is statically linked. After a lot of tinkering, I finally came to the conclusion that, for this one application, I had to load the sound module with different parameters.

For every application except Civ:CTP, my snd-hda-intel module is loaded with the parameters
position_fix=1 model=5stack

However, in order to run Civ:CTP, I have to exit all sound applications, remove the snd-hda-intel module, and re-load it with the parameters:
position_fix=3 model=5stack

With this change, the sound in Civ:CTP sounds fine. However, all other applications have poor sound, scratchy and unpleasant to the ear, so I only make this module change just prior to running the game, and re-load the module with the usual parameters immediately afterwards.

Wednesday, March 19, 2008

Experiences compiling X11R7

Compiling and installing X11R7, x.org 7.3, was a bit more rough than the X11 compiles I used to perform. I used the build script supplied with the source packages. When it finished, apparently successfully, there were two problems whose solutions were not obvious.

First of all, OpenGL worked on my NVidia box, but not my ATI laptop.

Second, my Chinese fonts for traditional characters in Emacs looked different, much worse. The simplified Chinese characters still looked fine.

OK, what were the problems, and how did I fix them. First of all, the OpenGL issue. I compiled X11 the same way on both computers, why did OpenGL not work on the ATI laptop? Well, both NVidia and ATI ship closed-source binary blobs with support libraries. The difference is that NVidia supplies its own libGL.so, while ATI uses the one from x.org. So, somehow I was failing to compile and install the OpenGL stuff. This didn't matter for the NVidia case, because it supplied all of the libraries required, but ATI doesn't do that. I had compiled and installed libMesa, so OpenGL should have worked. The OpenGL component is compiled as part of the xorg-server-1.4 package, and its configure script is executed by the build script that came with x.org. Aha, but in order to compile OpenGL, you have to provide the configure script with the path of the libMesa source tree. The x.org build script doesn't do that, so OpenGL is not built. The solution is to interrupt the build at the point where the xorg-server-1.4 is about to be built (you can edit the script and put in an 'exit 0' there, for instance), then configure, build, and install the xorg-server-1.4 archive by hand, remembering to tell it where the mesa source tree is located. Once that completes, you can continue the build with the xorg script (I just commented out all entries above the server compile and resumed).

Now, the font problem. My TTF fonts are in /usr/share/fonts, and I verified that the files there were being read when I asked Emacs to display Chinese characters. So, it appeared as if the Chinese TTF fonts were the ones that were looking bad. A bit of research showed that Emacs does not, as of version 22.1.1, use scalable fonts. So I decided that it probably wasn't supposed to be using those TTF fonts. Now, I had kept my old X11R6 tree around in case of issues like this, so a quick comparison of directories showed that there were some Chinese PCF fonts in the old install that I had forgotten to copy to the new location. So, I copied these files into their location in the X11R7 tree, and Emacs was restored to its former behaviour with respect to the displaying of Chinese fonts. The fonts, by the way, are taipei15.pcf, taipei16.pcf, taipei24.pcf, taipei24k.pcf, and taipeil24.pcf.

Tuesday, March 11, 2008

Selective sendmail relaying based on self-signed keys

Back in the early days of the Internet, people trusted one another not to abuse email. Sure, there were accidents. A badly configured mailing list could fill up with traffic as two vacation programs talked to one another, each informing the other that his latest message would not be read until some later date, because the recipient was out of the office.

In those days, you set up your sendmail to relay messages for others. Many people had email addresses that weren't on a full-time connection to the network, they might be on a BBS that did a nightly download of email, or down some Bitnet rabbit hole. Email was relayed from one intermediate post to another, rather than being simply sent directly from the sender to the receiver. A sendmail daemon that relayed messages for others was helpful to the community, everybody pitched in to get everyone's email where it was ultimately intended.

Then came new developments. Canter & Siegel, the September that never ended, and the presence of people who would buy things they saw in an unsolicited email message. Spam started to appear in mailboxes. Suddenly, being a helpful person and relaying messages was no longer beneficial to the community, as commercial email senders used relays to hide the origins of their messages. People started turning off open relays on their boxes as a defensive move.

So, now you've got a domain set up with a sendmail daemon at home, and you're traveling with a laptop. To make this a bit more complicated, let's say your laptop is a work computer, and you send email from its sendmail, but with a different domain than your home computer. Everything's working fine, until you find that the coffee shop in Beijing where you're using your laptop has made it onto a list of spamming IP numbers. Some recipients of your messages may not receive them because their sendmail is set up to refuse messages from computers on these bad IP numbers. You know that your home computer is not on a banned IP number, so it would be nice if you could forward your laptop-generated work-related messages through your home computer. It would be even nicer if people selling generic pharmaceuticals could not do the same thing, otherwise your home computer's IP number will very quickly find itself on one of those banned lists. So, you want to allow relaying from your laptop, but only from your laptop, and do it easily even if you move to another coffee shop.

What you want, then, is a way for your home computer to recognize your laptop, and permit only that computer to relay messages through the home sendmail. This will be done with sendmail's TLS facility. You will create a private certificate authority, one you don't have to pay to sign your keys. You'll then use a signed certificate to verify the identity of the laptop. The following procedure will be performed on the home computer, only at the end of this process will the laptop be involved.

We'll start by creating two directories on your home computer, one for the certificate authority, and the other for the signed certificates. I'll use the directory locations that are found in the default OpenSSL configuration file, so that you don't have to edit too many files.
mkdir /etc/mail/CA /etc/mail/certs /etc/mail/CA/demoCA /etc/mail/CA/demoCA/private

Copy the OpenSSL openssl.cnf file into /etc/mail/CA.

Next, we will create the signing certificate.
$ cd /etc/mail/CA
$ openssl req -new -x509 -keyout demoCA/private/cakey.pem -out demoCA/cacert.pem -days 1000 -config openssl.cnf
You will be prompted for several fields, such as country code, location, name. Here's a sample dialogue:
$ openssl req -new -x509 -keyout demoCA/private/cakey.pem -out demoCA/cacert.pem -days 1000 -config openssl.cnf
Generating a 1024 bit RSA private key
.............++++++
.........++++++
writing new private key to 'demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:Ontario
Locality Name (eg, city) []:Toronto
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Bert Ificate
Email Address []:bertificate@example.com

When prompted, you will have to enter a pass phrase twice. Remember this phrase, you will need it if you ever want to sign certificates with this signing certificate.

This command creates new files: /etc/mail/CA/demoCA/cacert.pem and /etc/mail/CA/demoCA/private/cakey.pem. The file contains encoded information related to a certificate signing authority that will be valid for 1000 days.

Next, you must create the certificate that you will use to validate your laptop. You enter the commands:
$ cd /etc/mail/CA
$ openssl req -nodes -new -x509 -keyout laptopcert.pem -out laptopcert.pem -days 365 -config openssl.cnf

Again, you will have to answer some questions. Here is a sample dialogue:
$ openssl req -nodes -new -x509 -keyout laptopcert.pem -out laptopcert.pem -days 365 -config openssl.cnf
Generating a 1024 bit RSA private key
....++++++
............................................++++++
writing new private key to 'laptopcert.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:Alberta
Locality Name (eg, city) []:Calgary
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Rhoda Warrior
Email Address []:rhoda-warrior@example.com

Now, you have a certificate for your laptop, but it hasn't yet been signed. You use the signing certificate to vouch for the laptop certificate. First, we have to set up a bit more information for the signing process:
$ mkdir /etc/mail/CA/demoCA/newcerts
$ touch /etc/mail/CA/demoCA/index.txt
$ echo 01 > /etc/mail/CA/demoCA/serial
You'll only have to do this the first time you set up a signing authority.

Now, we issue two commands to sign the laptop certificate:
$ openssl x509 -x509toreq -in laptopcert.pem -signkey laptopcert.pem -out tmp.pem
$ /usr/local/ssl/bin/openssl ca -config openssl.cnf -policy policy_anything -out signed-laptopcert.pem -infiles tmp.pem
Once again, there will be a brief dialogue when the second command is run, something like this:
$ openssl ca -config openssl.cnf -policy policy_anything -out signed-laptopcert.pem -infiles tmp.pem
Using configuration from openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Mar 12 00:46:43 2008 GMT
Not After : Mar 12 00:46:43 2009 GMT
Subject:
countryName = CA
stateOrProvinceName = Alberta
localityName = Calgary
organizationName = Example
commonName = Rhoda Warrior
emailAddress = rhoda-warrior@example.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
67:11:5A:25:6F:5C:70:36:03:14:3B:04:4A:8C:30:C9:CF:60:51:AE
X509v3 Authority Key Identifier:
keyid:F4:CE:58:BD:82:8A:E3:EC:0F:89:C6:60:E2:45:58:A4:CA:79:C8:89

Certificate is to be certified until Mar 12 00:46:43 2009 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated


Now, it's time to tell the home machine's sendmail that it should relay messages received from this key. Add a line to the /etc/mail/access.src file that looks like this:
CertIssuer:/C=CA/ST=Ontario/L=Toronto/O=Example/CN=Bert+20Ificate/emailAd
dress=bertificate@example.com RELAY

You'll have to make that file readable by sendmail:
makemap hash access.db < access.src


And now we have to make sure that the home machine's sendmail knows where to find its certificates and access file. Build a new sendmail.cf using a sendmail.mc something like this:
divert(0)dnl
VERSIONID(`sendmail.mc for example.com version 01')
OSTYPE(linux)dnl
DOMAIN(example.com)dnl
FEATURE(`nouucp', `reject')
FEATURE(`virtusertable', `hash /etc/sendmail/virtusertable')dnl
FEATURE(`genericstable', `hash /etc/sendmail/genericstable')dnl
FEATURE(`local_procmail', `/usr/local/bin/procmail')
FEATURE(`access_db', `hash -T<TMPF> /etc/mail/access')
FEATURE(`mailertable')
MAILER(local)
MAILER(smtp)
define(`CERT_DIR', `MAIL_SETTINGS_DIR`'certs')dnl
define(`confCACERT_PATH', `CERT_DIR')dnl
define(`confCACERT', `CERT_DIR/CAcert.pem')dnl
define(`confSERVER_CERT', `CERT_DIR/MYcert.pem')dnl
define(`confSERVER_KEY', `CERT_DIR/MYkey.pem')dnl
define(`confCLIENT_CERT', `CERT_DIR/MYcert.pem')dnl
define(`confCLIENT_KEY', `CERT_DIR/MYkey.pem')dnl


Now, we move some things around a bit. We copy the signing certificate and laptop signed certificate like this:
$ cd /etc/mail/CA
$ /bin/cp signed-laptopcert.pem /etc/mail/certs
$ /bin/cp demoCA/cacert.pem /etc/mail/certs/CAcert.pem
$ cd /etc/mail/certs
$ ln -s signed-laptopcert.pem `openssl x509 -noout -hash < signed-laptopcert.pem`.0

The three files, demoCA/cacert.pem, laptopcert.pem and signed-laptopcert.pem get copied onto the laptop, in its /etc/mail/certs directory. Now, you must tell the laptop's sendmail that these are its certificates. This is done by building (on the laptop) the sendmail.cf file from a sendmail.mc file that looks roughly like this:
divert(0)dnl
VERSIONID(`$Id: generic-linux.mc,v 8.1 1999/09/24 22:48:05 gshapiro Exp $')
OSTYPE(linux)dnl
DOMAIN(example.net)dnl
define(`confCACERT_PATH', `/etc/mail/certs/')
define(`confCACERT', `/etc/mail/certs/cacert.pem')
define(`confCLIENT_CERT', `/etc/mail/certs/laptopcert.pem')
define(`confCLIENT_KEY', `/etc/mail/certs/signed-laptopcert.pem')
define(`confSERVER_CERT', `/etc/mail/certs/laptopcert.pem')
define(`confSERVER_KEY', `/etc/mail/certs/signed-laptopcert.pem')
FEATURE(`genericstable')
FEATURE(`virtusertable')
FEATURE(`local_procmail', `/usr/local/bin/procmail')
MAILER(local)dnl
MAILER(smtp)dnl

Finally, you'll have to decide when you want to relay through the home computer. You really have two choices. You could set it up so that all messages are always relayed through the home computer, by setting a smart relay in your sendmail.cf, or you could relay them explicitly. There are other places that identify the technique for setting up a smart relay, so I'll just describe the second, on-demand version.

If you are trying to send email from your laptop to the user somebody@example.net, but want to relay it through your home computer at example.com, you would send the message to this email address:
somebody%example.net@example.com


And there you go, on-demand secure relaying of messages through your home computer.