quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tool_ssls.c (5981B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "tool_setup.h"
     25 
     26 #include "tool_cfgable.h"
     27 #include "tool_cb_dbg.h"
     28 #include "tool_msgs.h"
     29 #include "tool_setopt.h"
     30 #include "tool_ssls.h"
     31 #include "tool_parsecfg.h"
     32 
     33 /* The maximum line length for an ecoded session ticket */
     34 #define MAX_SSLS_LINE (64 * 1024)
     35 
     36 
     37 static CURLcode tool_ssls_easy(struct OperationConfig *config,
     38                                CURLSH *share, CURL **peasy)
     39 {
     40   CURLcode result = CURLE_OK;
     41   struct GlobalConfig *global = config->global;
     42 
     43   *peasy = curl_easy_init();
     44   if(!*peasy)
     45     return CURLE_OUT_OF_MEMORY;
     46 
     47   result = curl_easy_setopt(*peasy, CURLOPT_SHARE, share);
     48   if(!result && (global->tracetype != TRACE_NONE)) {
     49     my_setopt(*peasy, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
     50     my_setopt(*peasy, CURLOPT_DEBUGDATA, config);
     51     my_setopt_long(*peasy, CURLOPT_VERBOSE, 1L);
     52   }
     53   return result;
     54 }
     55 
     56 CURLcode tool_ssls_load(struct OperationConfig *config,
     57                         CURLSH *share, const char *filename)
     58 {
     59   FILE *fp;
     60   CURL *easy = NULL;
     61   struct dynbuf buf;
     62   unsigned char *shmac = NULL, *sdata = NULL;
     63   char *c, *line, *end;
     64   size_t shmac_len, sdata_len;
     65   CURLcode r = CURLE_OK;
     66   int i, imported;
     67   bool error = FALSE;
     68   struct GlobalConfig *global = config->global;
     69 
     70   curlx_dyn_init(&buf, MAX_SSLS_LINE);
     71   fp = fopen(filename, FOPEN_READTEXT);
     72   if(!fp) { /* ok if it does not exist */
     73     notef(global, "SSL session file does not exist (yet?): %s", filename);
     74     goto out;
     75   }
     76 
     77   r = tool_ssls_easy(config, share, &easy);
     78   if(r)
     79     goto out;
     80 
     81   i = imported = 0;
     82   while(my_get_line(fp, &buf, &error)) {
     83     ++i;
     84     curl_free(shmac);
     85     curl_free(sdata);
     86     line = curlx_dyn_ptr(&buf);
     87 
     88     c = memchr(line, ':', strlen(line));
     89     if(!c) {
     90       warnf(global, "unrecognized line %d in ssl session file %s",
     91             i, filename);
     92       continue;
     93     }
     94     *c = '\0';
     95     r = curlx_base64_decode(line, &shmac, &shmac_len);
     96     if(r) {
     97       warnf(global, "invalid shmax base64 encoding in line %d", i);
     98       continue;
     99     }
    100     line = c + 1;
    101     end = line + strlen(line) - 1;
    102     while((end > line) && (*end == '\n' || *end == '\r' || ISBLANK(*line))) {
    103       *end = '\0';
    104       --end;
    105     }
    106     r = curlx_base64_decode(line, &sdata, &sdata_len);
    107     if(r) {
    108       warnf(global, "invalid sdata base64 encoding in line %d: %s", i, line);
    109       continue;
    110     }
    111 
    112     r = curl_easy_ssls_import(easy, NULL, shmac, shmac_len, sdata, sdata_len);
    113     if(r) {
    114       warnf(global, "import of session from line %d rejected(%d)", i, r);
    115       continue;
    116     }
    117     ++imported;
    118   }
    119   if(error)
    120     r = CURLE_FAILED_INIT;
    121   else
    122     r = CURLE_OK;
    123 
    124 out:
    125   if(easy)
    126     curl_easy_cleanup(easy);
    127   if(fp)
    128     fclose(fp);
    129   curlx_dyn_free(&buf);
    130   curl_free(shmac);
    131   curl_free(sdata);
    132   return r;
    133 }
    134 
    135 struct tool_ssls_ctx {
    136   struct GlobalConfig *global;
    137   FILE *fp;
    138   int exported;
    139 };
    140 
    141 static CURLcode tool_ssls_exp(CURL *easy, void *userptr,
    142                               const char *session_key,
    143                               const unsigned char *shmac, size_t shmac_len,
    144                               const unsigned char *sdata, size_t sdata_len,
    145                               curl_off_t valid_until, int ietf_tls_id,
    146                               const char *alpn, size_t earlydata_max)
    147 {
    148   struct tool_ssls_ctx *ctx = userptr;
    149   char *enc = NULL;
    150   size_t enc_len;
    151   CURLcode r;
    152 
    153   (void)easy;
    154   (void)valid_until;
    155   (void)ietf_tls_id;
    156   (void)alpn;
    157   (void)earlydata_max;
    158   if(!ctx->exported)
    159     fputs("# Your SSL session cache. https://curl.se/docs/ssl-sessions.html\n"
    160         "# This file was generated by libcurl! Edit at your own risk.\n",
    161         ctx->fp);
    162 
    163   r = curlx_base64_encode((const char *)shmac, shmac_len, &enc, &enc_len);
    164   if(r)
    165     goto out;
    166   r = CURLE_WRITE_ERROR;
    167   if(enc_len != fwrite(enc, 1, enc_len, ctx->fp))
    168     goto out;
    169   if(EOF == fputc(':', ctx->fp))
    170     goto out;
    171   curl_free(enc);
    172   r = curlx_base64_encode((const char *)sdata, sdata_len, &enc, &enc_len);
    173   if(r)
    174     goto out;
    175   r = CURLE_WRITE_ERROR;
    176   if(enc_len != fwrite(enc, 1, enc_len, ctx->fp))
    177     goto out;
    178   if(EOF == fputc('\n', ctx->fp))
    179     goto out;
    180   r = CURLE_OK;
    181   ctx->exported++;
    182 out:
    183   if(r)
    184     warnf(ctx->global, "Warning: error saving SSL session for '%s': %d",
    185           session_key, r);
    186   curl_free(enc);
    187   return r;
    188 }
    189 
    190 CURLcode tool_ssls_save(struct OperationConfig *config,
    191                         CURLSH *share, const char *filename)
    192 {
    193   struct tool_ssls_ctx ctx;
    194   CURL *easy = NULL;
    195   CURLcode r = CURLE_OK;
    196 
    197   ctx.global = config->global;
    198   ctx.exported = 0;
    199   ctx.fp = fopen(filename, FOPEN_WRITETEXT);
    200   if(!ctx.fp) {
    201     warnf(config->global, "Warning: Failed to create SSL session file %s",
    202           filename);
    203     goto out;
    204   }
    205 
    206   r = tool_ssls_easy(config, share, &easy);
    207   if(r)
    208     goto out;
    209 
    210   r = curl_easy_ssls_export(easy, tool_ssls_exp, &ctx);
    211 
    212 out:
    213   if(easy)
    214     curl_easy_cleanup(easy);
    215   if(ctx.fp)
    216     fclose(ctx.fp);
    217   return r;
    218 }