X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/012d05c2b62332eb400d66b806e48216d39358c6..94187a80bd60baab4b9c4b949ad820d730578123:/h/oauth.h diff --git a/h/oauth.h b/h/oauth.h index a49cb4ac..7aa112c5 100644 --- a/h/oauth.h +++ b/h/oauth.h @@ -1,13 +1,12 @@ -/* - * Implementation of OAuth 2.0 [1] for XOAUTH2 in SMTP [2] and POP3 [3]. +/* oauth.h -- OAuth 2.0 implementation for XOAUTH2 in SMTP and POP3. * * Google defined XOAUTH2 for SMTP, and that's what we use here. If other * providers implement XOAUTH2 or some similar OAuth-based SMTP authentication * protocol, it should be simple to extend this. * - * [1] https://tools.ietf.org/html/rfc6749 - * [2] https://developers.google.com/gmail/xoauth2_protocol - * [3] http://googleappsdeveloper.blogspot.com/2014/10/updates-on-authentication-for-gmail.html + * OAuth https://tools.ietf.org/html/rfc6749 + * SMTP https://developers.google.com/gmail/xoauth2_protocol + * POP3 http://googleappsdeveloper.blogspot.com/2014/10/updates-on-authentication-for-gmail.html * * Presumably [2] should document POP3 and that is an over-sight. As it stands, * that blog post is the closest we have to documentation. @@ -20,7 +19,7 @@ * 1. User runs mhlogin which prints a URL the user must visit, and prompts for * a code retrieved from that page. * - * 2. User vists this URL in browser, signs in with some Google account, and + * 2. User visits this URL in browser, signs in with some Google account, and * copies and pastes the resulting code back to mhlogin. * * 3. mhlogin does HTTP POST to Google to exchange the user-provided code for a @@ -63,6 +62,10 @@ typedef enum { /* Attempting to refresh an access token without a refresh token. */ MH_OAUTH_NO_REFRESH, + + /* requested user not in cred file */ + MH_OAUTH_CRED_USER_NOT_FOUND, + /* error loading serialized credentials */ MH_OAUTH_CRED_FILE } mh_oauth_err_code; @@ -71,18 +74,48 @@ typedef struct mh_oauth_ctx mh_oauth_ctx; typedef struct mh_oauth_cred mh_oauth_cred; +typedef struct mh_oauth_service_info mh_oauth_service_info; + +struct mh_oauth_service_info { + /* Name of service, so we can search static internal services array + * and for determining default credential file name. */ + char *name; + + /* Human-readable name of the service; in mh_oauth_ctx::svc this is not + * another buffer to free, but a pointer to either static SERVICE data + * (below) or to the name field. */ + char *display_name; + + /* [1] 2.2 Client Identifier, 2.3.1 Client Password */ + char *client_id; + /* [1] 2.3.1 Client Password */ + char *client_secret; + /* [1] 3.1 Authorization Endpoint */ + char *auth_endpoint; + /* [1] 3.1.2 Redirection Endpoint */ + char *redirect_uri; + /* [1] 3.2 Token Endpoint */ + char *token_endpoint; + /* [1] 3.3 Access Token Scope */ + char *scope; +}; + /* * Do the complete dance for XOAUTH2 as used by POP3 and SMTP. * * Load tokens for svc from disk, refresh if necessary, and return the - * base64-encoded client response. + * client response in client_response and client_response_len. * * If refreshing, writes freshened tokens to disk. * * Exits via adios on any error. + * + * Always returns OK for now, but in the future could return NOTOK on error. */ -char * -mh_oauth_do_xoauth(const char *user, const char *svc, FILE *log); + +int +mh_oauth_do_xoauth(const char *user, const char *svc, unsigned char **oauth_res, + size_t *oauth_res_len, FILE *log); /* * Allocate and initialize a new OAuth context. @@ -95,9 +128,9 @@ mh_oauth_do_xoauth(const char *user, const char *svc, FILE *log); * * Accesses global m_defs via context_find. * - * On error, return FALSE and set an error in ctx; ctx is always allocated. + * On error, return false and set an error in ctx; ctx is always allocated. */ -boolean +bool mh_oauth_new(mh_oauth_ctx **ctx, const char *svc_name); /* @@ -112,7 +145,7 @@ mh_oauth_free(mh_oauth_ctx *ctx); * Never returns NULL. */ const char * -mh_oauth_svc_display_name(const mh_oauth_ctx *ctx); +mh_oauth_svc_display_name(const mh_oauth_ctx *ctx) PURE; /* * Enable logging for subsequent operations on ctx. @@ -131,7 +164,7 @@ mh_oauth_log_to(FILE *log, mh_oauth_ctx *ctx); * Must not be called if an error was not indicated. */ mh_oauth_err_code -mh_oauth_get_err_code(const mh_oauth_ctx *ctx); +mh_oauth_get_err_code(const mh_oauth_ctx *ctx) PURE; /* * Return null-terminated error message after some function indicated an error. @@ -163,16 +196,16 @@ mh_oauth_authorize(const char *code, mh_oauth_ctx *ctx); /* * Refresh access (and maybe refresh) token if refresh token present. * - * On error, return FALSE and leave cred untouched. + * On error, return false and leave cred untouched. */ -boolean +bool mh_oauth_refresh(mh_oauth_cred *cred); /* * Return whether access token is present and not expired at time T. */ -boolean -mh_oauth_access_token_valid(time_t t, const mh_oauth_cred *cred); +bool +mh_oauth_access_token_valid(time_t t, const mh_oauth_cred *cred) PURE; /* * Free all resources associated with cred. @@ -187,26 +220,26 @@ mh_oauth_cred_free(mh_oauth_cred *cred); * * Never returns NULL. */ -const char * -mh_oauth_cred_fn(mh_oauth_ctx *ctx); +char * +mh_oauth_cred_fn(const char *svc_name); /* * Serialize OAuth tokens to file. * - * On error, return FALSE. + * On error, return false. */ -boolean -mh_oauth_cred_save(FILE *fp, mh_oauth_cred *cred); +bool +mh_oauth_cred_save(FILE *fp, mh_oauth_cred *cred, const char *user); /* * Load OAuth tokens from file. * - * Calls m_getfld(), which writes to stderr with advise(). + * Calls m_getfld2(), which writes to stderr with advise(). * * On error, return NULL. */ mh_oauth_cred * -mh_oauth_cred_load(FILE *fp, mh_oauth_ctx *ctx); +mh_oauth_cred_load(FILE *fp, mh_oauth_ctx *ctx, const char *user); /* * Return null-terminated SASL client response for XOAUTH2 from access token. @@ -219,3 +252,11 @@ mh_oauth_cred_load(FILE *fp, mh_oauth_ctx *ctx); const char * mh_oauth_sasl_client_response(size_t *res_len, const char *user, const mh_oauth_cred *cred); + +/* + * Retrieve the various entries for the OAuth mechanism + */ + +bool +mh_oauth_get_service_info(const char *svc_name, mh_oauth_service_info *svcinfo, + char *errbuf, size_t errbuflen);