Browse Source

Moved OAuth code to mailimap_oauth2.[ch]

dvh-chacham15-master
Hoa V. DINH 9 years ago
parent
commit
9c8a0a5f3f
8 changed files with 218 additions and 177 deletions
  1. BIN
      build-mac/autogen-result.tar.gz
  2. +10
    -0
      build-mac/libetpan.xcodeproj/project.pbxproj
  3. +4
    -2
      src/low-level/imap/Makefile.am
  4. +0
    -56
      src/low-level/imap/mailimap.c
  5. +1
    -45
      src/low-level/imap/mailimap.h
  6. +142
    -0
      src/low-level/imap/mailimap_oauth2.c
  7. +61
    -0
      src/low-level/imap/mailimap_oauth2.h
  8. +0
    -74
      src/low-level/imap/mailimap_sender.c

BIN
build-mac/autogen-result.tar.gz View File


+ 10
- 0
build-mac/libetpan.xcodeproj/project.pbxproj View File

@ -15,6 +15,9 @@
8A75ECE6170414BA007F9972 /* mailimap_sort_types.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75ECE5170414B8007F9972 /* mailimap_sort_types.c */; };
8A75ECE7170414BA007F9972 /* mailimap_sort_types.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75ECE5170414B8007F9972 /* mailimap_sort_types.c */; };
8A75ECE8170414BA007F9972 /* mailimap_sort_types.c in Sources */ = {isa = PBXBuildFile; fileRef = 8A75ECE5170414B8007F9972 /* mailimap_sort_types.c */; };
C60136981776D16A00A5AF45 /* mailimap_oauth2.c in Sources */ = {isa = PBXBuildFile; fileRef = C60136961776D16A00A5AF45 /* mailimap_oauth2.c */; };
C60136991776D16A00A5AF45 /* mailimap_oauth2.c in Sources */ = {isa = PBXBuildFile; fileRef = C60136961776D16A00A5AF45 /* mailimap_oauth2.c */; };
C601369A1776D16A00A5AF45 /* mailimap_oauth2.c in Sources */ = {isa = PBXBuildFile; fileRef = C60136961776D16A00A5AF45 /* mailimap_oauth2.c */; };
C60E7B9A16C3809400A25BF4 /* enable.c in Sources */ = {isa = PBXBuildFile; fileRef = C60E7B9816C3809400A25BF4 /* enable.c */; };
C60E7B9D16C3809C00A25BF4 /* enable.c in Sources */ = {isa = PBXBuildFile; fileRef = C60E7B9816C3809400A25BF4 /* enable.c */; };
C60E7B9E16C3809D00A25BF4 /* enable.c in Sources */ = {isa = PBXBuildFile; fileRef = C60E7B9816C3809400A25BF4 /* enable.c */; };
@ -577,6 +580,8 @@
8A75ECEA170414E9007F9972 /* mailimap_sort_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mailimap_sort_types.h; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* libetpan.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libetpan.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C60136961776D16A00A5AF45 /* mailimap_oauth2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mailimap_oauth2.c; sourceTree = "<group>"; };
C60136971776D16A00A5AF45 /* mailimap_oauth2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mailimap_oauth2.h; sourceTree = "<group>"; };
C60E7B9816C3809400A25BF4 /* enable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = enable.c; sourceTree = "<group>"; };
C60E7B9916C3809400A25BF4 /* enable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = enable.h; sourceTree = "<group>"; };
C64BB21416E2FC2F000DB34C /* qresync_types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qresync_types.c; sourceTree = "<group>"; };
@ -1476,6 +1481,8 @@
C64EA7BE16A00CC300778456 /* mailimap_id_types.h */,
C6F9EA07105335BC0059C3BA /* mailimap_keywords.c */,
C6F9EA08105335BC0059C3BA /* mailimap_keywords.h */,
C60136961776D16A00A5AF45 /* mailimap_oauth2.c */,
C60136971776D16A00A5AF45 /* mailimap_oauth2.h */,
C6F9EA09105335BC0059C3BA /* mailimap_parser.c */,
C6F9EA0A105335BC0059C3BA /* mailimap_parser.h */,
C6F9EA0B105335BC0059C3BA /* mailimap_print.c */,
@ -2032,6 +2039,7 @@
C6517A08130E86C6004ADD56 /* namespace_types.c in Sources */,
C6517A0E130E86D3004ADD56 /* namespace_sender.c in Sources */,
C6667DEF1342ACCD00969A8E /* xlist.c in Sources */,
C60136981776D16A00A5AF45 /* mailimap_oauth2.c in Sources */,
C6CE9B1614AA9C8B00D20BA6 /* xgmlabels.c in Sources */,
365DFFD215D1C93100F2DD85 /* xgmmsgid.c in Sources */,
C6EFB8781433F1F300F805C0 /* mailstream_cfstream.c in Sources */,
@ -2214,6 +2222,7 @@
C682E2B715B315EF00BE9DA7 /* namespace_types.c in Sources */,
C682E2B815B315EF00BE9DA7 /* namespace_sender.c in Sources */,
C682E2B915B315EF00BE9DA7 /* xlist.c in Sources */,
C601369A1776D16A00A5AF45 /* mailimap_oauth2.c in Sources */,
C682E2BA15B315EF00BE9DA7 /* mailstream_cfstream.c in Sources */,
C682E2BB15B315EF00BE9DA7 /* xgmlabels.c in Sources */,
C64EA7B816A00CA700778456 /* xgmmsgid.c in Sources */,
@ -2396,6 +2405,7 @@
C6517A0A130E86C6004ADD56 /* namespace_types.c in Sources */,
C6517A10130E86D3004ADD56 /* namespace_sender.c in Sources */,
C6667DF11342ACCD00969A8E /* xlist.c in Sources */,
C60136991776D16A00A5AF45 /* mailimap_oauth2.c in Sources */,
C6EFB87A1433F1F300F805C0 /* mailstream_cfstream.c in Sources */,
C69AD25F14AB2062003D04D5 /* xgmlabels.c in Sources */,
C64EA7B716A00CA700778456 /* xgmmsgid.c in Sources */,


