summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2020-02-19 00:39:42 -0700
committerEduardo Chappa <chappa@washington.edu>2020-02-19 00:39:42 -0700
commitcd53b13aa5acaecb776c82cd6566122a6893240d (patch)
tree4e811c0dfdebf647b564f4f9659c388c87a44f4c
parent8781af1dfc9fdc1fbc08b281cc418bee8dde604d (diff)
downloadalpine-cd53b13aa5acaecb776c82cd6566122a6893240d.tar.xz
* Added support for SALS-IR (rfc 4959) and similar support for other
protocols (SMTP, NNTP, POP3) as some SMTP servers do not support a round-trip two step authentication. For example, davmail does not support PLAIN authentication in SMTP using the challenge-response scheme. Implemented after a report by Geoffrey Bodwin.
-rw-r--r--imap/src/c-client/auth_bea.c24
-rw-r--r--imap/src/c-client/auth_ext.c10
-rw-r--r--imap/src/c-client/auth_gss.c27
-rw-r--r--imap/src/c-client/auth_log.c10
-rw-r--r--imap/src/c-client/auth_md5.c8
-rw-r--r--imap/src/c-client/auth_oa2.c22
-rw-r--r--imap/src/c-client/auth_pla.c20
-rw-r--r--imap/src/c-client/imap4r1.c29
-rw-r--r--imap/src/c-client/mail.c1
-rw-r--r--imap/src/c-client/mail.h6
-rw-r--r--imap/src/c-client/nntp.c19
-rw-r--r--imap/src/c-client/pop3.c31
-rw-r--r--imap/src/c-client/smtp.c19
-rw-r--r--pith/pine.hlp7
14 files changed, 142 insertions, 91 deletions
diff --git a/imap/src/c-client/auth_bea.c b/imap/src/c-client/auth_bea.c
index 683d769..b9bf61e 100644
--- a/imap/src/c-client/auth_bea.c
+++ b/imap/src/c-client/auth_bea.c
@@ -11,7 +11,7 @@
* ========================================================================
*/
-long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder,
+long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder, char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
#ifndef HTTP_OAUTH2_INCLUDED
@@ -19,7 +19,7 @@ void mm_login_oauth2_c_client_method (NETMBX *, char *, char *, OAUTH2_S *, unsi
#endif /* HTTP_OAUTH2_INCLUDED */
AUTHENTICATOR auth_bea = {
- AU_HIDE, /* hidden */
+ AU_HIDE | AU_SINGLE, /* hidden, single trip */
BEARERNAME, /* authenticator name */
NIL, /* always valid */
auth_oauthbearer_client, /* client method */
@@ -77,7 +77,7 @@ char *oauth2_generate_state(void)
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder,
+long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user)
{
@@ -94,12 +94,14 @@ long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder
mm_log ("SECURITY PROBLEM: insecure server advertised AUTH=OAUTHBEARER",WARN);
/* get initial (empty) challenge */
- if ((challenge = (*challenger) (stream,&clen)) != NULL) {
- fs_give ((void **) &challenge);
- if (clen) { /* abort if challenge non-empty */
- mm_log ("Server bug: non-empty initial OAUTHBEARER challenge",WARN);
- (*responder) (stream,NIL,0);
- ret = LONGT; /* will get a BAD response back */
+ if (base || (challenge = (*challenger) (stream,&clen)) != NULL) {
+ if(base == NIL){
+ fs_give ((void **) &challenge);
+ if (clen) { /* abort if challenge non-empty */
+ mm_log ("Server bug: non-empty initial OAUTHBEARER challenge",WARN);
+ (*responder) (stream,NIL,NIL,0);
+ ret = LONGT; /* will get a BAD response back */
+ }
}
mm_login_method (mb, user, (void *) &oauth2, *trial, BEARERNAME);
@@ -137,7 +139,7 @@ long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder
/* empty challenge or user requested abort or client does not have info */
if(!oauth2.access_token) {
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
*trial = 0; /* cancel subsequent attempts */
ret = LONGT; /* will get a BAD response back */
}
@@ -166,7 +168,7 @@ long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder
for (u = oauth2.access_token; *u; *t++ = *u++);
*t++ = '\001'; /* delimiting ^A */
*t++ = '\001'; /* delimiting ^A */
- if ((*responder) (stream,response,rlen)) {
+ if ((*responder) (stream,base,response,rlen)) {
if ((challenge = (*challenger) (stream,&clen)) != NULL)
fs_give ((void **) &challenge);
else {
diff --git a/imap/src/c-client/auth_ext.c b/imap/src/c-client/auth_ext.c
index b85f6bb..6f8cf3a 100644
--- a/imap/src/c-client/auth_ext.c
+++ b/imap/src/c-client/auth_ext.c
@@ -27,7 +27,7 @@
* Last Edited: 30 August 2006
*/
-long auth_external_client (authchallenge_t challenger,authrespond_t responder,
+long auth_external_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
char *auth_external_server (authresponse_t responder,int argc,char *argv[]);
@@ -52,7 +52,7 @@ AUTHENTICATOR auth_ext = { /* secure, has full auth, hidden */
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_external_client (authchallenge_t challenger,authrespond_t responder,
+long auth_external_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user)
{
@@ -60,10 +60,10 @@ long auth_external_client (authchallenge_t challenger,authrespond_t responder,
unsigned long clen;
long ret = NIL;
*trial = 65535; /* never retry */
- if ((challenge = (*challenger) (stream,&clen)) != NULL) {
- fs_give ((void **) &challenge);
+ if (base || (challenge = (*challenger) (stream,&clen)) != NULL) {
+ if(base == NIL) fs_give ((void **) &challenge);
/* send authorization id (empty string OK) */
- if ((*responder) (stream,strcpy (user,mb->user),strlen (mb->user))) {
+ if ((*responder) (stream,base,strcpy (user,mb->user),strlen(mb->user))) {
if ((challenge = (*challenger) (stream,&clen)) != NULL)
fs_give ((void **) &challenge);
else ret = LONGT; /* check the authentication */
diff --git a/imap/src/c-client/auth_gss.c b/imap/src/c-client/auth_gss.c
index c6cc907..4ed612c 100644
--- a/imap/src/c-client/auth_gss.c
+++ b/imap/src/c-client/auth_gss.c
@@ -29,7 +29,7 @@
long auth_gssapi_valid (void);
-long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
+long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder, char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
@@ -89,7 +89,8 @@ long auth_gssapi_valid (void)
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
+long auth_gssapi_client (authchallenge_t challenger,authrespond_t
+responder,char *base,
char *service,NETMBX *mb,void *stream,unsigned long port,
unsigned long *trial,char *user)
{
@@ -101,12 +102,12 @@ long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
if ((chal.value = (*challenger) (stream,(unsigned long *) &chal.length)) != NULL) {
if (chal.length) { /* abort if challenge non-empty */
mm_log ("Server bug: non-empty initial GSSAPI challenge",WARN);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
ret = LONGT; /* will get a BAD response back */
}
else if (mb->authuser[0] && strcmp (mb->authuser,myusername ())) {
mm_log ("Can't use Kerberos: invalid /authuser",WARN);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
ret = LONGT; /* will get a BAD response back */
}
else ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
@@ -148,7 +149,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
if (gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&crname) !=
GSS_S_COMPLETE) {
mm_log ("Can't import Kerberos service name",WARN);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
}
else {
data = (*bn) (BLOCK_SENSITIVE,NIL);
@@ -163,7 +164,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
while (smj == GSS_S_CONTINUE_NEEDED) {
if (chal.value) fs_give ((void **) &chal.value);
/* send response, get next challenge */
- i = (*responder) (stream,resp.value,resp.length) &&
+ i = (*responder) (stream,NIL,resp.value,resp.length) &&
(chal.value = (*challenger) (stream,(unsigned long *) &chal.length));
gss_release_buffer (&smn,&resp);
if (i) { /* negotiate continuation with KDC */
@@ -184,7 +185,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
}
else { /* error in continuation */
mm_log ("Error in negotiating Kerberos continuation",WARN);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
/* don't need context any more */
gss_delete_sec_context (&smn,&ctx,NIL);
break;
@@ -195,7 +196,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
case GSS_S_COMPLETE:
if (chal.value) fs_give ((void **) &chal.value);
/* get prot mechanisms and max size */
- if ((*responder) (stream,resp.value ? resp.value : "",resp.length) &&
+ if ((*responder) (stream,NIL,resp.value ? resp.value : "",resp.length) &&
(chal.value = (*challenger) (stream,(unsigned long *)&chal.length))&&
(gss_unwrap (&smn,ctx,&chal,&resp,&conf,&qop) == GSS_S_COMPLETE) &&
(resp.length >= 4) && (*((char *) resp.value) & AUTH_GSSAPI_P_NONE)){
@@ -210,7 +211,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
/* successful negotiation */
switch (smj = gss_wrap (&smn,ctx,NIL,qop,&buf,&conf,&resp)) {
case GSS_S_COMPLETE:
- if ((*responder) (stream,resp.value,resp.length)) ret = T;
+ if ((*responder) (stream,NIL,resp.value,resp.length)) ret = T;
gss_release_buffer (&smn,&resp);
break;
default:
@@ -233,7 +234,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
gss_release_buffer (&dsmn,&resp);
}
while (dsmj == GSS_S_CONTINUE_NEEDED);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
}
}
/* flush final challenge */
@@ -252,7 +253,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
sprintf (tmp,"Kerberos credentials expired (try running kinit) for %s",
mb->host);
mm_log (tmp,WARN);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
}
break;
case GSS_S_FAILURE:
@@ -267,7 +268,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
stream,user,NIL);
break; /* done */
}
- else (*responder) (stream,NIL,0);
+ else (*responder) (stream,NIL,NIL,0);
case GSS_S_CONTINUE_NEEDED:
sprintf (tmp,kerberos_try_kinit (smn) ?
"Kerberos error: %.80s (try running kinit) for %.80s" :
@@ -298,7 +299,7 @@ long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
gss_release_buffer (&dsmn,&resp);
}
while (dsmj == GSS_S_CONTINUE_NEEDED);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
break;
}
/* finished with credentials name */
diff --git a/imap/src/c-client/auth_log.c b/imap/src/c-client/auth_log.c
index 9c8d76a..618e2a0 100644
--- a/imap/src/c-client/auth_log.c
+++ b/imap/src/c-client/auth_log.c
@@ -27,7 +27,7 @@
* Last Edited: 30 August 2006
*/
-long auth_login_client (authchallenge_t challenger,authrespond_t responder,
+long auth_login_client (authchallenge_t challenger,authrespond_t responder, char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
char *auth_login_server (authresponse_t responder,int argc,char *argv[]);
@@ -55,7 +55,7 @@ AUTHENTICATOR auth_log = {
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_login_client (authchallenge_t challenger,authrespond_t responder,
+long auth_login_client (authchallenge_t challenger,authrespond_t responder, char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user)
{
@@ -68,16 +68,16 @@ long auth_login_client (authchallenge_t challenger,authrespond_t responder,
fs_give ((void **) &challenge);
mm_login (mb,user, &pwd,*trial);
if (!pwd) { /* user requested abort */
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
*trial = 0; /* cancel subsequent attempts */
ret = LONGT; /* will get a BAD response back */
}
/* send user name */
- else if ((*responder) (stream,user,strlen (user)) &&
+ else if ((*responder) (stream,NIL,user,strlen (user)) &&
(challenge = (*challenger) (stream,&clen))) {
fs_give ((void **) &challenge);
/* send password */
- if ((*responder) (stream,pwd,strlen (pwd))) {
+ if ((*responder) (stream,NIL,pwd,strlen (pwd))) {
if ((challenge = (*challenger) (stream,&clen)) != NULL)
fs_give ((void **) &challenge);
else {
diff --git a/imap/src/c-client/auth_md5.c b/imap/src/c-client/auth_md5.c
index fea9673..a1c1f5e 100644
--- a/imap/src/c-client/auth_md5.c
+++ b/imap/src/c-client/auth_md5.c
@@ -44,7 +44,7 @@ typedef struct {
/* Prototypes */
long auth_md5_valid (void);
-long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
+long auth_md5_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
char *auth_md5_server (authresponse_t responder,int argc,char *argv[]);
@@ -95,7 +95,7 @@ long auth_md5_valid (void)
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
+long auth_md5_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user)
{
@@ -108,7 +108,7 @@ long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
mm_login (mb,user, &pwd,*trial);
if (!pwd) { /* user requested abort */
fs_give ((void **) &challenge);
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
*trial = 0; /* cancel subsequent attempts */
ret = LONGT; /* will get a BAD response back */
}
@@ -118,7 +118,7 @@ long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
pwd,strlen (pwd)));
fs_give ((void **) &challenge);
/* send credentials, allow retry if OK */
- if ((*responder) (stream,tmp,strlen (tmp))) {
+ if ((*responder) (stream,NIL,tmp,strlen (tmp))) {
if ((challenge = (*challenger) (stream,&clen)) != NULL)
fs_give ((void **) &challenge);
else {
diff --git a/imap/src/c-client/auth_oa2.c b/imap/src/c-client/auth_oa2.c
index bda9dd9..1608ad0 100644
--- a/imap/src/c-client/auth_oa2.c
+++ b/imap/src/c-client/auth_oa2.c
@@ -11,7 +11,7 @@
* ========================================================================
*/
-long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder,
+long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder, char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
@@ -20,7 +20,7 @@ void mm_login_oauth2_c_client_method (NETMBX *, char *, char *, OAUTH2_S *, unsi
#endif /* HTTP_OAUTH2_INCLUDED */
AUTHENTICATOR auth_oa2 = {
- AU_HIDE, /* hidden */
+ AU_HIDE | AU_SINGLE, /* hidden */
OA2NAME, /* authenticator name */
NIL, /* always valid */
auth_oauth2_client, /* client method */
@@ -75,7 +75,7 @@ char *oauth2_generate_state(void)
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder,
+long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder, char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user)
{
@@ -93,11 +93,13 @@ long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder,
/* get initial (empty) challenge */
if ((challenge = (*challenger) (stream,&clen)) != NULL) {
- fs_give ((void **) &challenge);
- if (clen) { /* abort if challenge non-empty */
- mm_log ("Server bug: non-empty initial XOAUTH2 challenge",WARN);
- (*responder) (stream,NIL,0);
- ret = LONGT; /* will get a BAD response back */
+ if(base == NIL){
+ fs_give ((void **) &challenge);
+ if (clen) { /* abort if challenge non-empty */
+ mm_log ("Server bug: non-empty initial XOAUTH2 challenge",WARN);
+ (*responder) (stream,NIL,NIL,0);
+ ret = LONGT; /* will get a BAD response back */
+ }
}
/*
@@ -168,7 +170,7 @@ long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder,
/* empty challenge or user requested abort or client does not have info */
if(!oauth2.access_token) {
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
*trial = 0; /* cancel subsequent attempts */
ret = LONGT; /* will get a BAD response back */
}
@@ -184,7 +186,7 @@ long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder,
for (u = oauth2.access_token; *u; *t++ = *u++);
*t++ = '\001'; /* delimiting ^A */
*t++ = '\001'; /* delimiting ^A */
- if ((*responder) (stream,response,rlen)) {
+ if ((*responder) (stream,base,response,rlen)) {
if ((challenge = (*challenger) (stream,&clen)) != NULL)
fs_give ((void **) &challenge);
else {
diff --git a/imap/src/c-client/auth_pla.c b/imap/src/c-client/auth_pla.c
index 6b58948..befd7f8 100644
--- a/imap/src/c-client/auth_pla.c
+++ b/imap/src/c-client/auth_pla.c
@@ -27,13 +27,13 @@
* Last Edited: 30 August 2006
*/
-long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
+long auth_plain_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user);
char *auth_plain_server (authresponse_t responder,int argc,char *argv[]);
AUTHENTICATOR auth_pla = {
- AU_AUTHUSER | AU_HIDE, /* allow authuser, hidden */
+ AU_AUTHUSER | AU_HIDE | AU_SINGLE, /* allow authuser, hidden, single trip */
"PLAIN", /* authenticator name */
NIL, /* always valid */
auth_plain_client, /* client method */
@@ -52,30 +52,30 @@ AUTHENTICATOR auth_pla = {
* Returns: T if success, NIL otherwise, number of trials incremented if retry
*/
-long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
+long auth_plain_client (authchallenge_t challenger,authrespond_t responder,char *base,
char *service,NETMBX *mb,void *stream, unsigned long port,
unsigned long *trial,char *user)
{
char *u, *pwd = NIL;
- void *challenge;
+ void *challenge = NIL;
unsigned long clen;
long ret = NIL;
/* snarl if not SSL/TLS session */
if (!mb->sslflag && !mb->tlsflag)
mm_log ("SECURITY PROBLEM: insecure server advertised AUTH=PLAIN",WARN);
/* get initial (empty) challenge */
- if ((challenge = (*challenger) (stream,&clen)) != NULL) {
- fs_give ((void **) &challenge);
+ if(base || (challenge = (*challenger) (stream,&clen)) != NULL) {
+ if(base == NIL) fs_give ((void **) &challenge);
#if 0
- if (clen) { /* abort if challenge non-empty */
+ if (clen) { /* abort if challenge non-empty */
mm_log ("Server bug: non-empty initial PLAIN challenge",WARN);
(*responder) (stream,NIL,0);
- ret = LONGT; /* will get a BAD response back */
+ ret = LONGT; /* will get a BAD response back */
}
#endif
mm_login (mb,user, &pwd,*trial);
if (!pwd) { /* empty challenge or user requested abort */
- (*responder) (stream,NIL,0);
+ (*responder) (stream,NIL,NIL,0);
*trial = 0; /* cancel subsequent attempts */
ret = LONGT; /* will get a BAD response back */
}
@@ -92,7 +92,7 @@ long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
/* copy password */
for (u = pwd; *u; *t++ = *u++);
/* send credentials */
- if ((*responder) (stream,response,rlen)) {
+ if ((*responder) (stream,base,response,rlen)) {
if ((challenge = (*challenger) (stream,&clen)) != NULL)
fs_give ((void **) &challenge);
else {
diff --git a/imap/src/c-client/imap4r1.c b/imap/src/c-client/imap4r1.c
index 86354d4..1b4241d 100644
--- a/imap/src/c-client/imap4r1.c
+++ b/imap/src/c-client/imap4r1.c
@@ -177,7 +177,7 @@ long imap_anon (MAILSTREAM *stream,char *tmp);
long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr);
long imap_login (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr);
void *imap_challenge (void *stream,unsigned long *len);
-long imap_response (void *stream,char *s,unsigned long size);
+long imap_response (void *stream,char *base,char *s,unsigned long size);
void imap_close (MAILSTREAM *stream,long options);
void imap_fast (MAILSTREAM *stream,char *sequence,long flags);
void imap_flags (MAILSTREAM *stream,char *sequence,long flags);
@@ -1107,7 +1107,7 @@ long imap_anon (MAILSTREAM *stream,char *tmp)
mm_log (broken,ERROR);
return NIL;
}
- if (imap_challenge (stream,&i)) imap_response (stream,s,strlen (s));
+ if (imap_challenge (stream,&i)) imap_response (stream,NIL,s,strlen (s));
/* get response */
if (!(reply = &LOCAL->reply)->tag) reply = imap_fake (stream,tag,broken);
/* what we wanted? */
@@ -1145,7 +1145,7 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr)
unsigned long trial,ua,uasaved;
int ok;
char tag[16];
- char *lsterr = NIL;
+ char *lsterr = NIL, *base;
AUTHENTICATOR *at, *atsaved;
IMAPPARSEDREPLY *reply;
for (ua = LOCAL->cap.auth, LOCAL->saslcancel = NIL; LOCAL->netstream && ua &&
@@ -1176,10 +1176,12 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr)
sprintf (tag,"%08lx",0xffffffff & (stream->gensym++));
/* build command */
sprintf (tmp,"%s AUTHENTICATE %s",tag,at->name);
- if (imap_soutr (stream,tmp)) {
+ base = (at->flags & AU_SINGLE) && LOCAL->cap.sasl_ir
+ ? (char *) tmp : NIL;
+ if (base || imap_soutr (stream,tmp)) {
/* hide client authentication responses */
if (!(at->flags & AU_SECURE)) LOCAL->sensitive = T;
- ok = (*at->client) (imap_challenge,imap_response,"imap",mb,stream,
+ ok = (*at->client) (imap_challenge,imap_response,base,"imap",mb,stream,
net_port(LOCAL->netstream),&trial,usr);
LOCAL->sensitive = NIL; /* unhide */
/* make sure have a response */
@@ -1311,15 +1313,26 @@ void *imap_challenge (void *s,unsigned long *len)
* Returns: T if successful, else NIL
*/
-long imap_response (void *s,char *response,unsigned long size)
+long imap_response (void *s,char *base,char *response,unsigned long size)
{
MAILSTREAM *stream = (MAILSTREAM *) s;
unsigned long i,j,ret;
char *t,*u;
if (response) { /* make CRLFless BASE64 string */
if (size) {
- for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
+ if(base){
+ char *s, *v;
+
+ v = (char *) rfc822_binary ((void *) response,size,&i);
+ t = fs_get((strlen(base) + strlen(v) + 1 + 2)*sizeof(char));
+ for(s = base, u = t; *s; s++) *u++ = *s;
+ *u++ = ' ';
+ for (s = v,j = 0; j < i; j++) if (s[j] > ' ') *u++ = s[j];
+ fs_give((void **) &v);
+ } else {
+ for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
j < i; j++) if (t[j] > ' ') *u++ = t[j];
+ }
*u = '\0'; /* tie off string for mm_dlog() */
if (stream->debug) mail_dlog (t,LOCAL->sensitive);
/* append CRLF */
@@ -1330,7 +1343,7 @@ long imap_response (void *s,char *response,unsigned long size)
else ret = imap_soutr (stream,"");
}
else { /* abort requested */
- ret = imap_soutr (stream,"*");
+ ret = base ? NIL : imap_soutr (stream,"*");
LOCAL->saslcancel = T; /* mark protocol-requested SASL cancel */
}
return ret;
diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c
index e591a52..8539868 100644
--- a/imap/src/c-client/mail.c
+++ b/imap/src/c-client/mail.c
@@ -6370,6 +6370,7 @@ long net_getbuffer (void *st,unsigned long size,char *buffer)
long net_soutr (NETSTREAM *stream,char *string)
{
+ mm_log(string, ERROR);
return (*stream->dtb->soutr) (stream->stream,string);
}
diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h
index 1a4e1b0..d7c52dd 100644
--- a/imap/src/c-client/mail.h
+++ b/imap/src/c-client/mail.h
@@ -548,6 +548,8 @@
#define AU_HIDE (long) 0x10000000
/* authenticator disabled */
#define AU_DISABLE (long) 0x20000000
+ /* can do single trip */
+#define AU_SINGLE (long) 0x40000000
/* Garbage collection flags */
@@ -1377,10 +1379,10 @@ typedef long (*mailproxycopy_t) (MAILSTREAM *stream,char *sequence,
typedef long (*tcptimeout_t) (long overall,long last, char *host);
typedef long (*ucs4width_t) (unsigned long c);
typedef void *(*authchallenge_t) (void *stream,unsigned long *len);
-typedef long (*authrespond_t) (void *stream,char *s,unsigned long size);
+typedef long (*authrespond_t) (void *stream,char *base,char *s,unsigned long size);
typedef long (*authcheck_t) (void);
typedef long (*authclient_t) (authchallenge_t challenger,
- authrespond_t responder,char *service,NETMBX *mb,
+ authrespond_t responder, char *base, char *service,NETMBX *mb,
void *s, unsigned long port, unsigned long *trial,char *user);
typedef char *(*authresponse_t) (void *challenge,unsigned long clen,
unsigned long *rlen);
diff --git a/imap/src/c-client/nntp.c b/imap/src/c-client/nntp.c
index 51d20b7..bce7c63 100644
--- a/imap/src/c-client/nntp.c
+++ b/imap/src/c-client/nntp.c
@@ -154,7 +154,7 @@ long nntp_send_work (SENDSTREAM *stream,char *command,char *args);
long nntp_send_auth (SENDSTREAM *stream,long flags);
long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags);
void *nntp_challenge (void *s,unsigned long *len);
-long nntp_response (void *s,char *response,unsigned long size);
+long nntp_response (void *s,char *base,char *response,unsigned long size);
long nntp_reply (SENDSTREAM *stream);
long nntp_fake (SENDSTREAM *stream,char *text);
long nntp_soutr (void *stream,char *s);
@@ -2045,7 +2045,7 @@ long nntp_send_auth (SENDSTREAM *stream,long flags)
long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags)
{
unsigned long trial,auths;
- char tmp[MAILTMPLEN],usr[MAILTMPLEN], *pwd2 = NIL;
+ char tmp[MAILTMPLEN],usr[MAILTMPLEN], *pwd2 = NIL, *base;
AUTHENTICATOR *at;
char *lsterr = NIL;
long ret = NIL;
@@ -2068,10 +2068,15 @@ long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *pwd,long flags)
fs_give ((void **) &lsterr);
}
stream->saslcancel = NIL;
- if (nntp_send (stream,"AUTHINFO SASL",at->name) == NNTPCHALLENGE) {
+ if(at->flags & AU_SINGLE){
+ sprintf(tmp, "AUTHINFO SASL %s", at->name); /* create base string */
+ base = (char *) tmp;
+ }
+ else base = NIL;
+ if ((at->flags & AU_SINGLE) || nntp_send (stream,"AUTHINFO SASL",at->name) == NNTPCHALLENGE) {
/* hide client authentication responses */
if (!(at->flags & AU_SECURE)) stream->sensitive = T;
- if ((*at->client) (nntp_challenge,nntp_response,"nntp",mb,stream,
+ if ((*at->client) (nntp_challenge,nntp_response,base,"nntp",mb,stream,
net_port(stream->netstream), &trial,usr)) {
if (stream->replycode == NNTPAUTHED) ret = LONGT;
/* if main program requested cancellation */
@@ -2163,7 +2168,7 @@ void *nntp_challenge (void *s,unsigned long *len)
* Returns: T, always
*/
-long nntp_response (void *s,char *response,unsigned long size)
+long nntp_response (void *s,char *base,char *response,unsigned long size)
{
SENDSTREAM *stream = (SENDSTREAM *) s;
unsigned long i,j;
@@ -2173,13 +2178,13 @@ long nntp_response (void *s,char *response,unsigned long size)
for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
j < i; j++) if (t[j] > ' ') *u++ = t[j];
*u = '\0'; /* tie off string */
- i = nntp_send_work (stream,t,NIL);
+ i = base ? nntp_send_work(stream, base, t) : nntp_send_work (stream,t,NIL);
fs_give ((void **) &t);
}
else i = nntp_send_work (stream,"",NIL);
}
else { /* abort requested */
- i = nntp_send_work (stream,"*",NIL);
+ i = base ? 0L : nntp_send_work (stream,"*",NIL);
stream->saslcancel = T; /* mark protocol-requested SASL cancel */
}
return LONGT;
diff --git a/imap/src/c-client/pop3.c b/imap/src/c-client/pop3.c
index 94df54f..b93ef8f 100644
--- a/imap/src/c-client/pop3.c
+++ b/imap/src/c-client/pop3.c
@@ -91,7 +91,7 @@ MAILSTREAM *pop3_open (MAILSTREAM *stream);
long pop3_capa (MAILSTREAM *stream,long flags);
long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr);
void *pop3_challenge (void *stream,unsigned long *len);
-long pop3_response (void *stream,char *s,unsigned long size);
+long pop3_response (void *stream,char *base,char *s,unsigned long size);
void pop3_close (MAILSTREAM *stream,long options);
void pop3_fetchfast (MAILSTREAM *stream,char *sequence,long flags);
char *pop3_header (MAILSTREAM *stream,unsigned long msgno,unsigned long *size,
@@ -555,7 +555,7 @@ long pop3_capa (MAILSTREAM *stream,long flags)
long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr)
{
unsigned long i,trial,auths = 0, authsaved;
- char *t, *app_pwd = NIL;
+ char *t, *app_pwd = NIL, *base;
AUTHENTICATOR *at, *atsaved;
long ret = NIL;
long flags = (stream->secure ? AU_SECURE : NIL) |
@@ -635,11 +635,15 @@ long pop3_auth (MAILSTREAM *stream,NETMBX *mb,char *pwd,char *usr)
mm_log (pwd,WARN);
fs_give ((void **) &t);
}
+ if(at->flags & AU_SINGLE){
+ sprintf(pwd, "AUTH %s", at->name);
+ base = (char *) pwd;
+ } else base = NIL;
LOCAL->saslcancel = NIL;
- if (pop3_send (stream,"AUTH",at->name)) {
+ if ((at->flags & AU_SINGLE) || pop3_send (stream,"AUTH",at->name)) {
/* hide client authentication responses */
if (!(at->flags & AU_SECURE)) LOCAL->sensitive = T;
- if ((*at->client) (pop3_challenge,pop3_response,"pop",mb,stream,
+ if ((*at->client) (pop3_challenge,pop3_response,base,"pop",mb,stream,
net_port(LOCAL->netstream),&trial,usr) && LOCAL->response) {
if (*LOCAL->response == '+') ret = LONGT;
/* if main program requested cancellation */
@@ -735,15 +739,26 @@ void *pop3_challenge (void *s,unsigned long *len)
* Returns: T if successful, else NIL
*/
-long pop3_response (void *s,char *response,unsigned long size)
+long pop3_response (void *s,char *base,char *response,unsigned long size)
{
MAILSTREAM *stream = (MAILSTREAM *) s;
unsigned long i,j,ret;
char *t,*u;
if (response) { /* make CRLFless BASE64 string */
if (size) {
- for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
- j < i; j++) if (t[j] > ' ') *u++ = t[j];
+ if(base){
+ char *s, *v;
+
+ v = (char *) rfc822_binary ((void *) response,size,&i);
+ t = fs_get((strlen(base) + strlen(v) + 1 + 2)*sizeof(char));
+ for(s = base, u = t; *s; s++) *u++ = *s;
+ *u++ = ' ';
+ for (s = v,j = 0; j < i; j++) if (s[j] > ' ') *u++ = s[j];
+ fs_give((void **) &v);
+ } else {
+ for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
+ j < i; j++) if (t[j] > ' ') *u++ = t[j];
+ }
*u = '\0'; /* tie off string for mm_dlog() */
if (stream->debug) mail_dlog (t,LOCAL->sensitive);
/* append CRLF */
@@ -754,7 +769,7 @@ long pop3_response (void *s,char *response,unsigned long size)
else ret = net_sout (LOCAL->netstream,"\015\012",2);
}
else { /* abort requested */
- ret = net_sout (LOCAL->netstream,"*\015\012",3);
+ ret = base ? NIL : net_sout (LOCAL->netstream,"*\015\012",3);
LOCAL->saslcancel = T; /* mark protocol-requested SASL cancel */
}
pop3_reply (stream); /* get response */
diff --git a/imap/src/c-client/smtp.c b/imap/src/c-client/smtp.c
index 96abd5f..30bfd29 100644
--- a/imap/src/c-client/smtp.c
+++ b/imap/src/c-client/smtp.c
@@ -59,7 +59,7 @@
/* Function prototypes */
void *smtp_challenge (void *s,unsigned long *len);
-long smtp_response (void *s,char *response,unsigned long size);
+long smtp_response (void *s,char *base,char *response,unsigned long size);
long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp);
long smtp_rcpt (SENDSTREAM *stream,ADDRESS *adr,long *error);
long smtp_send (SENDSTREAM *stream,char *command,char *args);
@@ -283,7 +283,7 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp)
{
unsigned long trial,auths, authsaved;
char *lsterr = NIL;
- char usr[MAILTMPLEN];
+ char usr[MAILTMPLEN], *base;
AUTHENTICATOR *at, *atsaved;
long ret = NIL;
for (auths = ESMTP.auth, stream->saslcancel = NIL;
@@ -311,11 +311,16 @@ long smtp_auth (SENDSTREAM *stream,NETMBX *mb,char *tmp)
mm_log (tmp,WARN);
fs_give ((void **) &lsterr);
}
+ if(at->flags & AU_SINGLE){
+ sprintf(tmp, "AUTH %s", at->name);
+ base = (char *) tmp;
+ }
+ else base = NIL;
stream->saslcancel = NIL;
- if (smtp_send (stream,"AUTH",at->name) == SMTPAUTHREADY) {
+ if ((at->flags & AU_SINGLE) || smtp_send (stream,"AUTH",at->name) == SMTPAUTHREADY) {
/* hide client authentication responses */
if (!(at->flags & AU_SECURE)) stream->sensitive = T;
- if ((*at->client) (smtp_challenge,smtp_response,"smtp",mb,stream,
+ if ((*at->client) (smtp_challenge,smtp_response,base,"smtp",mb,stream,
net_port(stream->netstream),&trial,usr)) {
if (stream->replycode == SMTPAUTHED) {
ESMTP.auth = NIL; /* disable authenticators */
@@ -375,7 +380,7 @@ void *smtp_challenge (void *s,unsigned long *len)
* Returns: T, always
*/
-long smtp_response (void *s,char *response,unsigned long size)
+long smtp_response (void *s,char* base,char *response,unsigned long size)
{
SENDSTREAM *stream = (SENDSTREAM *) s;
unsigned long i,j;
@@ -385,13 +390,13 @@ long smtp_response (void *s,char *response,unsigned long size)
for (t = (char *) rfc822_binary ((void *) response,size,&i),u = t,j = 0;
j < i; j++) if (t[j] > ' ') *u++ = t[j];
*u = '\0'; /* tie off string */
- i = smtp_send (stream,t,NIL);
+ i = base ? smtp_send(stream, base, t) : smtp_send (stream,t,NIL);
fs_give ((void **) &t);
}
else i = smtp_send (stream,"",NIL);
}
else { /* abort requested */
- i = smtp_send (stream,"*",NIL);
+ i = base ? 0L : smtp_send (stream,"*",NIL);
stream->saslcancel = T; /* mark protocol-requested SASL cancel */
}
return LONGT;
diff --git a/pith/pine.hlp b/pith/pine.hlp
index fa22dd9..1a3de03 100644
--- a/pith/pine.hlp
+++ b/pith/pine.hlp
@@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any
reasonable place to be called from.
Dummy change to get revision in pine.hlp
============= h_revision =================
-Alpine Commit 407 2020-02-09 22:46:28
+Alpine Commit 408 2020-02-19 00:39:37
============= h_news =================
<HTML>
<HEAD>
@@ -184,6 +184,11 @@ any problems you find with this release.
<LI> Add support for the OAUTHBEARER authentication method in Gmail. Thanks to
Alexander Perlis for suggesting it and explaining how the method works.
+<LI> Support for the SASL-IR IMAP extension that avoids a round trip during
+ authentication. Similar support added for the SMTP, NNTP and POP3
+ protocols. Thanks to Geoffrey Bodwin for a report that lead to this
+ implementation.
+
<LI> New variable system-certs-path that allows users to indicate the
location of the directory where certificates are located. In PC-Alpine
this must be C:\\libressl\\ssl\\certs. The C: drive can be replaced