httpsrr.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, 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 "curl_setup.h"
  25. #ifdef USE_HTTPSRR
  26. #include "urldata.h"
  27. #include "curl_addrinfo.h"
  28. #include "httpsrr.h"
  29. #include "connect.h"
  30. #include "sendf.h"
  31. /* The last 3 #include files should be in this order */
  32. #include "curl_printf.h"
  33. #include "curl_memory.h"
  34. #include "memdebug.h"
  35. CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
  36. unsigned char *alpns)
  37. {
  38. /*
  39. * spec here is as per RFC 9460, section-7.1.1
  40. * encoding is a concatenated list of strings each preceded by a one
  41. * octet length
  42. * output is comma-sep list of the strings
  43. * implementations may or may not handle quoting of comma within
  44. * string values, so we might see a comma within the wire format
  45. * version of a string, in which case we will precede that by a
  46. * backslash - same goes for a backslash character, and of course
  47. * we need to use two backslashes in strings when we mean one;-)
  48. */
  49. struct dynbuf dval;
  50. int idnum = 0;
  51. Curl_dyn_init(&dval, DYN_DOH_RESPONSE);
  52. while(len > 0) {
  53. size_t tlen = (size_t) *cp++;
  54. size_t i;
  55. enum alpnid id;
  56. len--;
  57. if(tlen > len)
  58. goto err;
  59. /* add escape char if needed, clunky but easier to read */
  60. for(i = 0; i != tlen; i++) {
  61. if('\\' == *cp || ',' == *cp) {
  62. if(Curl_dyn_addn(&dval, "\\", 1))
  63. goto err;
  64. }
  65. if(Curl_dyn_addn(&dval, cp++, 1))
  66. goto err;
  67. }
  68. len -= tlen;
  69. /* we only store ALPN ids we know about */
  70. id = Curl_alpn2alpnid(Curl_dyn_ptr(&dval), Curl_dyn_len(&dval));
  71. if(id != ALPN_none) {
  72. if(idnum == MAX_HTTPSRR_ALPNS)
  73. break;
  74. alpns[idnum++] = (unsigned char)id;
  75. }
  76. Curl_dyn_reset(&dval);
  77. }
  78. Curl_dyn_free(&dval);
  79. if(idnum < MAX_HTTPSRR_ALPNS)
  80. alpns[idnum] = ALPN_none; /* terminate the list */
  81. return CURLE_OK;
  82. err:
  83. Curl_dyn_free(&dval);
  84. return CURLE_BAD_CONTENT_ENCODING;
  85. }
  86. #ifdef USE_ARES
  87. static void httpsrr_opt(struct Curl_easy *data,
  88. const ares_dns_rr_t *rr,
  89. ares_dns_rr_key_t key, size_t idx)
  90. {
  91. size_t len = 0;
  92. const unsigned char *val = NULL;
  93. unsigned short code;
  94. struct thread_data *res = data->state.async.tdata;
  95. struct Curl_https_rrinfo *hi = &res->hinfo;
  96. code = ares_dns_rr_get_opt(rr, key, idx, &val, &len);
  97. switch(code) {
  98. case HTTPS_RR_CODE_ALPN: /* str_list */
  99. Curl_httpsrr_decode_alpn(val, len, hi->alpns);
  100. infof(data, "HTTPS RR ALPN: %u %u %u %u",
  101. hi->alpns[0], hi->alpns[1], hi->alpns[2], hi->alpns[3]);
  102. break;
  103. case HTTPS_RR_CODE_NO_DEF_ALPN:
  104. infof(data, "HTTPS RR no-def-alpn");
  105. break;
  106. case HTTPS_RR_CODE_IPV4: /* addr4 list */
  107. infof(data, "HTTPS RR IPv4");
  108. break;
  109. case HTTPS_RR_CODE_ECH:
  110. infof(data, "HTTPS RR ECH");
  111. break;
  112. case HTTPS_RR_CODE_IPV6: /* addr6 list */
  113. infof(data, "HTTPS RR IPv6");
  114. break;
  115. case HTTPS_RR_CODE_PORT:
  116. infof(data, "HTTPS RR port");
  117. break;
  118. default:
  119. infof(data, "HTTPS RR unknown code");
  120. break;
  121. }
  122. }
  123. void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
  124. size_t timeouts,
  125. const ares_dns_record_t *dnsrec)
  126. {
  127. struct Curl_easy *data = arg;
  128. size_t i;
  129. #ifdef CURLRES_ARES
  130. struct thread_data *res = data->state.async.tdata;
  131. res->num_pending--;
  132. #endif
  133. (void)timeouts;
  134. if((ARES_SUCCESS != status) || !dnsrec)
  135. return;
  136. for(i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
  137. size_t opt;
  138. const ares_dns_rr_t *rr =
  139. ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
  140. if(ares_dns_rr_get_type(rr) != ARES_REC_TYPE_HTTPS)
  141. continue;
  142. /* When SvcPriority is 0, the SVCB record is in AliasMode. Otherwise, it
  143. is in ServiceMode */
  144. infof(data, "HTTPS RR priority: %u",
  145. ares_dns_rr_get_u16(rr, ARES_RR_HTTPS_PRIORITY));
  146. for(opt = 0; opt < ares_dns_rr_get_opt_cnt(rr, ARES_RR_HTTPS_PARAMS);
  147. opt++)
  148. httpsrr_opt(data, rr, ARES_RR_HTTPS_PARAMS, opt);
  149. }
  150. }
  151. #endif /* USE_ARES */
  152. #endif /* USE_HTTPSRR */