Hello ppl,
I have been working with qpopper 2.4 and Dec Unix 4.0b, running on an
Alpha. Here is the situation. I dont know if it has been already released
before but, there is a security bug involving qpopper and C2 security.
Much like the wu-ftpd bug, it does not keep track of the ammount of
unsuccessful logins. There are programs out on the net that can brute
force this exploit.
With this in mind, I have been trying to apply a patch to this bug,
following the code released sometime ago by Dave Diehl, for qpopper 2.4.
However my programming C skills are somewhat new and I cannot seem to get
proper authetication with the patch. I have attached qpopper's code for
OSF and my version ( including the patch ). Any help would be much
appreciated.
Thanks
._._._._._._._._._._._._._._._._._._._._._._._._.
| | |
| Douglas Meldrum | A tiny lil bit in a |
| Network Coordinator | stream of bytes being |
| Delphi Supernet | bridge, routed, |
| .o0o. | filtered and dumped |
| | into someone's bit |
| "Eschew obfuscation" | bucket. |
| | |
.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Copyright (c) 1997 by Qualcomm Incorporated.
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#include <pwd.h>
#include "popper.h"
#define SLEEP_SECONDS 10
/* This error message is vague on purpose to help reduce help improve
security at the inconvience of administrators and users */
char *pwerrmsg = "Password supplied for \"%s\" is incorrect.";
#ifdef NONAUTHFILE
checknonauthfile(user)
char *user;
{
char buf[MAXUSERNAMELEN+1];
FILE *fp;
char cool = 0;
if ((fp = fopen(NONAUTHFILE, "r")) != NULL) {
while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
buf[strlen(buf) -1] = '\0';
if (!strcmp(buf, user)) {
fclose(fp);
return(-1);
}
}
fclose(fp);
}
return(0);
}
#endif
#ifdef AUTHFILE
checkauthfile(user)
char *user;
{
char buf[MAXUSERNAMELEN+1];
FILE *fp;
char cool = 0;
if ((fp = fopen(AUTHFILE, "r")) != NULL) {
while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
buf[strlen(buf) -1] = '\0';
if (!strcmp(buf, user)) {
fclose(fp);
return(0);
}
}
fclose(fp);
}
return(-1);
}
#endif
int auth_user_kerberos (p, pw)
POP * p;
struct passwd *pw;
{
#ifdef KERBEROS
char lrealm[REALM_SZ];
int status;
struct passwd *pwp;
if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) %s", p->client, kdata.pname,
kdata.pinst, kdata.prealm, krb_err_txt[status]);
return(pop_msg(p,POP_FAILURE,
"Kerberos error: \"%s\".", krb_err_txt[status]));
}
# ifdef KUSEROK
if (kuserok(&kdata, p->user)) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s): not in %s's ACL.",
p->client, kdata.pname, kdata.pinst, kdata.prealm, p->user);
return(pop_msg(p,POP_FAILURE, "Not in %s's ACL.", p->user));
}
# else
if (strcmp(kdata.prealm,lrealm)) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) realm not accepted.",
p->client, kdata.pname, kdata.pinst, kdata.prealm);
return(pop_msg(p,POP_FAILURE,
"Kerberos realm \"%s\" not accepted.", kdata.prealm));
}
if (strcmp(kdata.pinst,"")) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) instance not accepted.",
p->client, kdata.pname, kdata.pinst, kdata.prealm);
return(pop_msg(p,POP_FAILURE,
"Must use null Kerberos(tm) instance - \"%s.%s\" not accepted.",
kdata.pname, kdata.pinst));
}
# endif /* KUSEROK */
return(POP_SUCCESS);
#else /* Kerberos not defined */
return(pop_log(p, LOG_WARNING,
"Kerberos failure: The popper has not been compiled with -DKERBEROS"));
#endif /* KERBEROS */
}
#ifdef AUTH
char *crypt();
#if defined(SUNOS4) && !defined(ISC)
#include <sys/label.h>
#include <sys/audit.h>
#include <pwdadj.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
struct passwd_adjunct *pwadj;
/* Look for the user in the shadow password file */
if ((pwadj = getpwanam(p->user)) == NULL) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,
"(shadow) Password supplied for \"%s\" is empty.",p->user));
} else {
pw->pw_passwd = (char *)strdup(pwadj->pwa_passwd);
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* SUNOS4 */
#if defined(SOLARIS2) || defined(AUX)
#include <shadow.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
today = (long)time((time_t *)NULL)/24/60/60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
endspent();
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p, POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* SOLARIS2 || AUX */
#if defined(PTX) || defined(ISC)
#include <shadow.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* PTX */
#if defined(POPSCO) || defined(HPUX10)
#ifdef POPSCO
# include <sys/security.h>
# include <sys/audit.h>
#else
# include <hpsecurity.h>
#endif
#include <prot.h>
#define PASSWD(p) p->ufld.fd_encrypt
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct pr_passwd *pr;
if ((pr = getprpwnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
/* We don't accept connections from users with null passwords */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
(strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(crypt (p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))) {
sleep(SLEEP_SECONDS);
return(pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((PASSWD(pr) == NULL) || (*PASSWD(pr) == '\0')) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
if (strcmp(bigcrypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr)) &&
strcmp(crypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr))) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
}
return(POP_SUCCESS);
}
#endif /* POPSCO || HPUX10 */
#ifdef ULTRIX
#include <auth.h>
static int
auth_user(p, pw)
struct passwd * pw;
POP * p;
{
AUTHORIZATION *auth, *getauthuid();
if ((auth = getauthuid(pw->pw_uid)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
pw->pw_passwd = (char *)strdup(auth->a_password);
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0')) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
if (strcmp(crypt16(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* ULTRIX */
#ifdef OSF1
#include <sia.h>
#include <siad.h>
#include <sys/types.h>
#include <sys/security.h>
#include <prot.h>
/* #define PASSWD(p) (p->ufld.fd_encrypt) */
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
int osf_check_pass(char user[32], char *passwd)
{
register struct pr_passwd *pr;
if ((pr = getprpwnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else { */
pw->pw_passwd = (char *)strdup(PASSWD(pr));
}
/* Enhanced C2 security code */
if (osf_check_pass(user, pw->pw_passwd) <0) {
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
/* We don't accept connections from users with null passwords
Compare the supplied password with the password file entry
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0')) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
if (strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
*/
return(POP_SUCCESS);
}
/*
Enhanced C2 security code for keeping track of the number of login attempts
*/
in sia_collect_null(int timeout, int rendition, unsigned char *title, int num_pr
ompts, prompt_t *prompt)
{
return SIACOLSUCCESS;
}
static int
osf_check_passs(char user[32], char *passwd)
{
SIAENTITY *entity = NULL;
/* char uname[32]; */
int auth_status;
int argc = 1;
char *argv[2];
argv[0] = "popper";
argv[1] = (char *) 0;
set_auth_parameters(argc, argv);
/* (void) strcpy(uname, pw->pw_name); */
aut_status = sia_ses_init(&entity, argc, argv, NULL, user, NULL, FALSE, NUL
L);
if (auth_status != SIASUCCESS)
{
syslof(LOG_ERR, "sia_ses_init() failed in osf_check_pass");
return -1;
}
if (pw == (struct passwd *) NULL) {
return -1;
}
auth_status = sia_ses_authent(sia_collect_null, passwd, enntity);
if (auth_status != SIASUCCESS) {
return -1;
}
auth_status = sia_ses_estab(sia_collect_null, entity);
if (auth_status != SIASUCCESS)
{
syslog(LOG_WARNING, "sia_ses_estab() failed in osf_check_pass");
return -1;
}
auth_status = sia_ses_release(&entity);
if (auth_status != SIASUCCESS)
{
syslog(LOG_ERR, "sia_ses_release() failed ion osf_check_pass");
return -1;
}
return 0;
}
#endif /* OSF1 */
#ifdef UNIXWARE
#include <shadow.h>
static int
auth_user(p, pw)
struct passwd * pw;
POP * p;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
today = (long)time((time_t *)NULL)/24/60/60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
endspent();
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* UNIXWARE */
#ifdef LINUX
#include <shadow.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
today = (long)time((time_t *)NULL)/24/60/60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
endspent();
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
/* pw_encrypt() ?? */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
(strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(pw_encrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))){
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* LINUX */
#else /* NOT AUTH */
char *crypt();
static int
auth_user(p, pw)
POP * p;
struct passwd * pw;
{
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* AUTH */
/*
* pass: Obtain the user password from a POP client
*/
#ifdef SECURENISPLUS
/* AUTH gets defined in rpc/... */
# ifdef AUTH
# undef AUTH
# endif
# include <rpc/rpc.h>
# include <rpc/key_prot.h>
#endif
int pop_pass (p)
POP * p;
{
struct passwd pw, *pwp;
#ifdef CHECK_SHELL
char *getusershell();
void endusershell();
char *shell;
char *cp;
int shellvalid;
#endif
#ifdef SECURENISPLUS
UID_T uid_save;
char net_name[MAXNETNAMELEN],
secretkey[HEXKEYBYTES + 1];
*secretkey = '\0';
#endif
#ifdef NONAUTHFILE
/* Is the user not authorized to use POP? */
if (checknonauthfile(p->user) != 0) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
#endif
#ifdef AUTHFILE
/* Is the user authorized to use POP? */
if (checkauthfile(p->user) != 0) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
#endif
/* Look for the user in the password file */
if ((pwp = getpwnam(p->user)) == NULL) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
pw = *pwp;
#ifdef SECURENISPLUS
/* we must do this keyserv stuff (as well as auth_user()!) as the user */
uid_save = geteuid();
seteuid(pw.pw_uid);
/* see if DES keys are already known to the keyserv(1m) */
if (! key_secretkey_is_set()) {
/* keys are not known, so we must get the DES keys
and register with the keyserv(1m) */
getnetname(net_name);
if (getpublickey(net_name, secretkey)) {
if (strlen(p->pop_parm[1]) > 8) (p->pop_parm[1])[8] = '\0';
if (! getsecretkey(net_name, secretkey, p->pop_parm[1]) ||
*secretkey == '\0') {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
key_setsecret(secretkey);
memset(secretkey, '\0', sizeof(secretkey));
} else {
/* if there are no keys defined, we assume that password entry
either resides in /etc/shadow or "root" has access to the
corresponding NIS+ entry */
seteuid(0);
}
}
#endif
#ifdef BLOCK_UID
if (pw.pw_uid <= BLOCK_UID)
return (pop_msg(p,POP_FAILURE,
"Access is blocked for UIDs below %d", BLOCK_UID));
#endif
#ifdef CHECK_SHELL
/* Disallow anyone who does not have a standard shell as returned by
* getusershell(), unless the sys admin has included the wildcard
* shell in /etc/shells. (default wildcard - /POPPER/ANY/SHELL)
*/
if ((shell = pw.pw_shell) == NULL || *shell == 0)
/* You can default the shell, but I don't think it's a good idea */
/* shell = "/usr/bin/sh"; */
return(pop_msg(p, POP_FAILURE, "No user shell defined"));
for (shellvalid = 0; !shellvalid && ((cp = getusershell()) != NULL);)
if (!strcmp(cp, WILDCARD_SHELL) || !strcmp(cp, shell))
shellvalid = 1;
endusershell();
if (!shellvalid)
return(pop_msg(p, POP_FAILURE, "\"%s\": shell not found.", p->user));
#endif
if ((p->kerberos ? auth_user_kerberos(p, pw) : auth_user(p, pwp))
!= POP_SUCCESS) {
pop_log(p,POP_PRIORITY,"Failed attempted login to %s from host %s",
p->user, p->client);
return(POP_FAILURE);
}
#ifdef SECURENISPLUS
seteuid(uid_save);
#endif
/* Make a temporary copy of the user's maildrop */
/* and set the group and user id */
/* and get information about the maildrop */
if (pop_dropcopy(p, &pw) != POP_SUCCESS) return (POP_FAILURE);
/* Initialize the last-message-accessed number */
p->last_msg = 0;
/* Authorization completed successfully */
return (pop_msg (p,POP_SUCCESS,
"%s has %d message%s (%d octets).",
p->user,p->msg_count, p->msg_count == 1 ? "" : "s", p->drop_size));
}
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Copyright (c) 1997 by Qualcomm Incorporated.
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#include <pwd.h>
#include "popper.h"
#define SLEEP_SECONDS 10
/* This error message is vague on purpose to help reduce help improve
security at the inconvience of administrators and users */
char *pwerrmsg = "Password supplied for \"%s\" is incorrect.";
#ifdef NONAUTHFILE
checknonauthfile(user)
char *user;
{
char buf[MAXUSERNAMELEN+1];
FILE *fp;
char cool = 0;
if ((fp = fopen(NONAUTHFILE, "r")) != NULL) {
while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
buf[strlen(buf) -1] = '\0';
if (!strcmp(buf, user)) {
fclose(fp);
return(-1);
}
}
fclose(fp);
}
return(0);
}
#endif
#ifdef AUTHFILE
checkauthfile(user)
char *user;
{
char buf[MAXUSERNAMELEN+1];
FILE *fp;
char cool = 0;
if ((fp = fopen(AUTHFILE, "r")) != NULL) {
while (fgets(buf, MAXUSERNAMELEN+1, fp)) {
buf[strlen(buf) -1] = '\0';
if (!strcmp(buf, user)) {
fclose(fp);
return(0);
}
}
fclose(fp);
}
return(-1);
}
#endif
int auth_user_kerberos (p, pw)
POP * p;
struct passwd *pw;
{
#ifdef KERBEROS
char lrealm[REALM_SZ];
int status;
struct passwd *pwp;
if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) %s", p->client, kdata.pname,
kdata.pinst, kdata.prealm, krb_err_txt[status]);
return(pop_msg(p,POP_FAILURE,
"Kerberos error: \"%s\".", krb_err_txt[status]));
}
# ifdef KUSEROK
if (kuserok(&kdata, p->user)) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s): not in %s's ACL.",
p->client, kdata.pname, kdata.pinst, kdata.prealm, p->user);
return(pop_msg(p,POP_FAILURE, "Not in %s's ACL.", p->user));
}
# else
if (strcmp(kdata.prealm,lrealm)) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) realm not accepted.",
p->client, kdata.pname, kdata.pinst, kdata.prealm);
return(pop_msg(p,POP_FAILURE,
"Kerberos realm \"%s\" not accepted.", kdata.prealm));
}
if (strcmp(kdata.pinst,"")) {
pop_log(p, LOG_WARNING, "%s: (%s.%s@%s) instance not accepted.",
p->client, kdata.pname, kdata.pinst, kdata.prealm);
return(pop_msg(p,POP_FAILURE,
"Must use null Kerberos(tm) instance - \"%s.%s\" not accepted.",
kdata.pname, kdata.pinst));
}
# endif /* KUSEROK */
return(POP_SUCCESS);
#else /* Kerberos not defined */
return(pop_log(p, LOG_WARNING,
"Kerberos failure: The popper has not been compiled with -DKERBEROS"));
#endif /* KERBEROS */
}
#ifdef AUTH
char *crypt();
#if defined(SUNOS4) && !defined(ISC)
#include <sys/label.h>
#include <sys/audit.h>
#include <pwdadj.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
struct passwd_adjunct *pwadj;
/* Look for the user in the shadow password file */
if ((pwadj = getpwanam(p->user)) == NULL) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,
"(shadow) Password supplied for \"%s\" is empty.",p->user));
} else {
pw->pw_passwd = (char *)strdup(pwadj->pwa_passwd);
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* SUNOS4 */
#if defined(SOLARIS2) || defined(AUX)
#include <shadow.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
today = (long)time((time_t *)NULL)/24/60/60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
endspent();
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p, POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* SOLARIS2 || AUX */
#if defined(PTX) || defined(ISC)
#include <shadow.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* PTX */
#if defined(POPSCO) || defined(HPUX10)
#ifdef POPSCO
# include <sys/security.h>
# include <sys/audit.h>
#else
# include <hpsecurity.h>
#endif
#include <prot.h>
#define PASSWD(p) p->ufld.fd_encrypt
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct pr_passwd *pr;
if ((pr = getprpwnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
/* We don't accept connections from users with null passwords */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
(strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(crypt (p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))) {
sleep(SLEEP_SECONDS);
return(pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((PASSWD(pr) == NULL) || (*PASSWD(pr) == '\0')) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
if (strcmp(bigcrypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr)) &&
strcmp(crypt(p->pop_parm[1], PASSWD(pr)), PASSWD(pr))) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
}
return(POP_SUCCESS);
}
#endif /* POPSCO || HPUX10 */
#ifdef ULTRIX
#include <auth.h>
static int
auth_user(p, pw)
struct passwd * pw;
POP * p;
{
AUTHORIZATION *auth, *getauthuid();
if ((auth = getauthuid(pw->pw_uid)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
pw->pw_passwd = (char *)strdup(auth->a_password);
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0')) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
if (strcmp(crypt16(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* ULTRIX */
#ifdef OSF1
#include <sys/types.h>
#include <sys/security.h>
#include <prot.h>
#define PASSWD(p) (p->ufld.fd_encrypt)
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct pr_passwd *pr;
if ((pr = getprpwnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
pw->pw_passwd = (char *)strdup(PASSWD(pr));
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0')) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
if (strcmp(bigcrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* OSF1 */
#ifdef UNIXWARE
#include <shadow.h>
static int
auth_user(p, pw)
struct passwd * pw;
POP * p;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
today = (long)time((time_t *)NULL)/24/60/60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
endspent();
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* UNIXWARE */
#ifdef LINUX
#include <shadow.h>
static int
auth_user(p, pw)
POP * p;
struct passwd *pw;
{
register struct spwd * pwd;
long today;
/* Look for the user in the shadow password file */
if ((pwd = getspnam(p->user)) == NULL) {
if (!strcmp(pw->pw_passwd, "x")) { /* This my be a YP entry */
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
} else {
today = (long)time((time_t *)NULL)/24/60/60;
/* Check for expiration date */
if (pwd->sp_expire > 0 && today > pwd->sp_expire) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
/* Check if password is valid */
if (pwd->sp_max > 0 && today > pwd->sp_lstchg+pwd->sp_max) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE,"\"%s\": account expired.",p->user));
}
pw->pw_passwd = (char *)strdup(pwd->sp_pwdp);
endspent();
}
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
/* pw_encrypt() ?? */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
(strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd) &&
strcmp(pw_encrypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))){
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* LINUX */
#else /* NOT AUTH */
char *crypt();
static int
auth_user(p, pw)
POP * p;
struct passwd * pw;
{
/* We don't accept connections from users with null passwords */
/* Compare the supplied password with the password file entry */
if ((pw->pw_passwd == NULL) || (*pw->pw_passwd == '\0') ||
strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd)) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
return(POP_SUCCESS);
}
#endif /* AUTH */
/*
* pass: Obtain the user password from a POP client
*/
#ifdef SECURENISPLUS
/* AUTH gets defined in rpc/... */
# ifdef AUTH
# undef AUTH
# endif
# include <rpc/rpc.h>
# include <rpc/key_prot.h>
#endif
int pop_pass (p)
POP * p;
{
struct passwd pw, *pwp;
#ifdef CHECK_SHELL
char *getusershell();
void endusershell();
char *shell;
char *cp;
int shellvalid;
#endif
#ifdef SECURENISPLUS
UID_T uid_save;
char net_name[MAXNETNAMELEN],
secretkey[HEXKEYBYTES + 1];
*secretkey = '\0';
#endif
#ifdef NONAUTHFILE
/* Is the user not authorized to use POP? */
if (checknonauthfile(p->user) != 0) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
#endif
#ifdef AUTHFILE
/* Is the user authorized to use POP? */
if (checkauthfile(p->user) != 0) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
#endif
/* Look for the user in the password file */
if ((pwp = getpwnam(p->user)) == NULL) {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
pw = *pwp;
#ifdef SECURENISPLUS
/* we must do this keyserv stuff (as well as auth_user()!) as the user */
uid_save = geteuid();
seteuid(pw.pw_uid);
/* see if DES keys are already known to the keyserv(1m) */
if (! key_secretkey_is_set()) {
/* keys are not known, so we must get the DES keys
and register with the keyserv(1m) */
getnetname(net_name);
if (getpublickey(net_name, secretkey)) {
if (strlen(p->pop_parm[1]) > 8) (p->pop_parm[1])[8] = '\0';
if (! getsecretkey(net_name, secretkey, p->pop_parm[1]) ||
*secretkey == '\0') {
sleep(SLEEP_SECONDS);
return (pop_msg(p,POP_FAILURE, pwerrmsg, p->user));
}
key_setsecret(secretkey);
memset(secretkey, '\0', sizeof(secretkey));
} else {
/* if there are no keys defined, we assume that password entry
either resides in /etc/shadow or "root" has access to the
corresponding NIS+ entry */
seteuid(0);
}
}
#endif
#ifdef BLOCK_UID
if (pw.pw_uid <= BLOCK_UID)
return (pop_msg(p,POP_FAILURE,
"Access is blocked for UIDs below %d", BLOCK_UID));
#endif
#ifdef CHECK_SHELL
/* Disallow anyone who does not have a standard shell as returned by
* getusershell(), unless the sys admin has included the wildcard
* shell in /etc/shells. (default wildcard - /POPPER/ANY/SHELL)
*/
if ((shell = pw.pw_shell) == NULL || *shell == 0)
/* You can default the shell, but I don't think it's a good idea */
/* shell = "/usr/bin/sh"; */
return(pop_msg(p, POP_FAILURE, "No user shell defined"));
for (shellvalid = 0; !shellvalid && ((cp = getusershell()) != NULL);)
if (!strcmp(cp, WILDCARD_SHELL) || !strcmp(cp, shell))
shellvalid = 1;
endusershell();
if (!shellvalid)
return(pop_msg(p, POP_FAILURE, "\"%s\": shell not found.", p->user));
#endif
if ((p->kerberos ? auth_user_kerberos(p, pw) : auth_user(p, pwp))
!= POP_SUCCESS) {
pop_log(p,POP_PRIORITY,"Failed attempted login to %s from host %s",
p->user, p->client);
return(POP_FAILURE);
}
#ifdef SECURENISPLUS
seteuid(uid_save);
#endif
/* Make a temporary copy of the user's maildrop */
/* and set the group and user id */
/* and get information about the maildrop */
if (pop_dropcopy(p, &pw) != POP_SUCCESS) return (POP_FAILURE);
/* Initialize the last-message-accessed number */
p->last_msg = 0;
/* Authorization completed successfully */
return (pop_msg (p,POP_SUCCESS,
"%s has %d message%s (%d octets).",
p->user,p->msg_count, p->msg_count == 1 ? "" : "s", p->drop_size));
}
Received on Tue Feb 03 1998 - 02:36:00 NZDT