Implement both v4 and v5.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@2825 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -7,22 +7,37 @@
|
|||||||
#include <popper.h>
|
#include <popper.h>
|
||||||
RCSID("$Id$");
|
RCSID("$Id$");
|
||||||
|
|
||||||
static
|
#ifdef KRB4
|
||||||
int
|
static int
|
||||||
krb_authenticate(POP *p, struct sockaddr_in *addr)
|
krb4_authenticate (POP *p, int s, u_char *buf, struct sockaddr_in *addr)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef KERBEROS
|
|
||||||
Key_schedule schedule;
|
Key_schedule schedule;
|
||||||
KTEXT_ST ticket;
|
KTEXT_ST ticket;
|
||||||
char instance[INST_SZ];
|
char instance[INST_SZ];
|
||||||
char version[9];
|
char version[9];
|
||||||
int auth;
|
int auth;
|
||||||
|
u_char buf2[BUFSIZ];
|
||||||
|
|
||||||
|
if (memcmp (buf, KRB_SENDAUTH_VERS, 4) != 0)
|
||||||
|
return -1;
|
||||||
|
if (krb5_net_read (p->context, s, buf + 4,
|
||||||
|
KRB_SENDAUTH_VLEN - 4) != KRB_SENDAUTH_VLEN - 4)
|
||||||
|
return -1;
|
||||||
|
if (memcmp (buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
k_getsockinst (0, instance, sizeof(instance));
|
k_getsockinst (0, instance, sizeof(instance));
|
||||||
auth = krb_recvauth(0L, 0, &ticket, "pop", instance,
|
auth = krb_recvauth(KOPT_IGNORE_PROTOCOL,
|
||||||
addr, (struct sockaddr_in *) NULL,
|
s,
|
||||||
&p->kdata, "", schedule, version);
|
&ticket,
|
||||||
|
"pop",
|
||||||
|
instance,
|
||||||
|
addr,
|
||||||
|
(struct sockaddr_in *) NULL,
|
||||||
|
&p->kdata,
|
||||||
|
"",
|
||||||
|
schedule,
|
||||||
|
version);
|
||||||
|
|
||||||
if (auth != KSUCCESS) {
|
if (auth != KSUCCESS) {
|
||||||
pop_msg(p, POP_FAILURE, "Kerberos authentication failure: %s",
|
pop_msg(p, POP_FAILURE, "Kerberos authentication failure: %s",
|
||||||
@@ -37,14 +52,86 @@ krb_authenticate(POP *p, struct sockaddr_in *addr)
|
|||||||
pop_log(p, POP_DEBUG, "%s.%s@%s (%s): ok", p->kdata.pname,
|
pop_log(p, POP_DEBUG, "%s.%s@%s (%s): ok", p->kdata.pname,
|
||||||
p->kdata.pinst, p->kdata.prealm, inet_ntoa(addr->sin_addr));
|
p->kdata.pinst, p->kdata.prealm, inet_ntoa(addr->sin_addr));
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* KRB4 */
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb5_authenticate (POP *p, int s, u_char *buf, struct sockaddr_in *addr)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
krb5_auth_context auth_context = NULL;
|
||||||
|
u_int32_t len;
|
||||||
|
krb5_principal server;
|
||||||
|
krb5_ticket *ticket;
|
||||||
|
|
||||||
|
if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0)
|
||||||
|
return -1;
|
||||||
|
len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
|
||||||
|
|
||||||
|
if (krb5_net_read(p->context, s, buf, len) != len)
|
||||||
|
return -1;
|
||||||
|
if (len != sizeof(KRB5_SENDAUTH_VERSION)
|
||||||
|
|| memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = krb5_sname_to_principal (p->context,
|
||||||
|
p->myhost,
|
||||||
|
"pop",
|
||||||
|
KRB5_NT_SRV_HST,
|
||||||
|
&server);
|
||||||
|
if (ret) {
|
||||||
|
pop_log (p, POP_FAILURE,
|
||||||
|
"krb5_sname_to_principal: %s",
|
||||||
|
krb5_get_err_text(p->context, ret));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_recvauth (p->context,
|
||||||
|
&auth_context,
|
||||||
|
&s,
|
||||||
|
"KPOPV1.0",
|
||||||
|
server,
|
||||||
|
KRB5_RECVAUTH_IGNORE_VERSION,
|
||||||
|
NULL,
|
||||||
|
&ticket);
|
||||||
|
krb5_free_principal (p->context, server);
|
||||||
|
if (ret == 0) {
|
||||||
|
krb5_auth_con_free (p->context, auth_context);
|
||||||
|
krb5_copy_principal (p->context, ticket->client, &p->principal);
|
||||||
|
krb5_free_ticket (p->context, ticket);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb_authenticate(POP *p, struct sockaddr_in *addr)
|
||||||
|
{
|
||||||
|
#ifdef KERBEROS
|
||||||
|
u_char buf[BUFSIZ];
|
||||||
|
|
||||||
|
if (krb5_net_read (p->context, 0, buf, 4) != 4) {
|
||||||
|
pop_msg(p, POP_FAILURE, "Reading four bytes: %s",
|
||||||
|
strerror(errno));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
#ifdef KRB4
|
||||||
|
if (krb4_authenticate (p, 0, buf, addr) == 0)
|
||||||
|
p->version = 4;
|
||||||
|
else
|
||||||
|
#endif /* KRB4 */
|
||||||
|
if (krb5_authenticate (p, 0, buf, addr) == 0)
|
||||||
|
p->version = 5;
|
||||||
|
else {
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* KERBEROS */
|
#endif /* KERBEROS */
|
||||||
|
|
||||||
return(POP_SUCCESS);
|
return(POP_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int
|
||||||
int
|
|
||||||
plain_authenticate (POP *p, struct sockaddr_in *addr)
|
plain_authenticate (POP *p, struct sockaddr_in *addr)
|
||||||
{
|
{
|
||||||
return(POP_SUCCESS);
|
return(POP_SUCCESS);
|
||||||
@@ -75,7 +162,7 @@ pop_init(POP *p,int argcount,char **argmessage)
|
|||||||
p->myname = argmessage[0];
|
p->myname = argmessage[0];
|
||||||
|
|
||||||
/* Get the name of our host */
|
/* Get the name of our host */
|
||||||
k_gethostname(p->myhost,MaxHostNameLen);
|
gethostname(p->myhost,MaxHostNameLen);
|
||||||
|
|
||||||
/* Open the log file */
|
/* Open the log file */
|
||||||
openlog(p->myname,POP_LOGOPTS,POP_FACILITY);
|
openlog(p->myname,POP_LOGOPTS,POP_FACILITY);
|
||||||
@@ -153,8 +240,8 @@ pop_init(POP *p,int argcount,char **argmessage)
|
|||||||
if (inetd) {
|
if (inetd) {
|
||||||
if (portnum == 0)
|
if (portnum == 0)
|
||||||
portnum = p->kerberosp ?
|
portnum = p->kerberosp ?
|
||||||
k_getportbyname("kpop", "tcp", htons(1109)) :
|
krb5_getportbyname("kpop", "tcp", htons(1109)) :
|
||||||
k_getportbyname("pop", "tcp", htons(110));
|
krb5_getportbyname("pop", "tcp", htons(110));
|
||||||
mini_inetd (portnum);
|
mini_inetd (portnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,5 +332,9 @@ pop_init(POP *p,int argcount,char **argmessage)
|
|||||||
pop_log(p,POP_PRIORITY,"Debugging turned on");
|
pop_log(p,POP_PRIORITY,"Debugging turned on");
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
#ifdef KERBEROS
|
||||||
|
krb5_init_context (&p->context);
|
||||||
|
#endif
|
||||||
|
|
||||||
return((p->kerberosp ? krb_authenticate : plain_authenticate)(p, &cs));
|
return((p->kerberosp ? krb_authenticate : plain_authenticate)(p, &cs));
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,95 @@
|
|||||||
#include <popper.h>
|
#include <popper.h>
|
||||||
RCSID("$Id$");
|
RCSID("$Id$");
|
||||||
|
|
||||||
|
#ifdef KRB4
|
||||||
|
static int
|
||||||
|
krb4_verify_password (POP *p)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
char lrealm[REALM_SZ + 1];
|
||||||
|
char tkt[MaxPathLen];
|
||||||
|
|
||||||
|
status = krb_get_lrealm(lrealm,1);
|
||||||
|
if (status == KFAILURE) {
|
||||||
|
pop_log(p, POP_FAILURE, "%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),
|
||||||
|
TKT_ROOT "_popper.%u", (unsigned)getpid());
|
||||||
|
krb_set_tkt_string (tkt);
|
||||||
|
|
||||||
|
return krb_verify_user(p->user, "", lrealm, p->pop_parm[1],
|
||||||
|
1, "pop");
|
||||||
|
}
|
||||||
|
#endif /* KRB4 */
|
||||||
|
|
||||||
|
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_FAILURE, "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_FAILURE,
|
||||||
|
"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_FAILURE,
|
||||||
|
"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;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pass: Obtain the user password from a POP client
|
* pass: Obtain the user password from a POP client
|
||||||
*/
|
*/
|
||||||
@@ -15,8 +104,6 @@ int
|
|||||||
pop_pass (POP *p)
|
pop_pass (POP *p)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
char lrealm[REALM_SZ + 1];
|
|
||||||
int status;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Make one string of all these parameters */
|
/* Make one string of all these parameters */
|
||||||
@@ -30,18 +117,32 @@ pop_pass (POP *p)
|
|||||||
"Password supplied for \"%s\" is incorrect.",
|
"Password supplied for \"%s\" is incorrect.",
|
||||||
p->user));
|
p->user));
|
||||||
|
|
||||||
if ((status = krb_get_lrealm(lrealm,1)) == KFAILURE) {
|
if (p->kerberosp) {
|
||||||
pop_log(p, POP_FAILURE, "%s: (%s.%s@%s) %s", p->client,
|
#ifdef KRB4
|
||||||
p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
|
if (p->version == 4) {
|
||||||
krb_get_err_text(status));
|
if(kuserok (&p->kdata, p->user)) {
|
||||||
return(pop_msg(p,POP_FAILURE,
|
pop_log(p, POP_FAILURE,
|
||||||
"Kerberos error: \"%s\".",
|
"%s: (%s.%s@%s) tried to retrieve mail for %s.",
|
||||||
krb_get_err_text(status)));
|
p->client, p->kdata.pname, p->kdata.pinst,
|
||||||
}
|
p->kdata.prealm, p->user);
|
||||||
|
return(pop_msg(p,POP_FAILURE,
|
||||||
if (!p->kerberosp) {
|
"Popping not authorized"));
|
||||||
char tkt[MaxPathLen];
|
}
|
||||||
|
} else
|
||||||
|
#endif /* KRB4 */
|
||||||
|
if (p->version == 5) {
|
||||||
|
if (!krb5_kuserok (p->context, p->principal, p->user)) {
|
||||||
|
pop_log (p, POP_FAILURE,
|
||||||
|
"krb5 permission denied");
|
||||||
|
return pop_msg(p, POP_FAILURE,
|
||||||
|
"Popping not authorized");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pop_log (p, POP_FAILURE, "kerberos authentication failed");
|
||||||
|
return pop_msg (p, POP_FAILURE,
|
||||||
|
"kerberos authentication failed");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
/* We don't accept connections from users with null passwords */
|
/* We don't accept connections from users with null passwords */
|
||||||
if (pw->pw_passwd == NULL)
|
if (pw->pw_passwd == NULL)
|
||||||
return (pop_msg(p,
|
return (pop_msg(p,
|
||||||
@@ -49,32 +150,23 @@ pop_pass (POP *p)
|
|||||||
"Password supplied for \"%s\" is incorrect.",
|
"Password supplied for \"%s\" is incorrect.",
|
||||||
p->user));
|
p->user));
|
||||||
|
|
||||||
snprintf (tkt, sizeof(tkt),
|
|
||||||
TKT_ROOT "_popper.%u", (unsigned)getpid());
|
|
||||||
krb_set_tkt_string (tkt);
|
|
||||||
if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0)
|
if (otp_verify_user (&p->otp_ctx, p->pop_parm[1]) == 0)
|
||||||
;
|
;
|
||||||
else if(p->auth_level != AUTH_NONE)
|
else if(p->auth_level != AUTH_NONE)
|
||||||
return pop_msg(p, POP_FAILURE,
|
return pop_msg(p, POP_FAILURE,
|
||||||
"Password supplied for \"%s\" is incorrect.",
|
"Password supplied for \"%s\" is incorrect.",
|
||||||
p->user);
|
p->user);
|
||||||
else if (krb_verify_user(p->user, "", lrealm, p->pop_parm[1],
|
else {
|
||||||
1, "pop") &&
|
#ifdef KRB4
|
||||||
unix_verify_user(p->user, p->pop_parm[1])) {
|
if (krb4_verify_password (p) == 0)
|
||||||
dest_tkt ();
|
;
|
||||||
return (pop_msg(p,POP_FAILURE,
|
else
|
||||||
"Password supplied for \"%s\" is incorrect.",
|
#endif /* KRB4 */
|
||||||
p->user));
|
if (krb5_verify_password (p) == 0)
|
||||||
}
|
;
|
||||||
dest_tkt ();
|
else
|
||||||
} else {
|
return pop_msg(p, POP_FAILURE,
|
||||||
if (kuserok (&p->kdata, p->user)) {
|
"Password incorrect");
|
||||||
pop_log(p, POP_FAILURE,
|
|
||||||
"%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"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user