+ 4
- 2
src/low-level/imap/Makefile.am View File

@ -47,7 +47,8 @@ etpaninclude_HEADERS = \
enable.h condstore.h condstore_types.h \
qresync.h qresync_types.h \
mailimap_sort.h mailimap_sort_types.h \
mailimap_compress.h
mailimap_compress.h \
mailimap_oauth2.h
AM_CPPFLAGS = -I$(top_builddir)/include \
-I$(top_srcdir)/src/data-types
@ -99,4 +100,5 @@ libimap_la_SOURCES = \
qresync.h qresync.c qresync_types.h qresync_types.c qresync_private.h \
mailimap_sort.c mailimap_sort.h \
mailimap_sort_types.c mailimap_sort_types.h \
mailimap_compress.c mailimap_compress.h
mailimap_compress.c mailimap_compress.h \
mailimap_oauth2.c mailimap_oauth2.h

+ 0
- 56
src/low-level/imap/mailimap.c View File

@ -1851,62 +1851,6 @@ int mailimap_authenticate(mailimap * session, const char * auth_type,
#endif
}
LIBETPAN_EXPORT
int mailimap_oauth2_authenticate(mailimap * session, const char *auth_user, const char * access_token)
{
struct mailimap_response * response;
int r;
int error_code;
if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED)
return MAILIMAP_ERROR_BAD_STATE;
mailstream_set_privacy(session->imap_stream, 0);
r = mailimap_send_current_tag(session);
if (r != MAILIMAP_NO_ERROR) {
mailstream_set_privacy(session->imap_stream, 1);
return r;
}
r = mailimap_oauth2_authenticate_send(session, auth_user, access_token);
if (r != MAILIMAP_NO_ERROR) {
mailstream_set_privacy(session->imap_stream, 1);
return r;
}
r = mailimap_crlf_send(session->imap_stream);
if (r != MAILIMAP_NO_ERROR) {
mailstream_set_privacy(session->imap_stream, 1);
return r;
}
if (mailstream_flush(session->imap_stream) == -1) {
mailstream_set_privacy(session->imap_stream, 1);
return MAILIMAP_ERROR_STREAM;
}
mailstream_set_privacy(session->imap_stream, 1);
if (mailimap_read_line(session) == NULL)
return MAILIMAP_ERROR_STREAM;
r = mailimap_parse_response(session, &response);
if (r != MAILIMAP_NO_ERROR)
return r;
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
mailimap_response_free(response);
switch (error_code) {
case MAILIMAP_RESP_COND_STATE_OK:
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
return MAILIMAP_NO_ERROR;
default:
return MAILIMAP_ERROR_LOGIN;
}
}
LIBETPAN_EXPORT
int mailimap_lsub(mailimap * session, const char * mb,
const char * list_mb, clist ** result)


