221 lines
5.7 KiB
C
221 lines
5.7 KiB
C
/*
|
|
* Copyright (c) 1989 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*/
|
|
|
|
#include <popper.h>
|
|
RCSID("$Id: pop_pass.c,v 1.1.1.2 2000/12/29 01:42:46 assar Exp $");
|
|
|
|
#ifdef KRB4
|
|
static int
|
|
krb4_verify_password (POP *p)
|
|
{
|
|
int status;
|
|
char lrealm[REALM_SZ];
|
|
char tkt[MaxPathLen];
|
|
|
|
status = krb_get_lrealm(lrealm,1);
|
|
if (status == KFAILURE) {
|
|
pop_log(p, POP_PRIORITY, "%s: (%s.%s@%s) %s", p->client,
|
|
p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
|
|
krb_get_err_text(status));
|
|
return 1;
|
|
}
|
|
snprintf(tkt, sizeof(tkt), "%s_popper.%u", TKT_ROOT, (unsigned)getpid());
|
|
krb_set_tkt_string (tkt);
|
|
|
|
status = krb_verify_user(p->user, "", lrealm,
|
|
p->pop_parm[1], KRB_VERIFY_SECURE, "pop");
|
|
dest_tkt(); /* no point in keeping the tickets */
|
|
return status;
|
|
}
|
|
#endif /* KRB4 */
|
|
|
|
#ifdef KRB5
|
|
static int
|
|
krb5_verify_password (POP *p)
|
|
{
|
|
krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
|
|
krb5_get_init_creds_opt get_options;
|
|
krb5_verify_init_creds_opt verify_options;
|
|
krb5_error_code ret;
|
|
krb5_principal client, server;
|
|
krb5_creds creds;
|
|
|
|
krb5_get_init_creds_opt_init (&get_options);
|
|
|
|
krb5_get_init_creds_opt_set_preauth_list (&get_options,
|
|
pre_auth_types,
|
|
1);
|
|
|
|
krb5_verify_init_creds_opt_init (&verify_options);
|
|
|
|
ret = krb5_parse_name (p->context, p->user, &client);
|
|
if (ret) {
|
|
pop_log(p, POP_PRIORITY, "krb5_parse_name: %s",
|
|
krb5_get_err_text (p->context, ret));
|
|
return 1;
|
|
}
|
|
|
|
ret = krb5_get_init_creds_password (p->context,
|
|
&creds,
|
|
client,
|
|
p->pop_parm[1],
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&get_options);
|
|
if (ret) {
|
|
pop_log(p, POP_PRIORITY,
|
|
"krb5_get_init_creds_password: %s",
|
|
krb5_get_err_text (p->context, ret));
|
|
return 1;
|
|
}
|
|
|
|
ret = krb5_sname_to_principal (p->context,
|
|
p->myhost,
|
|
"pop",
|
|
KRB5_NT_SRV_HST,
|
|
&server);
|
|
if (ret) {
|
|
pop_log(p, POP_PRIORITY,
|
|
"krb5_get_init_creds_password: %s",
|
|
krb5_get_err_text (p->context, ret));
|
|
return 1;
|
|
}
|
|
|
|
ret = krb5_verify_init_creds (p->context,
|
|
&creds,
|
|
server,
|
|
NULL,
|
|
NULL,
|
|
&verify_options);
|
|
krb5_free_principal (p->context, client);
|
|
krb5_free_principal (p->context, server);
|
|
krb5_free_creds_contents (p->context, &creds);
|
|
return ret;
|
|
}
|
|
#endif
|
|
/*
|
|
* pass: Obtain the user password from a POP client
|
|
*/
|
|
|
|
int
|
|
pop_pass (POP *p)
|
|
{
|
|
struct passwd *pw;
|
|
int i;
|
|
struct stat st;
|
|
|
|
/* Make one string of all these parameters */
|
|
|
|
for (i = 1; i < p->parm_count; ++i)
|
|
p->pop_parm[i][strlen(p->pop_parm[i])] = ' ';
|
|
|
|
/* Look for the user in the password file */
|
|
if ((pw = k_getpwnam(p->user)) == NULL)
|
|
return (pop_msg(p,POP_FAILURE,
|
|
"Password supplied for \"%s\" is incorrect.",
|
|
p->user));
|
|
|
|
if (p->kerberosp) {
|
|
#ifdef KRB4
|
|
if (p->version == 4) {
|
|
if(kuserok (&p->kdata, p->user)) {
|
|
pop_log(p, POP_PRIORITY,
|
|
"%s: (%s.%s@%s) tried to retrieve mail for %s.",
|
|
p->client, p->kdata.pname, p->kdata.pinst,
|
|
p->kdata.prealm, p->user);
|
|
return(pop_msg(p,POP_FAILURE,
|
|
"Popping not authorized"));
|
|
}
|
|
pop_log(p, POP_INFO, "%s: %s.%s@%s -> %s",
|
|
p->ipaddr,
|
|
p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
|
|
p->user);
|
|
} else
|
|
#endif /* KRB4 */
|
|
#ifdef KRB5
|
|
if (p->version == 5) {
|
|
char *name;
|
|
|
|
if (!krb5_kuserok (p->context, p->principal, p->user)) {
|
|
pop_log (p, POP_PRIORITY,
|
|
"krb5 permission denied");
|
|
return pop_msg(p, POP_FAILURE,
|
|
"Popping not authorized");
|
|
}
|
|
if(krb5_unparse_name (p->context, p->principal, &name) == 0) {
|
|
pop_log(p, POP_INFO, "%s: %s -> %s",
|
|
p->ipaddr, name, p->user);
|
|
free (name);
|
|
}
|
|
} else {
|
|
pop_log (p, POP_PRIORITY, "kerberos authentication failed");
|
|
return pop_msg (p, POP_FAILURE,
|
|
"kerberos authentication failed");
|
|
}
|
|
#endif
|
|
{ }
|
|
} else {
|
|
/* We don't accept connections from users with null passwords */
|
|
if (pw->pw_passwd == NULL)
|
|
return (pop_msg(p,
|
|
POP_FAILURE,
|
|
"Password supplied for \"%s\" is incorrect.",
|
|
p->user));
|
|
|
|
#ifdef OTP
|
|
if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0)
|
|
/* pass OK */;
|
|
else
|
|
#endif
|
|
/* Compare the supplied password with the password file entry */
|
|
if (p->auth_level != AUTH_NONE)
|
|
return pop_msg(p, POP_FAILURE,
|
|
"Password supplied for \"%s\" is incorrect.",
|
|
p->user);
|
|
else if (!strcmp(crypt(p->pop_parm[1], pw->pw_passwd), pw->pw_passwd))
|
|
/* pass OK */;
|
|
else {
|
|
int ret = -1;
|
|
#ifdef KRB4
|
|
ret = krb4_verify_password (p);
|
|
#endif
|
|
#ifdef KRB5
|
|
if(ret)
|
|
ret = krb5_verify_password (p);
|
|
#endif
|
|
if(ret)
|
|
return pop_msg(p, POP_FAILURE,
|
|
"Password incorrect");
|
|
}
|
|
}
|
|
pop_log(p, POP_INFO, "login from %s as %s",
|
|
p->ipaddr, p->user);
|
|
|
|
/* Build the name of the user's maildrop */
|
|
snprintf(p->drop_name, sizeof(p->drop_name), "%s/%s", POP_MAILDIR, p->user);
|
|
|
|
if(stat(p->drop_name, &st) < 0 || !S_ISDIR(st.st_mode)){
|
|
/* Make a temporary copy of the user's maildrop */
|
|
/* and set the group and user id */
|
|
if (pop_dropcopy(p, pw) != POP_SUCCESS) return (POP_FAILURE);
|
|
|
|
/* Get information about the maildrop */
|
|
if (pop_dropinfo(p) != POP_SUCCESS) return(POP_FAILURE);
|
|
} else {
|
|
if(changeuser(p, pw) != POP_SUCCESS) return POP_FAILURE;
|
|
if(pop_maildir_info(p) != 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) (%ld octets).",
|
|
p->user, p->msg_count, p->drop_size));
|
|
}
|