Tackling your three suggestions in order ...
- Using crypt() assumes that you have crypt()ed passwords. While this may be the case on some systems, it isn't on all of 'em. For instance, if you enable "shadow" passwords and md5 passwords on Linux (both of which are good ideas) this won't work. It's certainly not portable.
- A non-root process can't switch to another UID. You could spawn su, and then use su to run another copy of your perl program with the new priveleges to do the real work. But I'd be very very careful about this. As an aside, this is just the situation where suidperl might be helpful.
- Yes, use PAM for authentication. Don't pretend to be something you're not though, as you want PAM to log accurate information.