+ 1
- 45
src/low-level/imap/mailimap.h View File

@ -64,6 +64,7 @@ extern "C" {
#include <libetpan/qresync.h>
#include <libetpan/mailimap_sort.h>
#include <libetpan/mailimap_compress.h>
#include <libetpan/mailimap_oauth2.h>
/*
mailimap_connect()
@ -394,51 +395,6 @@ int mailimap_authenticate(mailimap * session, const char * auth_type,
const char * login, const char * auth_name,
const char * password, const char * realm);
/*
mailimap_oauth2_authenticate()
Authenticates the client using using an oauth2 token.
To gather a deeper understanding of the OAuth2 aunthentication
process refer to: https://developers.google.com/gmail/xoauth2_protocol
For a quick start you may follow this brief set of steps:
1. Set up a profile for your app in the Google
API Console: https://code.google.com/apis/console
2. With your recently obtained client_id and secret
load the following URL (everything goes ina single line):
https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
response_type=code&scope=https%3A%2F%2Fmail.google.com%2F&
login_hint=[USER_EMAIL_ADDRESS]&access_type=offline
3. The user most follow instructions to authorize application access
to Gmail.
4. After the user hits the "Accept" button it will be redirected to another
page where the access token will be issued.
5. Now from the app we need and authorization token, to get one we issue a POST request
the following URL: https://accounts.google.com/o/oauth2/token using these parameters:
client_id: This is the client id we got from step 1
client_secret: Client secret as we got it from step 1
code: This is the code we received in step 4
redirect_uri: This is a redirect URI where the access token will be sent, for non
web applications this is usually urn:ietf:wg:oauth:2.0:oob (as we got from step 1)
grant_type: Always use the authorization_code parameter to retrieve an access and refresh tokens
6. After step 5 completes we receive a JSON object similar to:
{
"access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
"refresh_token":"1/fFAGRNJrufoiWEGIWEFJFJF",
"expires_in":3920,
"token_type":"Bearer"
}
The access token is what we need to authenticate via XOAuth2 with Gmail.
@param session IMAP session
@param session Authentication user (tipically an e-mail address, depends on server)
@param access_token OAuth2 access token
@return the return code is one of MAILIMAP_ERROR_XXX or
MAILIMAP_NO_ERROR codes
*/
LIBETPAN_EXPORT
int mailimap_oauth2_authenticate(mailimap * session, const char *auth_user,
const char * access_token);
/*
mailimap_lsub()


+ 142
- 0
src/low-level/imap/mailimap_oauth2.c View File

@ -0,0 +1,142 @@
#include "mailimap_oauth2.h"
#include <string.h>
#include <stdlib.h>
#include "base64.h"
#include "mailimap_sender.h"
#include "mailimap.h"
int mailimap_oauth2_authenticate_send(mailimap * session,
const char * auth_user,
const char * access_token);
LIBETPAN_EXPORT
int mailimap_oauth2_authenticate(mailimap * session, const char *auth_user, const char * access_token)
{
struct mailimap_response * response;
int r;
int error_code;
if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED)
return MAILIMAP_ERROR_BAD_STATE;
mailstream_set_privacy(session->imap_stream, 0);
r = mailimap_send_current_tag(session);
if (r != MAILIMAP_NO_ERROR) {
mailstream_set_privacy(session->imap_stream, 1);
return r;
}
r = mailimap_oauth2_authenticate_send(session, auth_user, access_token);
if (r != MAILIMAP_NO_ERROR) {
mailstream_set_privacy(session->imap_stream, 1);
return r;
}
r = mailimap_crlf_send(session->imap_stream);
if (r != MAILIMAP_NO_ERROR) {
mailstream_set_privacy(session->imap_stream, 1);
return r;
}
if (mailstream_flush(session->imap_stream) == -1) {
mailstream_set_privacy(session->imap_stream, 1);
return MAILIMAP_ERROR_STREAM;
}
mailstream_set_privacy(session->imap_stream, 1);
if (mailimap_read_line(session) == NULL)
return MAILIMAP_ERROR_STREAM;
r = mailimap_parse_response(session, &response);
if (r != MAILIMAP_NO_ERROR)
return r;
error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type;
mailimap_response_free(response);
switch (error_code) {
case MAILIMAP_RESP_COND_STATE_OK:
session->imap_state = MAILIMAP_STATE_AUTHENTICATED;
return MAILIMAP_NO_ERROR;
default:
return MAILIMAP_ERROR_LOGIN;
}
}
int mailimap_oauth2_authenticate_send(mailimap * session,
const char * auth_user,
const char * access_token)
{
int r;
char * ptr;
char * full_auth_string;
char * full_auth_string_b64;
int auth_user_len;
int access_token_len;
int full_auth_string_len;
int res;
full_auth_string = NULL;
full_auth_string_b64 = NULL;
/* Build client response string */
auth_user_len = strlen(auth_user);
access_token_len = strlen(access_token);
full_auth_string_len = 5 + auth_user_len + 1 + 12 + access_token_len + 2;
full_auth_string = malloc(full_auth_string_len + 1);
if (full_auth_string == NULL) {
res = MAILIMAP_ERROR_MEMORY;
goto free;
}
ptr = memcpy(full_auth_string, "user=", 5);
ptr = memcpy(ptr + 5, auth_user, auth_user_len);
ptr = memcpy(ptr + auth_user_len, "\1auth=Bearer ", 13);
ptr = memcpy(ptr + 13, access_token, access_token_len);
ptr = memcpy(ptr + access_token_len, "\1\1\0", 3);
/* Convert to base64 */
full_auth_string_b64 = encode_base64(full_auth_string, full_auth_string_len);
if (full_auth_string_b64 == NULL) {
res = MAILIMAP_ERROR_MEMORY;
goto free;
}
r = mailimap_token_send(session->imap_stream, "AUTHENTICATE");
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_space_send(session->imap_stream);
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_token_send(session->imap_stream, "XOAUTH2");
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_space_send(session->imap_stream);
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_astring_send(session->imap_stream, full_auth_string_b64);
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
res = MAILIMAP_NO_ERROR;
free:
free(full_auth_string);
free(full_auth_string_b64);
return res;
}

