diff options
author | Eduardo Chappa <chappa@washington.edu> | 2020-06-12 02:21:59 -0600 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2020-06-12 02:21:59 -0600 |
commit | 6c120b9e3730f997af56fbbe19229915b6380b2d (patch) | |
tree | 2acef9df0ffa1991a90cc1ded54400d1e0c1b35f /imap/src/c-client/auth_bea.c | |
parent | d600da07926e1ec3243c2a96cd988c61d6a97614 (diff) | |
download | alpine-6c120b9e3730f997af56fbbe19229915b6380b2d.tar.xz |
* Initial implementation of XOAUTH2 authentication support for Outlook.
Based on documentation suggested by Andrew C Aitchison.
Diffstat (limited to 'imap/src/c-client/auth_bea.c')
-rw-r--r-- | imap/src/c-client/auth_bea.c | 181 |
1 files changed, 2 insertions, 179 deletions
diff --git a/imap/src/c-client/auth_bea.c b/imap/src/c-client/auth_bea.c index 6079fb7b..bf5c9c1e 100644 --- a/imap/src/c-client/auth_bea.c +++ b/imap/src/c-client/auth_bea.c @@ -11,12 +11,11 @@ * ======================================================================== */ +#include "oauth2_aux.h" + 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 -void mm_login_oauth2_c_client_method (NETMBX *, char *, char *, OAUTH2_S *, unsigned long, int *); -#endif /* HTTP_OAUTH2_INCLUDED */ AUTHENTICATOR auth_bea = { AU_HIDE | AU_SINGLE, /* hidden, single trip */ @@ -34,38 +33,6 @@ AUTHENTICATOR auth_bea = { #define BEARER_HOST "host=" #define BEARER_PORT "port=" -#ifndef OAUTH2_GENERATE_STATE -#define OAUTH2_GENERATE_STATE -char *oauth2_generate_state(void); - -/* we generate something like a guid, but not care about - * anything, but that it is really random. - */ -char *oauth2_generate_state(void) -{ - char rv[37]; - int i; - - rv[0] = '\0'; - for(i = 0; i < 4; i++) - sprintf(rv + strlen(rv), "%x", (unsigned int) (random() % 256)); - sprintf(rv + strlen(rv), "%c", '-'); - for(i = 0; i < 2; i++) - sprintf(rv + strlen(rv), "%x", (unsigned int) (random() % 256)); - sprintf(rv + strlen(rv), "%c", '-'); - for(i = 0; i < 2; i++) - sprintf(rv + strlen(rv), "%x", (unsigned int) (random() % 256)); - sprintf(rv + strlen(rv), "%c", '-'); - for(i = 0; i < 2; i++) - sprintf(rv + strlen(rv), "%x", (unsigned int) (random() % 256)); - sprintf(rv + strlen(rv), "%c", '-'); - for(i = 0; i < 6; i++) - sprintf(rv + strlen(rv), "%x", (unsigned int) (random() % 256)); - rv[36] = '\0'; - return cpystr(rv); -} -#endif /* OAUTH2_GENERATE_STATE */ - /* Client authenticator * Accepts: challenger function * responder function @@ -196,147 +163,3 @@ long auth_oauthbearer_client (authchallenge_t challenger,authrespond_t responder *trial = 65535; /* don't retry if bad protocol */ return ret; } - -#ifndef HTTP_OAUTH2_INCLUDED -#define HTTP_OAUTH2_INCLUDED -/* - * The code above is enough to implement OAUTHBEARER, all one needs is the username - * and access token and give it to the function above. However, normal users cannot - * be expected to get the access token, so we ask the client to help with getting - * the access token, refresh token and expire values, so the code below is written - * to help with that. - */ - -#include "http.h" -#include "json.h" - -void -mm_login_oauth2_c_client_method (NETMBX *mb, char *user, char *method, - OAUTH2_S *oauth2, unsigned long trial, int *tryanother) -{ - int i; - HTTP_PARAM_S params[OAUTH2_PARAM_NUMBER]; - OAUTH2_SERVER_METHOD_S RefreshMethod; - unsigned char *s = NULL; - JSON_S *json = NULL; - int status = 0; - - if(oauth2->param[OA2_Id].value == NULL || oauth2->param[OA2_Secret].value == NULL){ - oauth2clientinfo_t ogci = - (oauth2clientinfo_t) mail_parameters (NIL, GET_OA2CLIENTINFO, NIL); - - if(ogci) (*ogci)(oauth2->name, &oauth2->param[OA2_Id].value, - &oauth2->param[OA2_Secret].value); - } - - if(oauth2->param[OA2_Id].value == NULL || oauth2->param[OA2_Secret].value == NULL) - return; - - /* first check if we have a refresh token, and in that case use it */ - if(oauth2->param[OA2_RefreshToken].value){ - - RefreshMethod = oauth2->server_mthd[OA2_GetAccessTokenFromRefreshToken]; - for(i = 0; RefreshMethod.params[i] != OA2_End; i++){ - OA2_type j = RefreshMethod.params[i]; - params[i].name = oauth2->param[j].name; - params[i].value = oauth2->param[j].value; - } - params[i].name = params[i].value = NULL; - - if(strcmp(RefreshMethod.name, "POST") == 0) - s = http_post_param(RefreshMethod.urlserver, params, &status); - else if(strcmp(RefreshMethod.name, "POST2") == 0) - s = http_post_param2(RefreshMethod.urlserver, params, &status); - - if(status != 200 && s) - fs_give((void **) &s); /* at this moment ignore the reply text */ - - if(s){ - unsigned char *u = s; - json = json_parse(&u); - fs_give((void **) &s); - } - - if(json != NULL){ - JSON_X *jx; - - jx = json_body_value(json, "access_token"); - if(jx && jx->jtype == JString) - oauth2->access_token = cpystr((char *) jx->value); - - jx = json_body_value(json, "expires_in"); - if(jx && jx->jtype == JString) - oauth2->expiration = time(0) + atol((char *) jx->value); - - json_free(&json); - } - return; - } - /* - * else, we do not have a refresh token, nor an access token. - * We need to start the process to get an access code. We use this - * to get an access token and refresh token. - */ - { - RefreshMethod = oauth2->server_mthd[OA2_GetAccessCode]; - for(i = 0; RefreshMethod.params[i] != OA2_End; i++){ - OA2_type j = RefreshMethod.params[i]; - params[i].name = oauth2->param[j].name; - params[i].value = oauth2->param[j].value; - } - params[i].name = params[i].value = NULL; - - if(strcmp(RefreshMethod.name, "GET") == 0){ - unsigned char *url = http_get_param_url(RefreshMethod.urlserver, params); - oauth2getaccesscode_t ogac = - (oauth2getaccesscode_t) mail_parameters (NIL, GET_OA2CLIENTGETACCESSCODE, NIL); - - if(ogac) - oauth2->param[OA2_Code].value = (*ogac)(url, method, oauth2, tryanother); - } - - if(oauth2->param[OA2_Code].value){ - RefreshMethod = oauth2->server_mthd[OA2_GetAccessTokenFromAccessCode]; - for(i = 0; RefreshMethod.params[i] != OA2_End; i++){ - OA2_type j = RefreshMethod.params[i]; - params[i].name = oauth2->param[j].name; - params[i].value = oauth2->param[j].value; - } - params[i].name = params[i].value = NULL; - - if(strcmp(RefreshMethod.name, "POST") == 0) - s = http_post_param(RefreshMethod.urlserver, params, &status); - else if(strcmp(RefreshMethod.name, "POST2") == 0) - s = http_post_param2(RefreshMethod.urlserver, params, &status); - - if(status != 200 && s) - fs_give((void **) &s); /* at this moment ignore the error */ - - if(s){ - unsigned char *u = s; - json = json_parse(&u); - fs_give((void **) &s); - } - - if(json != NULL){ - JSON_X *jx; - - jx = json_body_value(json, "refresh_token"); - if(jx && jx->jtype == JString) - oauth2->param[OA2_RefreshToken].value = cpystr((char *) jx->value); - - jx = json_body_value(json, "access_token"); - if(jx && jx->jtype == JString) - oauth2->access_token = cpystr((char *) jx->value); - - jx = json_body_value(json, "expires_in"); - if(jx && jx->jtype == JString) - oauth2->expiration = time(0) + atol((char *) jx->value); - - json_free(&json); - } - } - return; - } -} -#endif /* HTTP_OAUTH2_INCLUDED */ |