imap-send: drop global `imap_server_conf` variable

In "imap-send.c", we have a global `sturct imap_server_conf` variable that keeps track of the configuration of the IMAP server. This variable is being populated mostly via the Git configuration. Refactor the code to allocate the structure on the stack instead of having it globally. This change allows us to track its lifetime more closely. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jun 7, 2024 at 08:39 UTC cea1ff7f1fb65daaf1059bdc0e5b65e2a2e3b89b
1 file changed +30 -27
imap-send.c
+30 -27
@@ -82,10 +82,6 @@ struct imap_server_conf {
82 char *auth_method;
83 };
84
85 -static struct imap_server_conf server = {
86 - .ssl_verify = 1,
87 -};
88 -
85 struct imap_socket {
86 int fd[2];
87 SSL *ssl;
@@ -110,6 +106,7 @@ struct imap {
106 };
107
108 struct imap_store {
109 + const struct imap_server_conf *cfg;
110 /* currently open mailbox */
111 const char *name; /* foreign! maybe preset? */
112 int uidvalidity;
@@ -194,8 +191,8 @@ static void socket_perror(const char *func, struct imap_socket *sock, int ret)
191
192 #ifdef NO_OPENSSL
193 static int ssl_socket_connect(struct imap_socket *sock UNUSED,
197 - int use_tls_only UNUSED,
198 - int verify UNUSED)
194 + const struct imap_server_conf *cfg,
195 + int use_tls_only UNUSED)
196 {
197 fprintf(stderr, "SSL requested but SSL support not compiled in\n");
198 return -1;
@@ -250,7 +247,9 @@ static int verify_hostname(X509 *cert, const char *hostname)
247 cname, hostname);
248 }
249
253 -static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
250 +static int ssl_socket_connect(struct imap_socket *sock,
251 + const struct imap_server_conf *cfg,
252 + int use_tls_only)
253 {
254 #if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
255 const SSL_METHOD *meth;
@@ -279,7 +278,7 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
278 if (use_tls_only)
279 SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
280
282 - if (verify)
281 + if (cfg->ssl_verify)
282 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
283
284 if (!SSL_CTX_set_default_verify_paths(ctx)) {
@@ -306,9 +305,9 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
305 * OpenSSL does not document this function, but the implementation
306 * returns 1 on success, 0 on failure after calling SSLerr().
307 */
309 - ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
308 + ret = SSL_set_tlsext_host_name(sock->ssl, cfg->host);
309 if (ret != 1)
311 - warning("SSL_set_tlsext_host_name(%s) failed.", server.host);
310 + warning("SSL_set_tlsext_host_name(%s) failed.", cfg->host);
311 #endif
312
313 ret = SSL_connect(sock->ssl);
@@ -317,12 +316,12 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
316 return -1;
317 }
318
320 - if (verify) {
319 + if (cfg->ssl_verify) {
320 /* make sure the hostname matches that of the certificate */
321 cert = SSL_get_peer_certificate(sock->ssl);
322 if (!cert)
323 return error("unable to get peer certificate.");
325 - if (verify_hostname(cert, server.host) < 0)
324 + if (verify_hostname(cert, cfg->host) < 0)
325 return -1;
326 }
327
@@ -895,7 +894,7 @@ static int auth_cram_md5(struct imap_store *ctx, const char *prompt)
894 int ret;
895 char *response;
896
898 - response = cram(prompt, server.user, server.pass);
897 + response = cram(prompt, ctx->cfg->user, ctx->cfg->pass);
898
899 ret = socket_write(&ctx->imap->buf.sock, response, strlen(response));
900 if (ret != strlen(response))
@@ -935,6 +934,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c
934
935 CALLOC_ARRAY(ctx, 1);
936
937 + ctx->cfg = srvc;
938 ctx->imap = CALLOC_ARRAY(imap, 1);
939 imap->buf.sock.fd[0] = imap->buf.sock.fd[1] = -1;
940 imap->in_progress_append = &imap->in_progress;
@@ -1035,7 +1035,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c
1035 imap->buf.sock.fd[1] = dup(s);
1036
1037 if (srvc->use_ssl &&
1038 - ssl_socket_connect(&imap->buf.sock, 0, srvc->ssl_verify)) {
1038 + ssl_socket_connect(&imap->buf.sock, srvc, 0)) {
1039 close(s);
1040 goto bail;
1041 }
@@ -1068,8 +1068,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc, const c
1068 if (!srvc->use_ssl && CAP(STARTTLS)) {
1069 if (imap_exec(ctx, NULL, "STARTTLS") != RESP_OK)
1070 goto bail;
1071 - if (ssl_socket_connect(&imap->buf.sock, 1,
1072 - srvc->ssl_verify))
1071 + if (ssl_socket_connect(&imap->buf.sock, srvc, 1))
1072 goto bail;
1073 /* capabilities may have changed, so get the new capabilities */
1074 if (imap_exec(ctx, NULL, "CAPABILITY") != RESP_OK)
@@ -1299,23 +1298,24 @@ static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)
1298 static int git_imap_config(const char *var, const char *val,
1299 const struct config_context *ctx, void *cb)
1300 {
1301 + struct imap_server_conf *cfg = cb;
1302
1303 if (!strcmp("imap.sslverify", var))
1304 - server.ssl_verify = git_config_bool(var, val);
1304 + cfg->ssl_verify = git_config_bool(var, val);
1305 else if (!strcmp("imap.preformattedhtml", var))
1306 - server.use_html = git_config_bool(var, val);
1306 + cfg->use_html = git_config_bool(var, val);
1307 else if (!strcmp("imap.folder", var))
1308 - return git_config_string(&server.folder, var, val);
1308 + return git_config_string(&cfg->folder, var, val);
1309 else if (!strcmp("imap.user", var))
1310 - return git_config_string(&server.user, var, val);
1310 + return git_config_string(&cfg->user, var, val);
1311 else if (!strcmp("imap.pass", var))
1312 - return git_config_string(&server.pass, var, val);
1312 + return git_config_string(&cfg->pass, var, val);
1313 else if (!strcmp("imap.tunnel", var))
1314 - return git_config_string(&server.tunnel, var, val);
1314 + return git_config_string(&cfg->tunnel, var, val);
1315 else if (!strcmp("imap.authmethod", var))
1316 - return git_config_string(&server.auth_method, var, val);
1316 + return git_config_string(&cfg->auth_method, var, val);
1317 else if (!strcmp("imap.port", var))
1318 - server.port = git_config_int(var, val, ctx->kvi);
1318 + cfg->port = git_config_int(var, val, ctx->kvi);
1319 else if (!strcmp("imap.host", var)) {
1320 if (!val) {
1321 return config_error_nonbool(var);
@@ -1324,11 +1324,11 @@ static int git_imap_config(const char *var, const char *val,
1324 val += 5;
1325 else if (starts_with(val, "imaps:")) {
1326 val += 6;
1327 - server.use_ssl = 1;
1327 + cfg->use_ssl = 1;
1328 }
1329 if (starts_with(val, "//"))
1330 val += 2;
1331 - server.host = xstrdup(val);
1331 + cfg->host = xstrdup(val);
1332 }
1333 } else
1334 return git_default_config(var, val, ctx, cb);
@@ -1497,12 +1497,15 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
1497
1498 int cmd_main(int argc, const char **argv)
1499 {
1500 + struct imap_server_conf server = {
1501 + .ssl_verify = 1,
1502 + };
1503 struct strbuf all_msgs = STRBUF_INIT;
1504 int total;
1505 int nongit_ok;
1506
1507 setup_git_directory_gently(&nongit_ok);
1505 - git_config(git_imap_config, NULL);
1508 + git_config(git_imap_config, &server);
1509
1510 argc = parse_options(argc, (const char **)argv, "", imap_send_options, imap_send_usage, 0);
1511