+ 61
- 0
src/low-level/imap/mailimap_oauth2.h View File

@ -0,0 +1,61 @@
#ifndef MAILIMAP_OAUTH2_H
#define MAILIMAP_OAUTH2_H
#include <libetpan/mailimap_types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
mailimap_oauth2_authenticate()
Authenticates the client using using an oauth2 token.
To gather a deeper understanding of the OAuth2 aunthentication
process refer to: https://developers.google.com/gmail/xoauth2_protocol
For a quick start you may follow this brief set of steps:
1. Set up a profile for your app in the Google
API Console: https://code.google.com/apis/console
2. With your recently obtained client_id and secret
load the following URL (everything goes ina single line):
https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]&
redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&
response_type=code&scope=https%3A%2F%2Fmail.google.com%2F&
login_hint=[USER_EMAIL_ADDRESS]&access_type=offline
3. The user most follow instructions to authorize application access
to Gmail.
4. After the user hits the "Accept" button it will be redirected to another
page where the access token will be issued.
5. Now from the app we need and authorization token, to get one we issue a POST request
the following URL: https://accounts.google.com/o/oauth2/token using these parameters:
client_id: This is the client id we got from step 1
client_secret: Client secret as we got it from step 1
code: This is the code we received in step 4
redirect_uri: This is a redirect URI where the access token will be sent, for non
web applications this is usually urn:ietf:wg:oauth:2.0:oob (as we got from step 1)
grant_type: Always use the authorization_code parameter to retrieve an access and refresh tokens
6. After step 5 completes we receive a JSON object similar to:
{
"access_token":"1/fFAGRNJru1FTz70BzhT3Zg",
"refresh_token":"1/fFAGRNJrufoiWEGIWEFJFJF",
"expires_in":3920,
"token_type":"Bearer"
}
The access token is what we need to authenticate via XOAuth2 with Gmail.
@param session IMAP session
@param session Authentication user (tipically an e-mail address, depends on server)
@param access_token OAuth2 access token
@return the return code is one of MAILIMAP_ERROR_XXX or
MAILIMAP_NO_ERROR codes
*/
LIBETPAN_EXPORT
int mailimap_oauth2_authenticate(mailimap * session, const char * auth_user,
const char * access_token);
#ifdef __cplusplus
}
#endif
#endif

