summaryrefslogtreecommitdiff
path: root/imap/src/c-client
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2020-07-28 20:52:28 -0600
committerEduardo Chappa <chappa@washington.edu>2020-07-28 20:52:28 -0600
commit0d181b64d4d433a5ec88c4bfd55cd5a1d5f9a1da (patch)
tree981d63dd006c04c1b884d0b6cbbcd6a405593ae0 /imap/src/c-client
parent6591233b484d8f303b64f9042aee516d1b3a9cc6 (diff)
downloadalpine-0d181b64d4d433a5ec88c4bfd55cd5a1d5f9a1da.tar.xz
* XOAUTH2: automatic renew of access token and connection to a server
within 60 seconds of expiration of the access token.
Diffstat (limited to 'imap/src/c-client')
-rw-r--r--imap/src/c-client/imap4r1.c26
-rw-r--r--imap/src/c-client/mail.c11
-rw-r--r--imap/src/c-client/mail.h8
-rw-r--r--imap/src/c-client/nntp.c3
-rw-r--r--imap/src/c-client/oauth2_aux.c45
-rw-r--r--imap/src/c-client/pop3.c3
6 files changed, 92 insertions, 4 deletions
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 */