Fun with Mozilla, emacs, PAM, WU-FTPD, and MT
So today I decided I should set up a web log to keep track of my exploits. Who else would the uninitiated turn to except Blogger ?
I go to Blogger’s site, create an account, and then set about creating
an FTP-only account on my system. By “FTP-only” I mean an account
that is unable to do anything (including log in to SSH) except FTP in.
Anonymous users won’t work for this since I need the account to be
password’ed (and separate from the ”
ftp
” user, anyway).
A regular account won’t do because I don’t want to give anyone that
manages to crack Blogger a login and password to my server. One would
think this is something that people do all the time, a fairly trivial
task. I mean to foreshadow, of course, that one would be wrong in
this assumption.
First step to creating such an account with WU-FTPD (default on Red
Hat systems, and mine is RH 7.1) is creating a regular system account,
but with a valid-but-useless shell and with a specially formatted
string for their home directory. I used
/sbin/nologin
for the shell, which comes in RH’s util-linux package; I had to
manually list the shell in /etc/shells to satisfy the “valid” part of
“valid-but-useless”. The home directory needs to look like
/PATH/TO/CHDIR/./PATH/TO/HOME
. Note the
/.
in the middle, which tells WU-FTPD that when this user logs in it
should first chroot to
/PATH/TO/CHDIR
then chdir to
/PATH/TO/HOME
.
Next you have to signal the user you just created as a “guest user”
with the
guestuser <username>
directive in
/etc/ftpaccess
. This combined with the fun home
directory above will cause WU-FTPD to chroot this user when they log
in.
Most people pretty much stop here. They assign the account a
password, try logging in (
/sbin/nologin
sends back a
pretty message and then promptly exits) and leave it at that. My fear
is that another service, such as POP3, might still authenticate the
user if I ever decide to use it in the future and forget about my FTP
user I just created. Worse, they might be able to have SSH forward
ports and connect to them before the login shell could terminate. Not
acceptable.
WU-FTPD seems to have little solution for this problem. It has some support for virtual “domains” (really IP addresses, I believe), but using this points it to a whole separate password file as near as I can tell. I want to authenticate both system accounts and FTP-only accounts, so this won’t work. (I wouldn’t be surprised to find that I missed something in WU-FTPD’s configuration, so someone please feel free to enlighten me.)
Instead, I ended up at PAM . Miraculously, this allowed me to do exactly what I want without any real compiling of programs. (I’m kind of lying here since, in the process of debugging things, I may have compiled something. Someone that doesn’t make stupid mistakes, though, can follow what I did without touching gcc’n'friends.) I took my /etc/pam.d/ftp file, which looked like this:
#%PAM-1.0 auth required /lib/security/pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed auth required /lib/security/pam_stack.so service=system-auth auth required /lib/security/pam_shells.so account required /lib/security/pam_stack.so service=system-auth session required /lib/security/pam_stack.so service=system-auth
and changed it to this:
#%PAM-1.0 auth required /lib/security/pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed auth required /lib/security/pam_shells.so #auth required /lib/security/pam_stack.so service=system-auth # From system-auth, slightly modified. auth required /lib/security/pam_env.so auth sufficient /lib/security/pam_userdb.so db=/etc/ftppasswd auth sufficient /lib/security/pam_unix.so likeauth nullok auth required /lib/security/pam_deny.so account required /lib/security/pam_stack.so service=system-auth session required /lib/security/pam_stack.so service=system-auth
This basically tells PAM to first try authenticating from a Berkeley DB file /etc/ftppasswd.db first, then try authenticating using normal system mechanisms. If either of these succeed, the user is authenticated. Then to create the DB file, something like:
[darkness@darkness darkness]$ db_load -t hash -T ftppasswd.db user password ^D [darkness@darkness darkness]$
You can dump the database like:
[darkness@darkness darkness]$ db_dump -p ftppasswd.db VERSION=2 format=print type=hash h_nelem=1 HEADER=END user password DATA=END [darkness@darkness darkness]$
Incidentally, you can take the output from
db_dump
and feed
it right back in to
db_load
; just leave off the
-t
hash -T
part. There is also a create.pl file that comes with
Linux-PAM that will do something similar to the above, but I couldn’t
find it in the RH packages so I didn’t really bother with it.
This should be pretty much it. Make sure your FTP user has a disabled
password in
/etc/shadow
(second field for the user’s line
should have something like
!!
in it). Now when they
connect via FTP they’ll be authenticated from our separate password
database, but if they connect via any other service they’ll be unable
to authenticate. Some gotchas:
Don’t be an idiot like I was and spend hours figuring out why all you see in the logs is:
Sep 17 19:12:28 darkness pam_userdb[6802]: user 'my-ftp-user' granted acces Sep 17 19:12:28 darkness ftp(pam_unix)[6802]: authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=localhost user=my-ftp-user
If you get to pam_unix after pam_userdb reports that it “granted acces sic” that means that one of the required modules above it failed. In my case, pam_shells.so was failing because I forgot to put
/sbin/nologinin /etc/shells. (Note: RH 7.1 didn’t have it in there, but another system with RH 7.3 already did, so it may be default now.)- You can put
debugon the end of just about any PAM module and it might spit out debugging information. - Note that while I called my database file
ftppasswd.db, you leave the.dboff the database name when specifying it to pam_userdb.
So now I was reasonably happy. I had Blogger. I had an FTP-only user that Blogger was going to upload to. Feeling good about myself I speed Mozilla to Blogger’s site, log in, click something on their site and POOF no more Mozilla. What’s this? Mozilla has been solid for quite some time now! After repeating this a couple of times, I opt to check my version. GASP! 0.9.9! Oh horror of horrors, 1.1 is out and 1.2a as well, yet I’m wasting away in the lowly depths of a pre-release. Then I remember why: RH 7.3 didn’t ship with Mozilla 1.0 (presumably for QA, compatibility, and/or release deadlines). Luckily, Mozilla has RPMs built just for me and RH 7.x.
A bit later I’ve upgraded to Mozilla 1.1 and I’m once again fairly happy. I then become distressed at the size of the text entry field on the Blogger UI; I run at 1024×768, and this thing wasn’t too nice. Then I remember the slight pain of entering in text in a Mozilla text input widget. Pain enough to make me seek out MozBlog . Their site was down yesterday, but apparently came up today.
I get (don’t forget to install
JsLib
first). I install (don’t
forget to run Mozilla as root to install stuff). It… does
weird shit
.
OK, I read the bug report, find a couple newer versions, install them.
After blowing away
~/.mozilla
a time or two, I’m getting
messages like “error! Null” when I start Mozilla up. Luckily I found
somewhere that you need to seek out
discussProfile.rdf
and
blogHistory.rdf
in
~/.mozilla
and chmod
them 600 or so. Now no more errors on startup. I edit my
preferences, set up my Blogger web log; it pings, I get happy. Then I
realize I have no idea how to pull up this magical MozBlog log entry
dialog.
Alt-` I see in some places? Nope. Finally I realize I need to bring up the “Bottombar”, which strikes me as some sort of obscene reference. Now I am graced with the MozBlog interface, which does everything it’s supposed to just fine. Of course, I’m still not satisfied.
It only has a limited number of formatting styles (bold and italics, IIRC; no underline, for example). What appear to be its attempt at “styles” don’t seem to reset from one to the next correctly (though I may have been using it wrong). You can’t insert markup in normal mode. You switch to what looks like “source mode”, as in editing HTML source, and it… tries to stick my log entry on one big line? Not having it. Plus, this text widget feel suspiciously like the normal text widget, with a bigger font size. Uh uh, not having it.
So the Bottombar goes back to the … bottom, and I start thinking about an interface I’d like. Then I realize the answer: Emacs. I’ve been way in to Emacs lately, writing Elisp and everything. I find blogger.el . It requires xml-rpc.el . This, in turn, requires something called “URL” for Emacs. Go to the GNU site for “URL loader” , which is apparently destined to be part of the new Emacs/W3 , and find their CVS pserver to be down. wget’ing their WebCVS interface isn’t happening either. So instead I find what I guess is the old Emacs/W3 page and grab the entire Emacs/W3 from them. Compile, shove in load-path, and I’m now making web log entries from Emacs. Works fabulously. Emacs never ceases to amaze me these days.
By now you’d think I’d be content. Not so, though, as someone starts telling me about Movable Type , which is actually a set of Perl CGI’s that comprise an entire web log management system. (Probably has features beyond this too; I didn’t get much chance to look at it.) Follow the install instructions and you’ll mostly be OK. Don’t forget to run mt-load.cgi (I wonder how many MT web logs still have this file lying about?) before going to mt.cgi. I set mine up in mod_perl; if you do this, be aware of mod_perl instructions for Movable Type . Follow these after you run mt-check.cgi and mt-load.cgi, but before hitting /mt for the first time. My directory structure looks like:
site-directory/
document-root/ # This is DocumentRoot in Apache configuration.
blogs/ # This is where I keep my users' blogs.
users...
mt-static/ # This contains docs and images from the
docs/ # MT distribution.
images/
perl-bin/ # I need this here to house mt-xmlrpc.cgi.
data/
mt/
db/ # Make sure this is writable by Apache's user.
tmpl/ # tmpl and import from the MT distribution.
import/
lib/
mt/
lib/ # This is lib from the MT distribution.
I get errors from time to time, at least during initial setup. Creating a blog would fail, but the blog would be there when I go back to the menu. I could usually delete it, recreate it, and it would bring me to the prefs screen. Don’t forget to hit “Rebuild Site” after you first create a web log or there won’t be any files in the user’s blog directory. Also note that you seem to have to have a blog created to start editing “authors” (or “users” as I like to think of them). So I created an admin user, created a “System Blog”, then created my normal user and its blog. I can probably delete the “System Blog” I guess.
Now I was pretty much happy. Except… titles. MT uses them, blogger.el doesn’t apparently. I think this is because all this stuff was based on the original blogger API which didn’t (doesn’t?) support them. So I made a tiny patch to mt-xmlrpc.cgi from MT 2.21:
--- MT-2.21/mt-xmlrpc.cgi Mon Jun 24 15:10:38 2002
+++ /srv/www/www.codefu.org/perl-bin/mt-xmlrpc.cgi Wed Sep 18 03:27:45 2002@@ -97,6 +97,9 @@
my($appkey, $blog_id, $user, $pass, $item, $publish);
if ($class eq 'blogger') {
($appkey, $blog_id, $user, $pass, my($content), $publish) = @_;
+ if ($content =~ s/^title=([^\n]+)\n+//s) {
+ chomp ($item->{title} = $1);
+ }
$item->{description} = $content;
} else {
($blog_id, $user, $pass, $item, $publish) = @_;
@@ -147,6 +150,9 @@
my($appkey, $entry_id, $user, $pass, $item, $publish);
if ($class eq 'blogger') {
($appkey, $entry_id, $user, $pass, my($content), $publish) = @_;
+ if ($content =~ s/^title=([^\n]+)\n+//s) {
+ chomp ($item->{title} = $1);
+ }
$item->{description} = $content;
} else {
($entry_id, $user, $pass, $item, $publish) = @_;
This allows you to specify “title=” as the first line in a log entry on a line by itself. Any blank lines following this line are deleted. This patch really isn’t complete yet and probably isn’t very nice, but it works for me. I don’t think it’ll put in this title= when retrieving a post, which it probably should — and which I’ll probably do later.
So now I’m happy, and as you may have noticed, I’m blogging from Emacs. And I have a completely useless FTP-only account.
Man, “blogging” sounds stupid. I’m sorry.
(And then as I upload this and see how shitty it looks, I have to turn off auto-convert line breaks, insert my own paragraph breaks, turn off auto-linking… Oh the joy.)