summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2020-08-29 18:58:30 -0600
committerEduardo Chappa <chappa@washington.edu>2020-08-29 18:58:30 -0600
commitf12bfecb345d42bc3b57e76b8f2e71548ceefc16 (patch)
tree23291d9542a79af1b8eb73e00db7248d94c26e7c
parent116585bd28c0dbe4c4663229eb64755545601e6c (diff)
downloadalpine-f12bfecb345d42bc3b57e76b8f2e71548ceefc16.tar.xz
* When a server expires a refresh token, Alpine needs to cancel it
internally. * Fixes to some prototyping for code related to authentication. * Fixes to documentation contributed by Dennis Davis.
-rw-r--r--alpine/imap.c42
-rw-r--r--alpine/osdep/termout.wnt.c8
-rw-r--r--alpine/osdep/termout.wnt.h2
-rw-r--r--imap/src/c-client/auth_bea.c3
-rw-r--r--imap/src/c-client/auth_oa2.c5
-rw-r--r--imap/src/c-client/mail.h1
-rw-r--r--imap/src/c-client/oauth2_aux.c15
-rw-r--r--pith/pine.hlp11
8 files changed, 57 insertions, 30 deletions
diff --git a/alpine/imap.c b/alpine/imap.c
index 7c518cf..f1654de 100644
--- a/alpine/imap.c
+++ b/alpine/imap.c
@@ -172,7 +172,8 @@ OAUTH2_S alpine_oauth2_list[] =
NULL, /* access token */
0, /* expiration time */
0, /* first time indicator */
- 1 /* client secret required */
+ 1, /* client secret required */
+ 0 /* Cancel refresh token */
},
{OUTLOOK_NAME,
{"outlook.office365.com", "smtp.office365.com", NULL, NULL},
@@ -201,7 +202,8 @@ OAUTH2_S alpine_oauth2_list[] =
NULL, /* access token */
0, /* expiration time */
0, /* first time indicator */
- 0 /* client secret required */
+ 0, /* client secret required */
+ 0 /* Cancel refresh token */
},
{OUTLOOK_NAME,
{"outlook.office365.com", "smtp.office365.com", NULL, NULL},
@@ -230,7 +232,8 @@ OAUTH2_S alpine_oauth2_list[] =
NULL, /* access token */
0, /* expiration time */
0, /* first time indicator */
- 1 /* client secret required */
+ 1, /* client secret required */
+ 0 /* Cancel refresh token */
},
{YANDEX_NAME,
{"imap.yandex.com", "smtp.yandex.com", NULL, NULL},
@@ -259,9 +262,10 @@ OAUTH2_S alpine_oauth2_list[] =
NULL, /* access token */
0, /* expiration time */
0, /* first time indicator */
- 1 /* client secret required */
+ 1, /* client secret required */
+ 0 /* Cancel refresh token */
},
- { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0},
+ { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0},
};
int
@@ -292,7 +296,7 @@ OAUTH2_S *
oauth2_select_flow(char *host)
{
OAUTH2_S *oa2list, *oa2;
- int i, n, rv;
+ int i, rv;
char *method;
if(ps_global->ttyo){
@@ -350,7 +354,7 @@ oauth2_select_flow(char *host)
char *s;
char prompt[1024];
char reply[1024];
- int sel, j;
+ int sel, n = 0, j;
for(oa2list = alpine_oauth2_list; oa2list && oa2list->name ;oa2list++)
n += strlen(oa2list->name); + 5; /* number, parenthesis, space */
@@ -1011,7 +1015,7 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method,
user[NETMAXUSER-1] = '\0';
/* The Old* variables is what c_client knows */
- OldRefreshToken = login->param[OA2_RefreshToken].value;
+ OldRefreshToken = login->cancel_refresh_token ? NULL : login->param[OA2_RefreshToken].value;
OldAccessToken = login->access_token;
OldExpirationTime = login->expiration;
@@ -1020,7 +1024,7 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method,
NewExpirationTime = 0L;
ChangeAccessToken = ChangeRefreshToken = ChangeExpirationTime = 0;
- if(token && *token){
+ if(token && *token && !login->cancel_refresh_token){
char *s, *t;
s = token;
@@ -1049,7 +1053,9 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method,
if(NewAccessToken && (NewExpirationTime == 0L || !*NewAccessToken))
fs_give((void **) &NewAccessToken);
}
- else login->first_time++;
+
+ if(NewRefreshToken == NULL)
+ login->first_time++;
if(login->first_time){ /* count how many authorization methods we support */
int nmethods, i, j;
@@ -1071,7 +1077,7 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method,
/* Default to saving what we already had saved */
- SaveRefreshToken = NewRefreshToken;
+ SaveRefreshToken = login->cancel_refresh_token ? NULL : NewRefreshToken;
SaveAccessToken = NewAccessToken;
SaveExpirationTime = NewExpirationTime;
@@ -1131,10 +1137,11 @@ mm_login_oauth2(NETMBX *mb, char *user, char *method,
oa2list->access_token = SaveAccessToken;
oa2list->expiration = SaveExpirationTime;
oa2list->first_time = login->first_time;
- *login = *oa2list; /* load login pointer */
+ oa2list->cancel_refresh_token = login->cancel_refresh_token;
+ *login = *oa2list; /* load login pointer */
}
- if(!ChangeAccessToken && !ChangeRefreshToken)
+ if(!ChangeAccessToken && !ChangeRefreshToken && !login->cancel_refresh_token)
return;
/* get ready to save this information. The format will be
@@ -2027,8 +2034,15 @@ mm_login_work(NETMBX *mb, char *user, char **pwd, long int trial,
flags = F_ON(F_QUELL_ASTERISKS, ps_global) ? OE_PASSWD_NOAST : OE_PASSWD;
flags |= OE_KEEP_TRAILING_SPACE;
#ifdef _WINDOWS
- rc = os_login_dialog(mb, user, NETMAXUSER, tmp, NETMAXPASSWD, 0, 1,
+ {
+ char *tmpp;
+ tmpp = fs_get(NETMAXPASSWD*sizeof(char));
+ rc = os_login_dialog(mb, user, NETMAXUSER, &tmpp, NETMAXPASSWD, 0, 1,
&preserve_password);
+ strncpy(tmp, tmpp, sizeof(tmp));
+ tmp[sizeof(tmp)-1] = '\0';
+ if(tmpp) fs_give((void **)&tmpp);
+ }
#else /* !_WINDOWS */
rc = optionally_enter(tmp, q_line, 0, NETMAXPASSWD,
prompt, NULL, help, &flags);
diff --git a/alpine/osdep/termout.wnt.c b/alpine/osdep/termout.wnt.c
index 778890b..95dec41 100644
--- a/alpine/osdep/termout.wnt.c
+++ b/alpine/osdep/termout.wnt.c
@@ -737,7 +737,7 @@ os_argsdialog (char **arg_text)
*/
int
os_login_dialog (NETMBX *mb, char *user_utf8, int userlen,
- char *pwd_utf8, int pwdlen, int pwc, int fixuser, int *prespass)
+ char **pwd_utf8, int pwdlen, int pwc, int fixuser, int *prespass)
{
DLGPROC dlgprc;
HINSTANCE hInst;
@@ -760,7 +760,7 @@ os_login_dialog (NETMBX *mb, char *user_utf8, int userlen,
dlgpw.userlen = userlen;
dlgpw.pwd = (LPTSTR)fs_get(pwdlen*sizeof(TCHAR));
- pwd_lptstr = utf8_to_lptstr(pwd_utf8);
+ pwd_lptstr = utf8_to_lptstr(*pwd_utf8);
_tcsncpy(dlgpw.pwd, pwd_lptstr, pwdlen - 1);
dlgpw.pwd[pwdlen - 1] = '\0';
fs_give((void **) &pwd_lptstr);
@@ -786,8 +786,8 @@ os_login_dialog (NETMBX *mb, char *user_utf8, int userlen,
tpwd_utf8 = lptstr_to_utf8(dlgpw.pwd);
if(tpwd_utf8){
- strncpy(pwd_utf8, tpwd_utf8, pwdlen - 1);
- pwd_utf8[pwdlen - 1] = '\0';
+ strncpy(*pwd_utf8, tpwd_utf8, pwdlen - 1);
+ (*pwd_utf8)[pwdlen - 1] = '\0';
fs_give((void **) &tpwd_utf8);
}
if(prespass)
diff --git a/alpine/osdep/termout.wnt.h b/alpine/osdep/termout.wnt.h
index 7344de6..1993a6b 100644
--- a/alpine/osdep/termout.wnt.h
+++ b/alpine/osdep/termout.wnt.h
@@ -39,7 +39,7 @@ void scroll_setrange(long, long);
/* dialog stuff */
int init_install_get_vars(void);
int os_argsdialog(char **);
-int os_login_dialog(NETMBX *, char *, int, char *, int, int, int, int *);
+int os_login_dialog(NETMBX *, char *, int, char **, int, int, int, int *);
int os_flagmsgdialog(struct flag_table *);
int os_sortdialog(DLG_SORTPARAM *);
int os_config_dialog(char *, int, int *, int);
diff --git a/imap/src/c-client/auth_bea.c b/imap/src/c-client/auth_bea.c
index e580042..64c3aa6 100644
--- a/imap/src/c-client/auth_bea.c
+++ b/imap/src/c-client/auth_bea.c
@@ -99,7 +99,8 @@ long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder
&& (oauth2.access_token
|| (!RefreshToken && oauth2.param[OA2_RefreshToken].value)
|| (RefreshToken && oauth2.param[OA2_RefreshToken].value
- && strcmp(RefreshToken, oauth2.param[OA2_RefreshToken].value))))
+ && strcmp(RefreshToken, oauth2.param[OA2_RefreshToken].value)
+ || oauth2.cancel_refresh_token)))
mm_login_method (mb, user, (void *) &oauth2, *trial, BEARERNAME);
}
diff --git a/imap/src/c-client/auth_oa2.c b/imap/src/c-client/auth_oa2.c
index f5345bf..dac8796 100644
--- a/imap/src/c-client/auth_oa2.c
+++ b/imap/src/c-client/auth_oa2.c
@@ -124,10 +124,11 @@ long auth_oauth2_client (authchallenge_t challenger,authrespond_t responder, cha
*/
if(!tryanother
- && (oauth2.access_token
+ && (oauth2.access_token
|| (!RefreshToken && oauth2.param[OA2_RefreshToken].value)
|| (RefreshToken && oauth2.param[OA2_RefreshToken].value
- && strcmp(RefreshToken, oauth2.param[OA2_RefreshToken].value))))
+ && strcmp(RefreshToken, oauth2.param[OA2_RefreshToken].value)
+ || oauth2.cancel_refresh_token)))
mm_login_method (mb, user, (void *) &oauth2, *trial, OA2NAME);
}
diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h
index 9a02c5f..13bbc84 100644
--- a/imap/src/c-client/mail.h
+++ b/imap/src/c-client/mail.h
@@ -1989,6 +1989,7 @@ typedef struct oauth2_s {
unsigned long expiration;
unsigned int first_time:1; /* this is the first time we get credentials for this account */
unsigned int require_secret:1; /* this server requires a client-secret */
+ int cancel_refresh_token; /* ask client to cancel refresh token */
} OAUTH2_S;
typedef struct deviceproc_s {
diff --git a/imap/src/c-client/oauth2_aux.c b/imap/src/c-client/oauth2_aux.c
index 6fab291..6b7c401 100644
--- a/imap/src/c-client/oauth2_aux.c
+++ b/imap/src/c-client/oauth2_aux.c
@@ -223,11 +223,13 @@ mm_login_oauth2_c_client_method (NETMBX *mb, char *user, char *method,
case JLong : oauth2->expiration = time(0) + *(long *) jx->value;
break;
}
+ oauth2->cancel_refresh_token = 0; /* do not cancel this token. It is good */
break;
default : { char tmp[100];
- sprintf(tmp, "Oauth2 client Received Code %d", status);
- mm_log (tmp, ERROR);
+ sprintf(tmp, "Oauth2 client Received Code %d", status);
+ mm_log (tmp, ERROR);
+ oauth2->cancel_refresh_token++;
}
break;
}
@@ -284,13 +286,16 @@ mm_login_oauth2_c_client_method (NETMBX *mb, char *user, char *method,
if(jx && jx->jtype == JString)
oauth2->expiration = time(0) + atol((char *) jx->value);
+ oauth2->cancel_refresh_token = 0; /* do not cancel this token. It is good */
+
break;
case HTTP_BAD : break;
default : { char tmp[100];
sprintf(tmp, "Oauth2 Client Received Code %d", status);
- fatal (tmp);
+ mm_log (tmp, ERROR);
+ oauth2->cancel_refresh_token++;
}
}
@@ -356,13 +361,15 @@ void oauth2deviceinfo_get_accesscode(void *inp, void *outp)
}
rv = OA2_CODE_SUCCESS;
+ oauth2->cancel_refresh_token = 0; /* do not cancel this token. It is good */
break;
default : { char tmp[100];
sprintf(tmp, "Oauth device Received Code %d", status);
mm_log (tmp, ERROR);
- }
+ oauth2->cancel_refresh_token++;
+ }
}
json_free(&json);
diff --git a/pith/pine.hlp b/pith/pine.hlp
index d4810a6..8412fca 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 504 2020-08-27 20:15:43
+Alpine Commit 505 2020-08-29 18:58:26
============= h_news =================
<HTML>
<HEAD>
@@ -250,8 +250,12 @@ problems you find with this release.
which allow a user to specify locations for certificates that the user
trusts.
-<LI> Ignore non-empty initial challenge in the GSSAPI authenticaor. Based
+<LI> Ignore non-empty initial challenge in the GSSAPI authenticator. Based
on a patch written by Jarek Polok, but submitted by Ignacio Reguero.
+
+<LI> When a server expires a refresh token, Alpine needs to cancel it
+ internally. Alpine will attempt to get a new one when it reopens the
+ folder after it cancels it.
</UL>
<P>
@@ -293,8 +297,7 @@ Bugs addressed:
<LI> Crash in PC-Alpine when using the eXternal command.
<LI> Fix in Macs that made Alpine abort a ssh connection to an imap server.
- Reported and asisted by Wang Kang.
-
+ Reported and assisted by Wang Kang.
</UL>
<P>