summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2021-11-01 20:42:12 -0600
committerEduardo Chappa <chappa@washington.edu>2021-11-01 20:42:12 -0600
commita0159a2dc04389a62d81f39d91f76cfab6b7293c (patch)
tree8fdc4cd5db688294e6567639d3876386a28dbdce
parente90e7ba5b8e93f47d5e4a3f2afa1748246b079e6 (diff)
downloadalpine-a0159a2dc04389a62d81f39d91f76cfab6b7293c.tar.xz
* When Alpine is trying to decide which client-id to choose it used to limit
its choices the ps_global->vars[V_XOAUTH2_INFO].current_val.l. Now it will also use ps_global->vars[V_XOAUTH2_INFO].main_user_val.l. In addition some of the code in alpine/xoauth2conf.c was moved to the c-client library.
-rw-r--r--alpine/xoauth2conf.c117
-rw-r--r--imap/src/c-client/mail.h3
-rw-r--r--imap/src/c-client/oauth2_aux.c42
-rw-r--r--pith/pine.hlp2
4 files changed, 114 insertions, 50 deletions
diff --git a/alpine/xoauth2conf.c b/alpine/xoauth2conf.c
index 676b5867..fa4c1ddf 100644
--- a/alpine/xoauth2conf.c
+++ b/alpine/xoauth2conf.c
@@ -59,23 +59,11 @@ char *list_to_array(char **);
char **array_to_list(char *);
void write_xoauth_configuration(struct variable *, struct variable **, EditWhich);
char **xoauth2_conf_dedup_and_merge(char ***);
-int same_xoauth2_info(XOAUTH2_INFO_S, XOAUTH2_INFO_S);
XOAUTH2_INFO_S *xoauth_info_choice(XOAUTH2_INFO_S **, char *);
int xoauth2_info_tool(struct pine *, int, CONF_S **, unsigned int);
char *xoauth2_extra_text(XOAUTH2_INFO_S **, int);
-
-int
-same_xoauth2_info(XOAUTH2_INFO_S x, XOAUTH2_INFO_S y)
-{
- int rv = 0;
- if(x.name && y.name && !strcmp((char *) x.name, (char *) y.name)
- && x.client_id && y.client_id && !strcmp(x.client_id, y.client_id)
- && ((!x.client_secret && !y.client_secret)
- || (x.client_secret && y.client_secret && !strcmp(x.client_secret, y.client_secret)))
- && ((!x.tenant && !y.tenant) || (x.tenant && y.tenant && !strcmp(x.tenant, y.tenant))))
- rv = 1;
- return rv;
-}
+XOAUTH2_INFO_S **xoauth2_configured_servers(void);
+XOAUTH2_INFO_S **parse_xoauth2_info_list(char **lval, int *totalp);
char *
list_to_array(char **list)
@@ -310,45 +298,89 @@ xoauth_info_choice(XOAUTH2_INFO_S **xinfo, char *user)
return NULL;
}
+XOAUTH2_INFO_S **
+parse_xoauth2_info_list(char **lval, int *totalp)
+{
+ int i, total;
+ XOAUTH2_INFO_S **rv = NULL;
+
+ for(total = 0; lval && lval[total]; total++);
+ if(total){
+ rv = fs_get((total + 1)*sizeof(XOAUTH2_INFO_S *));
+ for(i = 0; i < total; i++)
+ rv[i] = xoauth_parse_client_info(lval[i]);
+ rv[i] = NULL;
+ }
+ *totalp = total;
+ return rv;
+}
+
+
+XOAUTH2_INFO_S **
+xoauth2_configured_servers(void)
+{
+ XOAUTH2_INFO_S **cv, **muv, **rv = NULL;
+ int cvt, muvt, rvt, i, j, total = 0;
+
+ cv = parse_xoauth2_info_list(ps_global->vars[V_XOAUTH2_INFO].current_val.l, &cvt);
+ muv = parse_xoauth2_info_list(ps_global->vars[V_XOAUTH2_INFO].main_user_val.l, &muvt);
+
+ rvt = cvt + muvt;
+ if(rvt){
+ rv = fs_get((rvt + 1)*sizeof(XOAUTH2_INFO_S *));
+ memset((void *) rv, 0, (rvt + 1)*sizeof(XOAUTH2_INFO_S *));
+
+ for(i = 0; cv && cv[i]; i++){
+ for(j = 0; rv[j] && !same_xoauth2_info(*cv[i], *rv[j]); j++);
+ if(!rv[j]) rv[total++] = copy_xoauth2_info(cv[i]);
+ }
+
+ for(i = 0; muv && muv[i]; i++){
+ for(j = 0; rv[j] && !same_xoauth2_info(*muv[i], *rv[j]); j++);
+ if(!rv[j]) rv[total++] = copy_xoauth2_info(muv[i]);
+ }
+ }
+ return rv;
+}
+
/* Get the client-id, etc. for server "name" associated to user "user" */
XOAUTH2_INFO_S *
oauth2_get_client_info(unsigned char *name, char *user)
{
int i, j, matches, len;
- char **lval;
- XOAUTH2_INFO_S *x, **xinfo;
+ XOAUTH2_INFO_S *x, **xinfo, **lval;
if(name == NULL || *name == '\0' || user == NULL || *user == '\0')
return NULL;
matches = 0;
/* first count how many servers */
- lval = ps_global->vars[V_XOAUTH2_INFO].current_val.l;
+ lval = xoauth2_configured_servers();
for(i = 0; lval && lval[i]; i++){
- x = xoauth_parse_client_info(lval[i]);
+ x = lval[i];
if(x && x->name && name && !strcmp((char *) x->name, (char *) name))
matches++;
- free_xoauth2_info(&x);
}
/* if nothing, use the default value */
for(i = 0; xoauth_default[i].name != NULL && strcmp((char *) xoauth_default[i].name, (char *) name); i++);
if(xoauth_default[i].name) matches++;
- if(matches == 0) return NULL;
- if(matches == 1) return copy_xoauth2_info(&xoauth_default[i]);
+ if(matches <= 1){
+ free_xoauth2_info_list(&lval);
+ return matches == 1 ? copy_xoauth2_info(&xoauth_default[i]) : NULL;
+ }
/* more than one match, see if it is a duplicate client-id entry */
xinfo = fs_get((matches + 1)*sizeof(XOAUTH2_INFO_S *));
memset((void *)xinfo, 0, (matches + 1)*sizeof(XOAUTH2_INFO_S *));
matches = 0; /* restart the recount, it might go lower! */
for(i = 0; lval && lval[i]; i++){
- x = xoauth_parse_client_info(lval[i]);
+ x = lval[i];
if(x && x->name && name && !strcmp((char *) x->name, (char *) name)){
for(j = 0; xinfo && xinfo[j] && !same_xoauth2_info(*x, *xinfo[j]); j++);
if(!xinfo[j]) xinfo[matches++] = copy_xoauth2_info(x);
}
- free_xoauth2_info(&x);
}
for(i = 0; xoauth_default[i].name != NULL && strcmp((char *) xoauth_default[i].name, (char *) name); i++);
for(j = 0; xinfo && xinfo[j] && !same_xoauth2_info(xoauth_default[i], *xinfo[j]); j++);
@@ -357,58 +389,57 @@ oauth2_get_client_info(unsigned char *name, char *user)
/* if after removing the duplicate entries, we only have one, use it */
if(matches == 1){
x = copy_xoauth2_info(xinfo[0]);
- for(i = 0; xinfo[i] != NULL; i++)
- free_xoauth2_info(&xinfo[i]);
- fs_give((void **) &xinfo);
+ free_xoauth2_info_list(&lval);
+ free_xoauth2_info_list(&xinfo);
return x;
}
+ x = NULL; /* reset x to null so it will not be double freed */
/* we have more than one match, now check if any of them matches the given user */
matches = 0;
for(i = 0; xinfo && xinfo[i]; i++){
- lval = array_to_list(xinfo[i]->users);
- for(j = 0; lval && lval[j] && strucmp(lval[j], user); j++);
- if(lval && lval[j]){
+ char **alval = array_to_list(xinfo[i]->users);
+ for(j = 0; alval && alval[j] && strucmp(alval[j], user); j++);
+ if(alval && alval[j]){
matches++;
free_xoauth2_info(&x);
x = copy_xoauth2_info(xinfo[i]);
}
- if(lval) free_list_array(&lval);
+ if(alval) free_list_array(&alval);
}
/* only one server matches the username */
if(matches == 1){
- for(i = 0; xinfo[i] != NULL; i++)
- free_xoauth2_info(&xinfo[i]);
- fs_give((void **) &xinfo);
+ free_xoauth2_info_list(&xinfo);
+ free_xoauth2_info_list(&lval);
return x;
}
free_xoauth2_info(&x);
+
/* We either have no matches, or have more than one match!
* in either case, let the user pick what they want */
x = xoauth_info_choice(xinfo, user);
- for(i = 0; xinfo[i] != NULL; i++)
- free_xoauth2_info(&xinfo[i]);
- fs_give((void **) &xinfo);
+ free_xoauth2_info_list(&xinfo);
+ free_xoauth2_info_list(&lval);
/* Once the user chose a client-id, save it so we do not ask again */
if(x != NULL){
int n = x->users ? strlen(x->users) + 1 : 0;
- char ***alval;
+ char ***alval, **lvalp;
fs_resize((void **) &x->users, (n + strlen(user) + 1)*sizeof(char));
x->users[n > 0 ? n - 1 : 0] = '\0';
if(n > 0) strcat(x->users, ",");
strcat(x->users, user);
alval = ALVAL(&ps_global->vars[V_XOAUTH2_INFO], Main);
- lval = *alval;
+ lvalp = *alval;
- for(n = 0; lval && lval[n]; n++);
- fs_resize((void **) &lval, (n+2)*sizeof(char *));
- lval[n] = xoauth_config_line(x);
- lval[n+1] = NULL;
- *alval = xoauth2_conf_dedup_and_merge(&lval);
+ for(n = 0; lvalp && lvalp[n]; n++);
+ fs_resize((void **) &lvalp, (n+2)*sizeof(char *));
+ lvalp[n] = xoauth_config_line(x);
+ lvalp[n+1] = NULL;
+ *alval = xoauth2_conf_dedup_and_merge(&lvalp);
set_current_val(&ps_global->vars[V_XOAUTH2_INFO], FALSE, FALSE);
write_pinerc(ps_global, Main, WRP_NONE);
}
diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h
index 8e848201..94ac64fa 100644
--- a/imap/src/c-client/mail.h
+++ b/imap/src/c-client/mail.h
@@ -2034,6 +2034,9 @@ char *oauth2_generate_state(void);
void oauth2deviceinfo_get_accesscode(void *, void *);
XOAUTH2_INFO_S *new_xoauth2_info(void);
void free_xoauth2_info(XOAUTH2_INFO_S **);
+void free_xoauth2_info_list(XOAUTH2_INFO_S ***);
XOAUTH2_INFO_S *copy_xoauth2_info(XOAUTH2_INFO_S *);
+int same_xoauth2_info(XOAUTH2_INFO_S, XOAUTH2_INFO_S);
char *oauth2_generate_state(void);
void renew_accesstoken(MAILSTREAM *);
+XOAUTH2_INFO_S **parse_xoauth2_info_list(char **, int *);
diff --git a/imap/src/c-client/oauth2_aux.c b/imap/src/c-client/oauth2_aux.c
index a0828ba4..363f41d1 100644
--- a/imap/src/c-client/oauth2_aux.c
+++ b/imap/src/c-client/oauth2_aux.c
@@ -65,7 +65,8 @@ char *xoauth2_server(char *, char *);
(Y)[i].name = (Y)[i].value = NULL; \
}
-char *xoauth2_server(char *server, char *tenant)
+char *
+xoauth2_server(char *server, char *tenant)
{
char *rv = NULL;
char *s;
@@ -100,7 +101,8 @@ char *xoauth2_server(char *server, char *tenant)
return rv;
}
-JSON_S *oauth2_json_reply(OAUTH2_SERVER_METHOD_S RefreshMethod, OAUTH2_S *oauth2, int *status)
+JSON_S *
+oauth2_json_reply(OAUTH2_SERVER_METHOD_S RefreshMethod, OAUTH2_S *oauth2, int *status)
{
JSON_S *json = NULL;
HTTP_PARAM_S params[OAUTH2_PARAM_NUMBER];
@@ -312,7 +314,8 @@ mm_login_oauth2_c_client_method (NETMBX *mb, char *user, char *method,
}
}
-void oauth2deviceinfo_get_accesscode(void *inp, void *outp)
+void
+oauth2deviceinfo_get_accesscode(void *inp, void *outp)
{
OAUTH2_DEVICEPROC_S *oad = (OAUTH2_DEVICEPROC_S *) inp;
OAUTH2_S *oauth2 = oad->xoauth2;
@@ -380,14 +383,16 @@ void oauth2deviceinfo_get_accesscode(void *inp, void *outp)
*(int *)outp = rv;
}
-XOAUTH2_INFO_S *new_xoauth2_info(void)
+XOAUTH2_INFO_S *
+new_xoauth2_info(void)
{
XOAUTH2_INFO_S *rv = fs_get(sizeof(XOAUTH2_INFO_S));
memset((void *) rv, 0, sizeof(XOAUTH2_INFO_S));
return rv;
}
-void free_xoauth2_info(XOAUTH2_INFO_S **xp)
+void
+free_xoauth2_info(XOAUTH2_INFO_S **xp)
{
if(xp == NULL || *xp == NULL) return;
@@ -400,7 +405,8 @@ void free_xoauth2_info(XOAUTH2_INFO_S **xp)
fs_give((void **) xp);
}
-XOAUTH2_INFO_S *copy_xoauth2_info(XOAUTH2_INFO_S *x)
+XOAUTH2_INFO_S *
+copy_xoauth2_info(XOAUTH2_INFO_S *x)
{
XOAUTH2_INFO_S *y;
@@ -415,6 +421,30 @@ XOAUTH2_INFO_S *copy_xoauth2_info(XOAUTH2_INFO_S *x)
return y;
}
+int
+same_xoauth2_info(XOAUTH2_INFO_S x, XOAUTH2_INFO_S y)
+{
+ int rv = 0;
+ if(x.name && y.name && !strcmp((char *) x.name, (char *) y.name)
+ && x.client_id && y.client_id && !strcmp(x.client_id, y.client_id)
+ && ((!x.client_secret && !y.client_secret)
+ || (x.client_secret && y.client_secret && !strcmp(x.client_secret, y.client_secret)))
+ && ((!x.tenant && !y.tenant) || (x.tenant && y.tenant && !strcmp(x.tenant, y.tenant))))
+ rv = 1;
+ return rv;
+}
+
+void
+free_xoauth2_info_list(XOAUTH2_INFO_S ***xp)
+{
+ int i;
+
+ if(xp == NULL || *xp == NULL || **xp) return;
+ for(i = 0; (*xp)[i] != NULL; i++) free_xoauth2_info(&(*xp)[i]);
+ fs_give((void **) &xp);
+}
+
+
/* 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.
diff --git a/pith/pine.hlp b/pith/pine.hlp
index ae07ae85..507ba91b 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 610 2021-10-30 14:28:50
+Alpine Commit 611 2021-11-01 20:42:01
============= h_news =================
<HTML>
<HEAD>