From 0d181b64d4d433a5ec88c4bfd55cd5a1d5f9a1da Mon Sep 17 00:00:00 2001 From: Eduardo Chappa Date: Tue, 28 Jul 2020 20:52:28 -0600 Subject: * XOAUTH2: automatic renew of access token and connection to a server within 60 seconds of expiration of the access token. --- imap/src/c-client/imap4r1.c | 26 ++++++++++++++++++++++-- imap/src/c-client/mail.c | 11 +++++++++++ imap/src/c-client/mail.h | 8 ++++++++ imap/src/c-client/nntp.c | 3 ++- imap/src/c-client/oauth2_aux.c | 45 ++++++++++++++++++++++++++++++++++++++++++ imap/src/c-client/pop3.c | 3 ++- 6 files changed, 92 insertions(+), 4 deletions(-) (limited to 'imap/src/c-client') diff --git a/imap/src/c-client/imap4r1.c b/imap/src/c-client/imap4r1.c index db3f1190..7343122c 100644 --- a/imap/src/c-client/imap4r1.c +++ b/imap/src/c-client/imap4r1.c @@ -170,6 +170,7 @@ long imap_delete (MAILSTREAM *stream,char *mailbox); long imap_rename (MAILSTREAM *stream,char *old,char *newname); long imap_manage (MAILSTREAM *stream,char *mailbox,char *command,char *arg2); long imap_status (MAILSTREAM *stream,char *mbx,long flags); +long imap_renew (MAILSTREAM *stream,MAILSTREAM *m); MAILSTREAM *imap_open (MAILSTREAM *stream); IMAPPARSEDREPLY *imap_rimap (MAILSTREAM *stream,char *service,NETMBX *mb, char *usr,char *tmp); @@ -316,7 +317,8 @@ DRIVER imapdriver = { imap_expunge, /* expunge deleted messages */ imap_copy, /* copy messages to another mailbox */ imap_append, /* append string message to mailbox */ - imap_gc /* garbage collect stream */ + imap_gc, /* garbage collect stream */ + imap_renew /* renew stream */ }; /* prototype stream */ @@ -793,6 +795,22 @@ long imap_status (MAILSTREAM *stream,char *mbx,long flags) return ret; /* success */ } +/* IMAP renew + * Accepts: stream to renew + * returns 0 if success, 1 if failure + */ +long imap_renew (MAILSTREAM *stream, MAILSTREAM *m) +{ + IMAPLOCAL *MLOCAL = (IMAPLOCAL *) m->local; + NETSTREAM *xnetstream; + + xnetstream = LOCAL->netstream; + LOCAL->netstream = MLOCAL->netstream; + MLOCAL->netstream = xnetstream; + + return 0L; +} + /* IMAP open * Accepts: stream to open * Returns: stream to use on success, NIL on failure @@ -1210,7 +1228,11 @@ long imap_auth (MAILSTREAM *stream,NETMBX *mb,char *tmp,char *usr) while (compare_cstring ((reply = imap_reply (stream,tag))->tag,tag)) imap_soutr (stream,"*"); /* good if SASL ok and success response */ - if (ok && imap_OK (stream,reply)) return T; + if (ok && imap_OK (stream,reply)){ + if(stream->auth.name) fs_give((void **) &stream->auth.name); + stream->auth.name = cpystr(at->name); /* save method name */ + return T; + } if (!trial) { /* if main program requested cancellation */ mm_log ("IMAP Authentication cancelled",ERROR); return NIL; diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c index a9688d4b..b52d0626 100644 --- a/imap/src/c-client/mail.c +++ b/imap/src/c-client/mail.c @@ -1238,6 +1238,17 @@ long mail_status_default (MAILSTREAM *stream,char *mbx,long flags) return T; /* success */ } +/* Mail renew stream + * Accepts: stream to renew + * returns: 0 for success, 1 for failure + */ +long mail_renew_stream (MAILSTREAM *stream) +{ + MAILSTREAM *m = mail_open(NIL, stream->original_mailbox, OP_SILENT); + long rv = stream && m ? (stream->dtb->renew)(stream, m) : 1; + mail_close(m); + return rv; +} /* Mail open * Accepts: candidate stream for recycling * mailbox name diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index adcad4d9..9a02c5f9 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -1154,6 +1154,10 @@ typedef struct mail_stream { void *local; /* pointer to driver local data */ char *mailbox; /* mailbox name (canonicalized) */ char *original_mailbox; /* mailbox name (non-canonicalized) */ + struct { + char *name; /* AUTHENTICATE method */ + unsigned long expiration; /* expiration time for authentication */ + } auth; unsigned short use; /* stream use count */ unsigned short sequence; /* stream sequence */ unsigned int inbox : 1; /* stream open on an INBOX */ @@ -1582,6 +1586,8 @@ DRIVER { long (*append) (MAILSTREAM *stream,char *mailbox,append_t af,void *data); /* garbage collect stream */ void (*gc) (MAILSTREAM *stream,long gcflags); + /* renew stream */ + long (*renew) (MAILSTREAM *stream, MAILSTREAM *m); }; @@ -1706,6 +1712,7 @@ long mail_rename (MAILSTREAM *stream,char *old,char *newname); char *mail_utf7_valid (char *mailbox); long mail_status (MAILSTREAM *stream,char *mbx,long flags); long mail_status_default (MAILSTREAM *stream,char *mbx,long flags); +long mail_renew_stream (MAILSTREAM *stream); MAILSTREAM *mail_open (MAILSTREAM *stream,char *name,long options); MAILSTREAM *mail_open_work (DRIVER *d,MAILSTREAM *stream,char *name, long options); @@ -2011,3 +2018,4 @@ XOAUTH2_INFO_S *new_xoauth2_info(void); void free_xoauth2_info(XOAUTH2_INFO_S **); XOAUTH2_INFO_S *copy_xoauth2_info(XOAUTH2_INFO_S *); char *oauth2_generate_state(void); +void renew_accesstoken(MAILSTREAM *); diff --git a/imap/src/c-client/nntp.c b/imap/src/c-client/nntp.c index a46a5bd6..b8d89893 100644 --- a/imap/src/c-client/nntp.c +++ b/imap/src/c-client/nntp.c @@ -202,7 +202,8 @@ DRIVER nntpdriver = { nntp_expunge, /* expunge deleted messages */ nntp_copy, /* copy messages to another mailbox */ nntp_append, /* append string message to mailbox */ - NIL /* garbage collect stream */ + NIL, /* garbage collect stream */ + NIL /* renew stream */ }; /* prototype stream */ diff --git a/imap/src/c-client/oauth2_aux.c b/imap/src/c-client/oauth2_aux.c index 24827e70..6fab2917 100644 --- a/imap/src/c-client/oauth2_aux.c +++ b/imap/src/c-client/oauth2_aux.c @@ -405,3 +405,48 @@ XOAUTH2_INFO_S *copy_xoauth2_info(XOAUTH2_INFO_S *x) if(x->users) y->users = cpystr(x->users); return y; } + +/* This function does not create a refresh token and and + * an access token, but uses an already known refresh token + * to generate a refresh token on an ALREADY OPEN stream. + * The assumption is that the user has already unlocked all + * passwords and the app can access them from some source + * (key chain/credentials/memory) to go through this + * process seamlessly. + */ +void renew_accesstoken(MAILSTREAM *stream) +{ + OAUTH2_S oauth2; + NETMBX mb; + char user[MAILTMPLEN]; + int tryanother; + unsigned long trial = 0; + + memset((void *) &oauth2, 0, sizeof(OAUTH2_S)); + mail_valid_net_parse(stream->original_mailbox, &mb); + user[0] = '\0'; + mm_login_method (&mb, user, (void *) &oauth2, trial, stream->auth.name); + + if(oauth2.param[OA2_State].value) + fs_give((void **) &oauth2.param[OA2_State].value); + + if(stream->auth.expiration == 0){ + stream->auth.expiration = oauth2.expiration; + return; + } + + if(oauth2.access_token) + fs_give((void **) &oauth2.access_token); + + oauth2.param[OA2_State].value = oauth2_generate_state(); + + mm_login_oauth2_c_client_method (&mb, user, stream->auth.name, &oauth2, trial, &tryanother); + + if(oauth2.access_token) + mm_login_method (&mb, user, (void *) &oauth2, trial, stream->auth.name); + + stream->auth.expiration = oauth2.expiration; + if(oauth2.param[OA2_Id].value) fs_give((void **) &oauth2.param[OA2_Id].value); + if(oauth2.param[OA2_Secret].value) fs_give((void **) &oauth2.param[OA2_Secret].value); + if(oauth2.param[OA2_Tenant].value) fs_give((void **) &oauth2.param[OA2_Tenant].value); +} diff --git a/imap/src/c-client/pop3.c b/imap/src/c-client/pop3.c index b5b51486..d91b3ccd 100644 --- a/imap/src/c-client/pop3.c +++ b/imap/src/c-client/pop3.c @@ -154,7 +154,8 @@ DRIVER pop3driver = { pop3_expunge, /* expunge deleted messages */ pop3_copy, /* copy messages to another mailbox */ pop3_append, /* append string message to mailbox */ - NIL /* garbage collect stream */ + NIL, /* garbage collect stream */ + NIL /* renew stream */ }; /* prototype stream */ -- cgit v1.2.3-70-g09d2