Git fork

imap-send: add PLAIN authentication method to OpenSSL

The current implementation for PLAIN in imap-send works just fine
if using curl, but if attempted to use for OpenSSL, it is treated
as an invalid mechanism. The default implementation for OpenSSL is
IMAP LOGIN command rather than AUTH PLAIN. Since AUTH PLAIN is
still used today by many email providers in form of app passwords,
lets add an implementation that can use AUTH PLAIN if specified.

Signed-off-by: Aditya Garg <gargaditya08@live.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Aditya Garg and committed by
Junio C Hamano
ea8681e3 103d7b12

+61 -3
+2 -2
Documentation/config/imap.adoc
··· 40 40 Specify the authentication method for authenticating with the IMAP server. 41 41 If Git was built with the NO_CURL option, or if your curl version is older 42 42 than 7.34.0, or if you're running git-imap-send with the `--no-curl` 43 - option, the only supported methods are `CRAM-MD5`, `OAUTHBEARER` and 44 - `XOAUTH2`. If this is not set then `git imap-send` uses the basic IMAP 43 + option, the only supported methods are `PLAIN`, `CRAM-MD5`, `OAUTHBEARER` 44 + and `XOAUTH2`. If this is not set then `git imap-send` uses the basic IMAP 45 45 plaintext `LOGIN` command.
+59 -1
imap-send.c
··· 139 139 LITERALPLUS, 140 140 NAMESPACE, 141 141 STARTTLS, 142 + AUTH_PLAIN, 142 143 AUTH_CRAM_MD5, 143 144 AUTH_OAUTHBEARER, 144 145 AUTH_XOAUTH2, ··· 150 151 "LITERAL+", 151 152 "NAMESPACE", 152 153 "STARTTLS", 154 + "AUTH=PLAIN", 153 155 "AUTH=CRAM-MD5", 154 156 "AUTH=OAUTHBEARER", 155 157 "AUTH=XOAUTH2", ··· 851 853 } 852 854 853 855 #define ENCODED_SIZE(n) (4 * DIV_ROUND_UP((n), 3)) 856 + static char *plain_base64(const char *user, const char *pass) 857 + { 858 + struct strbuf raw = STRBUF_INIT; 859 + int b64_len; 860 + char *b64; 861 + 862 + /* 863 + * Compose the PLAIN string 864 + * 865 + * The username and password are combined to one string and base64 encoded. 866 + * "\0user\0pass" 867 + * 868 + * The method has been described in RFC4616. 869 + * 870 + * https://datatracker.ietf.org/doc/html/rfc4616 871 + */ 872 + strbuf_addch(&raw, '\0'); 873 + strbuf_addstr(&raw, user); 874 + strbuf_addch(&raw, '\0'); 875 + strbuf_addstr(&raw, pass); 876 + 877 + b64 = xmallocz(ENCODED_SIZE(raw.len)); 878 + b64_len = EVP_EncodeBlock((unsigned char *)b64, (unsigned char *)raw.buf, raw.len); 879 + strbuf_release(&raw); 880 + 881 + if (b64_len < 0) { 882 + free(b64); 883 + return NULL; 884 + } 885 + return b64; 886 + } 887 + 854 888 static char *cram(const char *challenge_64, const char *user, const char *pass) 855 889 { 856 890 int i, resp_len, encoded_len, decoded_len; ··· 947 981 return b64; 948 982 } 949 983 984 + static int auth_plain(struct imap_store *ctx, const char *prompt UNUSED) 985 + { 986 + int ret; 987 + char *b64; 988 + 989 + b64 = plain_base64(ctx->cfg->user, ctx->cfg->pass); 990 + if (!b64) 991 + return error("PLAIN: base64 encoding failed"); 992 + 993 + /* Send the base64-encoded response */ 994 + ret = socket_write(&ctx->imap->buf.sock, b64, strlen(b64)); 995 + if (ret != (int)strlen(b64)) { 996 + free(b64); 997 + return error("IMAP error: sending PLAIN response failed"); 998 + } 999 + 1000 + free(b64); 1001 + return 0; 1002 + } 1003 + 950 1004 static int auth_cram_md5(struct imap_store *ctx, const char *prompt) 951 1005 { 952 1006 int ret; ··· 1007 1061 1008 1062 #else 1009 1063 1064 + #define auth_plain NULL 1010 1065 #define auth_cram_md5 NULL 1011 1066 #define auth_oauthbearer NULL 1012 1067 #define auth_xoauth2 NULL ··· 1219 1274 server_fill_credential(srvc, &cred); 1220 1275 1221 1276 if (srvc->auth_method) { 1222 - if (!strcmp(srvc->auth_method, "CRAM-MD5")) { 1277 + if (!strcmp(srvc->auth_method, "PLAIN")) { 1278 + if (try_auth_method(srvc, ctx, imap, "PLAIN", AUTH_PLAIN, auth_plain)) 1279 + goto bail; 1280 + } else if (!strcmp(srvc->auth_method, "CRAM-MD5")) { 1223 1281 if (try_auth_method(srvc, ctx, imap, "CRAM-MD5", AUTH_CRAM_MD5, auth_cram_md5)) 1224 1282 goto bail; 1225 1283 } else if (!strcmp(srvc->auth_method, "OAUTHBEARER")) {