+ 0
- 74
src/low-level/imap/mailimap_sender.c View File

@ -472,80 +472,6 @@ int mailimap_authenticate_resp_send(mailstream * fd,
return MAILIMAP_NO_ERROR;
}
int mailimap_oauth2_authenticate_send(mailimap * session,
const char * auth_user,
const char * access_token)
{
int r;
char * ptr;
char * full_auth_string;
char * full_auth_string_b64;
int auth_user_len;
int access_token_len;
int full_auth_string_len;
int r;
full_auth_string = NULL;
full_auth_string_b64 = NULL;
/* Build client response string */
auth_user_len = strlen(auth_user);
access_token_len = strlen(access_token);
full_auth_string_len = 5 + auth_user_len + 1 + 12 + access_token_len + 2;
full_auth_string = malloc(full_auth_string_len + 1);
if (full_auth_string == NULL) {
res = MAILIMAP_ERROR_MEMORY;
goto free;
}
ptr = memcpy(full_auth_string, "user=", 5);
ptr = memcpy(ptr + 5, auth_user, auth_user_len);
ptr = memcpy(ptr + auth_user_len, "\1auth=Bearer ", 13);
ptr = memcpy(ptr + 13, access_token, access_token_len);
ptr = memcpy(ptr + access_token_len, "\1\1\0", 3);
/* Convert to base64 */
full_auth_string_b64 = encode_base64(full_auth_string, full_auth_string_len);
if (full_auth_string_b64 == NULL) {
res = MAILIMAP_ERROR_MEMORY;
goto free;
}
r = mailimap_token_send(session->imap_stream, "AUTHENTICATE");
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_space_send(session->imap_stream);
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_token_send(session->imap_stream, "XOAUTH2");
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_space_send(session->imap_stream);
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
r = mailimap_astring_send(session->imap_stream, full_auth_string_b64);
if (r != MAILIMAP_NO_ERROR) {
res = r;
goto free;
}
res = MAILIMAP_NO_ERROR;
free:
free(full_auth_string);
free(full_auth_string_b64);
err:
return res;
}
/*
=> auth-type = atom
; Defined by [SASL]


Loading…
Cancel
Save