imap-send: gracefully fail if CRAM-MD5 authentication is requested without OpenSSL

Unlike PLAIN, XOAUTH2 and OAUTHBEARER, CRAM-MD5 authentication is not supported by libcurl and requires OpenSSL. If the user tries to use CRAM-MD5 authentication without OpenSSL, the previous behaviour was to attempt to authenticate and fail with a die(error). Handle this in a better way by first checking if OpenSSL is available and then attempting to authenticate. If OpenSSL is not available, print an error message and exit gracefully. Signed-off-by: Aditya Garg <gargaditya08@live.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Aditya Garg committed Jun 20, 2025 at 12:10 UTC b9e766604df2c50b2f721479bb405409db3344d1
1 file changed +39 -27
imap-send.c
+39 -27
@@ -885,18 +885,6 @@ static char *cram(const char *challenge_64, const char *user, const char *pass)
885 return (char *)response_64;
886 }
887
888 -#else
889 -
890 -static char *cram(const char *challenge_64 UNUSED,
891 - const char *user UNUSED,
892 - const char *pass UNUSED)
893 -{
894 - die("If you want to use CRAM-MD5 authenticate method, "
895 - "you have to build git-imap-send with OpenSSL library.");
896 -}
897 -
898 -#endif
899 -
888 static int auth_cram_md5(struct imap_store *ctx, const char *prompt)
889 {
890 int ret;
@@ -915,6 +903,12 @@ static int auth_cram_md5(struct imap_store *ctx, const char *prompt)
903 return 0;
904 }
905
906 +#else
907 +
908 +#define auth_cram_md5 NULL
909 +
910 +#endif
911 +
912 static void server_fill_credential(struct imap_server_conf *srvc, struct credential *cred)
913 {
914 if (srvc->user && srvc->pass)
@@ -934,6 +928,38 @@ static void server_fill_credential(struct imap_server_conf *srvc, struct credent
928 srvc->pass = xstrdup(cred->password);
929 }
930
931 +static int try_auth_method(struct imap_server_conf *srvc,
932 + struct imap_store *ctx,
933 + struct imap *imap,
934 + const char *auth_method,
935 + enum CAPABILITY cap,
936 + int (*fn)(struct imap_store *, const char *))
937 +{
938 + struct imap_cmd_cb cb = {0};
939 +
940 + if (!CAP(cap)) {
941 + fprintf(stderr, "You specified "
942 + "%s as authentication method, "
943 + "but %s doesn't support it.\n",
944 + auth_method, srvc->host);
945 + return -1;
946 + }
947 + cb.cont = fn;
948 +
949 + if (NOT_CONSTANT(!cb.cont)) {
950 + fprintf(stderr, "If you want to use %s authentication mechanism, "
951 + "you have to build git-imap-send with OpenSSL library.",
952 + auth_method);
953 + return -1;
954 + }
955 + if (imap_exec(ctx, &cb, "AUTHENTICATE %s", auth_method) != RESP_OK) {
956 + fprintf(stderr, "IMAP error: AUTHENTICATE %s failed\n",
957 + auth_method);
958 + return -1;
959 + }
960 + return 0;
961 +}
962 +
963 static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const char *folder)
964 {
965 struct credential cred = CREDENTIAL_INIT;
@@ -1089,23 +1115,9 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c
1115 server_fill_credential(srvc, &cred);
1116
1117 if (srvc->auth_method) {
1092 - struct imap_cmd_cb cb;
1093 -
1118 if (!strcmp(srvc->auth_method, "CRAM-MD5")) {
1095 - if (!CAP(AUTH_CRAM_MD5)) {
1096 - fprintf(stderr, "You specified "
1097 - "CRAM-MD5 as authentication method, "
1098 - "but %s doesn't support it.\n", srvc->host);
1099 - goto bail;
1100 - }
1101 - /* CRAM-MD5 */
1102 -
1103 - memset(&cb, 0, sizeof(cb));
1104 - cb.cont = auth_cram_md5;
1105 - if (imap_exec(ctx, &cb, "AUTHENTICATE CRAM-MD5") != RESP_OK) {
1106 - fprintf(stderr, "IMAP error: AUTHENTICATE CRAM-MD5 failed\n");
1119 + if (try_auth_method(srvc, ctx, imap, "CRAM-MD5", AUTH_CRAM_MD5, auth_cram_md5))
1120 goto bail;
1108 - }
1121 } else {
1122 fprintf(stderr, "Unknown authentication method:%s\n", srvc->host);
1123 goto bail;