iodine 0.7.38 → 0.7.43

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,6 +33,11 @@ Feel free to copy, use and enjoy according to the license provided.
33
33
  FIO_LOG_FATAL("No supported SSL/TLS library available."); \
34
34
  exit(-1);
35
35
  #endif
36
+
37
+ #ifndef FIO_TLS_TIMEOUT
38
+ #define FIO_TLS_TIMEOUT 4
39
+ #endif
40
+
36
41
  /* STOP deleting after this line */
37
42
 
38
43
  /* *****************************************************************************
@@ -590,6 +595,7 @@ file_missing:
590
595
  */
591
596
  void FIO_TLS_WEAK fio_tls_accept(intptr_t uuid, fio_tls_s *tls, void *udata) {
592
597
  REQUIRE_LIBRARY();
598
+ fio_timeout_set(uuid, FIO_TLS_TIMEOUT);
593
599
  fio_tls_attach2uuid(uuid, tls, udata, 1);
594
600
  }
595
601
 
@@ -29,6 +29,10 @@ The SSL/TLS helper data types (can be left as is)
29
29
  #define FIO_FORCE_MALLOC_TMP 1
30
30
  #include <fio.h>
31
31
 
32
+ #ifndef FIO_TLS_TIMEOUT
33
+ #define FIO_TLS_TIMEOUT 4
34
+ #endif
35
+
32
36
  typedef struct {
33
37
  fio_str_s private_key;
34
38
  fio_str_s public_key;
@@ -190,8 +194,12 @@ typedef struct {
190
194
 
191
195
  FIO_FUNC inline void alpn_select___task(void *t_, void *ignr_) {
192
196
  alpn_task_s *t = t_;
193
- t->alpn.on_selected((fio_is_valid(t->uuid) ? t->uuid : -1),
194
- t->udata_connection, t->alpn.udata_tls);
197
+ if (fio_is_valid(t->uuid)) {
198
+ fio_timeout_set(t->uuid, 0); // remove TLS timeout
199
+ t->alpn.on_selected(t->uuid, t->udata_connection, t->alpn.udata_tls);
200
+ } else {
201
+ t->alpn.on_selected(-1, t->udata_connection, t->alpn.udata_tls);
202
+ }
195
203
  fio_free(t);
196
204
  (void)ignr_;
197
205
  }
@@ -537,19 +545,21 @@ static ssize_t fio_tls_read(intptr_t uuid, void *udata, void *buf,
537
545
  case SSL_ERROR_SSL: /* overflow */
538
546
  case SSL_ERROR_ZERO_RETURN:
539
547
  return 0; /* EOF */
548
+ case SSL_ERROR_SYSCALL: /* allow errno to inform us */
549
+ break; /* return -1 */
540
550
  case SSL_ERROR_NONE: /* overflow */
541
551
  case SSL_ERROR_WANT_CONNECT: /* overflow */
542
552
  case SSL_ERROR_WANT_ACCEPT: /* overflow */
543
553
  case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
554
+ case SSL_ERROR_WANT_WRITE: /* overflow */
555
+ case SSL_ERROR_WANT_READ: /* overflow */
544
556
  #ifdef SSL_ERROR_WANT_ASYNC
545
557
  case SSL_ERROR_WANT_ASYNC: /* overflow */
546
558
  #endif
547
- case SSL_ERROR_WANT_WRITE: /* overflow */
548
- case SSL_ERROR_WANT_READ:
549
559
  default:
560
+ errno = EWOULDBLOCK;
550
561
  break;
551
562
  }
552
- errno = EWOULDBLOCK;
553
563
  return -1;
554
564
  (void)uuid;
555
565
  }
@@ -591,19 +601,21 @@ static ssize_t fio_tls_write(intptr_t uuid, void *udata, const void *buf,
591
601
  case SSL_ERROR_SSL: /* overflow */
592
602
  case SSL_ERROR_ZERO_RETURN:
593
603
  return 0; /* EOF */
604
+ case SSL_ERROR_SYSCALL: /* allow errno to inform us */
605
+ break; /* return -1 */
594
606
  case SSL_ERROR_NONE: /* overflow */
595
607
  case SSL_ERROR_WANT_CONNECT: /* overflow */
596
608
  case SSL_ERROR_WANT_ACCEPT: /* overflow */
597
609
  case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
610
+ case SSL_ERROR_WANT_WRITE: /* overflow */
611
+ case SSL_ERROR_WANT_READ: /* overflow */
598
612
  #ifdef SSL_ERROR_WANT_ASYNC
599
613
  case SSL_ERROR_WANT_ASYNC: /* overflow */
600
614
  #endif
601
- case SSL_ERROR_WANT_WRITE: /* overflow */
602
- case SSL_ERROR_WANT_READ:
603
615
  default:
616
+ errno = EWOULDBLOCK;
604
617
  break;
605
618
  }
606
- errno = EWOULDBLOCK;
607
619
  return -1;
608
620
  (void)uuid;
609
621
  }
@@ -640,13 +652,20 @@ static void fio_tls_cleanup(void *udata) {
640
652
  static fio_rw_hook_s FIO_TLS_HOOKS = {
641
653
  .read = fio_tls_read,
642
654
  .write = fio_tls_write,
643
- .before_close = fio_tls_before_close,
644
655
  .flush = fio_tls_flush,
656
+ .before_close = fio_tls_before_close,
645
657
  .cleanup = fio_tls_cleanup,
646
658
  };
647
659
 
660
+ #define FIO_TLS_HANDSHAKE_ERROR 0
661
+ #define FIO_TLS_HANDSHAKE_OK 1
662
+ #define FIO_TLS_HANDSHAKE_NEED_READ 2
663
+ #define FIO_TLS_HANDSHAKE_NEED_WRITE 4
664
+
648
665
  static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
666
+ size_t status = FIO_TLS_HANDSHAKE_ERROR;
649
667
  fio_tls_connection_s *c = udata;
668
+
650
669
  int ri;
651
670
  if (c->is_server) {
652
671
  ri = SSL_accept(c->ssl);
@@ -659,26 +678,29 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
659
678
  case SSL_ERROR_NONE:
660
679
  // FIO_LOG_DEBUG("SSL_accept/SSL_connect %p state: SSL_ERROR_NONE",
661
680
  // (void *)uuid);
662
- return 0;
681
+ status = FIO_TLS_HANDSHAKE_NEED_READ | FIO_TLS_HANDSHAKE_NEED_WRITE;
682
+ return status;
663
683
  case SSL_ERROR_WANT_WRITE:
664
684
  // FIO_LOG_DEBUG("SSL_accept/SSL_connect %p state: SSL_ERROR_WANT_WRITE",
665
685
  // (void *)uuid);
666
- // fio_force_event(uuid, FIO_EVENT_ON_READY);
667
- return 0;
686
+ status = FIO_TLS_HANDSHAKE_NEED_WRITE;
687
+ return status;
668
688
  case SSL_ERROR_WANT_READ:
669
689
  // FIO_LOG_DEBUG("SSL_accept/SSL_connect %p state: SSL_ERROR_WANT_READ",
670
690
  // (void *)uuid);
671
- // fio_force_event(uuid, FIO_EVENT_ON_DATA);
672
- return 0;
691
+ status = FIO_TLS_HANDSHAKE_NEED_READ;
692
+ return status;
673
693
  case SSL_ERROR_SYSCALL:
674
- FIO_LOG_DEBUG(
675
- "SSL_accept/SSL_connect %p error: SSL_ERROR_SYSCALL, errno: %s",
676
- (void *)uuid, strerror(errno));
677
- // fio_force_event(uuid, FIO_EVENT_ON_DATA);
678
- return 0;
694
+ if (errno) {
695
+ FIO_LOG_DEBUG(
696
+ "SSL_accept/SSL_connect %p error: SSL_ERROR_SYSCALL, errno: %s",
697
+ (void *)uuid, strerror(errno));
698
+ }
699
+ break;
679
700
  case SSL_ERROR_SSL:
680
- FIO_LOG_DEBUG("SSL_accept/SSL_connect %p error: SSL_ERROR_SSL",
681
- (void *)uuid);
701
+ FIO_LOG_DEBUG(
702
+ "SSL_accept/SSL_connect %p error: SSL_ERROR_SSL (non SSL attempt?)",
703
+ (void *)uuid);
682
704
  break;
683
705
  case SSL_ERROR_ZERO_RETURN:
684
706
  FIO_LOG_DEBUG("SSL_accept/SSL_connect %p error: SSL_ERROR_ZERO_RETURN",
@@ -715,8 +737,9 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
715
737
  (void *)uuid, ri);
716
738
  break;
717
739
  }
740
+ fio_rw_hook_replace_unsafe(uuid, &FIO_TLS_HOOKS, udata);
718
741
  fio_defer(fio_tls_delayed_close, (void *)uuid, NULL);
719
- return 0;
742
+ return status;
720
743
  }
721
744
  if (!c->alpn_ok) {
722
745
  c->alpn_ok = 1;
@@ -745,7 +768,7 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
745
768
  } else {
746
769
  FIO_LOG_DEBUG("Something went wrong during TLS handshake for %p",
747
770
  (void *)uuid);
748
- return 0;
771
+ return status;
749
772
  }
750
773
  /* make sure the connection is re-added to the reactor */
751
774
  fio_force_event(uuid, FIO_EVENT_ON_DATA);
@@ -768,14 +791,18 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
768
791
  buff2);
769
792
  }
770
793
  #endif
771
- return 1;
794
+ status = FIO_TLS_HANDSHAKE_OK;
795
+ return status;
772
796
  }
773
797
 
774
798
  static ssize_t fio_tls_read4handshake(intptr_t uuid, void *udata, void *buf,
775
799
  size_t count) {
776
800
  // FIO_LOG_DEBUG("TLS handshake from read %p", (void *)uuid);
777
- if (fio_tls_handshake(uuid, udata))
801
+ size_t s = fio_tls_handshake(uuid, udata);
802
+ if (s == FIO_TLS_HANDSHAKE_OK)
778
803
  return fio_tls_read(uuid, udata, buf, count);
804
+ if (!s)
805
+ return 0;
779
806
  errno = EWOULDBLOCK;
780
807
  return -1;
781
808
  }
@@ -783,20 +810,27 @@ static ssize_t fio_tls_read4handshake(intptr_t uuid, void *udata, void *buf,
783
810
  static ssize_t fio_tls_write4handshake(intptr_t uuid, void *udata,
784
811
  const void *buf, size_t count) {
785
812
  // FIO_LOG_DEBUG("TLS handshake from write %p", (void *)uuid);
786
- if (fio_tls_handshake(uuid, udata))
813
+ size_t s = fio_tls_handshake(uuid, udata);
814
+ if (s == FIO_TLS_HANDSHAKE_OK)
787
815
  return fio_tls_write(uuid, udata, buf, count);
816
+ if (!s)
817
+ return 0;
788
818
  errno = EWOULDBLOCK;
789
819
  return -1;
790
820
  }
791
821
 
792
822
  static ssize_t fio_tls_flush4handshake(intptr_t uuid, void *udata) {
793
823
  // FIO_LOG_DEBUG("TLS handshake from flush %p", (void *)uuid);
794
- if (fio_tls_handshake(uuid, udata)) {
824
+ size_t s = fio_tls_handshake(uuid, udata);
825
+ if (s == FIO_TLS_HANDSHAKE_OK) {
795
826
  return fio_tls_flush(uuid, udata);
796
827
  }
828
+ if (!s)
829
+ return 0;
797
830
  errno = 0;
798
- return 1;
831
+ return s | FIO_TLS_HANDSHAKE_NEED_WRITE;
799
832
  }
833
+
800
834
  static fio_rw_hook_s FIO_TLS_HANDSHAKE_HOOKS = {
801
835
  .read = fio_tls_read4handshake,
802
836
  .write = fio_tls_write4handshake,
@@ -967,6 +1001,7 @@ file_missing:
967
1001
  */
968
1002
  void FIO_TLS_WEAK fio_tls_accept(intptr_t uuid, fio_tls_s *tls, void *udata) {
969
1003
  REQUIRE_LIBRARY();
1004
+ fio_timeout_set(uuid, FIO_TLS_TIMEOUT);
970
1005
  fio_tls_attach2uuid(uuid, tls, udata, 1);
971
1006
  }
972
1007
 
@@ -1007,6 +1042,7 @@ void FIO_TLS_WEAK fio_tls_destroy(fio_tls_s *tls) {
1007
1042
  cert_ary_free(&tls->sni);
1008
1043
  trust_ary_free(&tls->trust);
1009
1044
  free(tls);
1045
+ FIO_LOG_DEBUG("freed TLS context %p", (void *)tls);
1010
1046
  }
1011
1047
 
1012
1048
  #endif /* Library compiler flags */
@@ -874,19 +874,23 @@ static uint8_t fio_http_at_capa = 0;
874
874
 
875
875
  static void http_on_server_protocol_http1(intptr_t uuid, void *set,
876
876
  void *ignr_) {
877
- fio_timeout_set(uuid, ((http_settings_s *)set)->timeout);
878
- if (fio_uuid2fd(uuid) >= ((http_settings_s *)set)->max_clients) {
879
- if (!fio_http_at_capa)
880
- FIO_LOG_WARNING("HTTP server at capacity");
881
- fio_http_at_capa = 1;
882
- http_send_error2(uuid, 503, set);
883
- fio_close(uuid);
877
+ if ((unsigned int)fio_uuid2fd(uuid) >=
878
+ ((http_settings_s *)set)->max_clients) {
879
+ if (fio_uuid2fd(uuid) != -1) {
880
+ if (!fio_http_at_capa)
881
+ FIO_LOG_WARNING("HTTP server at capacity");
882
+ fio_http_at_capa = 1;
883
+ http_send_error2(uuid, 503, set);
884
+ fio_close(uuid);
885
+ }
884
886
  return;
885
887
  }
886
888
  fio_http_at_capa = 0;
887
889
  fio_protocol_s *pr = http1_new(uuid, set, NULL, 0);
888
890
  if (!pr)
889
891
  fio_close(uuid);
892
+ else
893
+ fio_timeout_set(uuid, ((http_settings_s *)set)->timeout);
890
894
  (void)ignr_;
891
895
  }
892
896
 
@@ -2089,111 +2093,94 @@ See the libc `gmtime_r` documentation for details.
2089
2093
 
2090
2094
  Falls back to `gmtime_r` for dates before epoch.
2091
2095
  */
2092
- struct tm *http_gmtime(time_t timer, struct tm *tmbuf) {
2093
- // static char* DAYS[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
2094
- // "Sat"}; static char * Months = { "Jan", "Feb", "Mar", "Apr", "May",
2095
- // "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2096
- static const uint8_t month_len[] = {
2097
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, // nonleap year
2098
- 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // leap year
2099
- };
2100
- if (timer < 0)
2101
- return gmtime_r(&timer, tmbuf);
2096
+ struct tm *http_gmtime(time_t timer, struct tm *tm) {
2102
2097
  ssize_t a, b;
2103
- #if HAVE_TM_TM_ZONE
2104
- *tmbuf = (struct tm){
2098
+ #if HAVE_TM_TM_ZONE || defined(BSD)
2099
+ *tm = (struct tm){
2105
2100
  .tm_isdst = 0,
2106
- .tm_year = 70, // tm_year == The number of years since 1900
2107
- .tm_mon = 0,
2108
- .tm_zone = "UTC",
2101
+ .tm_zone = (char *)"UTC",
2109
2102
  };
2110
2103
  #else
2111
- *tmbuf = (struct tm){
2104
+ *tm = (struct tm){
2112
2105
  .tm_isdst = 0,
2113
- .tm_year = 70, // tm_year == The number of years since 1900
2114
- .tm_mon = 0,
2115
2106
  };
2116
2107
  #endif
2117
- // for seconds up to weekdays, we build up, as small values clean up
2118
- // larger values.
2119
- a = (ssize_t)timer;
2120
- b = a / 60;
2121
- tmbuf->tm_sec = a - (b * 60);
2122
- a = b / 60;
2123
- tmbuf->tm_min = b - (a * 60);
2124
- b = a / 24;
2125
- tmbuf->tm_hour = a - (b * 24);
2126
- // day of epoch was a thursday. Add + 4 so sunday == 0...
2127
- tmbuf->tm_wday = (b + 4) % 7;
2128
- // tmp == number of days since epoch
2129
- #define DAYS_PER_400_YEARS ((400 * 365) + 97)
2130
- while (b >= DAYS_PER_400_YEARS) {
2131
- tmbuf->tm_year += 400;
2132
- b -= DAYS_PER_400_YEARS;
2133
- }
2134
- #undef DAYS_PER_400_YEARS
2135
- #define DAYS_PER_100_YEARS ((100 * 365) + 24)
2136
- while (b >= DAYS_PER_100_YEARS) {
2137
- tmbuf->tm_year += 100;
2138
- b -= DAYS_PER_100_YEARS;
2139
- if (((tmbuf->tm_year / 100) & 3) ==
2140
- 0) // leap century divisable by 400 => add leap
2108
+
2109
+ // convert seconds from epoch to days from epoch + extract data
2110
+ if (timer >= 0) {
2111
+ // for seconds up to weekdays, we reduce the reminder every step.
2112
+ a = (ssize_t)timer;
2113
+ b = a / 60; // b == time in minutes
2114
+ tm->tm_sec = a - (b * 60);
2115
+ a = b / 60; // b == time in hours
2116
+ tm->tm_min = b - (a * 60);
2117
+ b = a / 24; // b == time in days since epoch
2118
+ tm->tm_hour = a - (b * 24);
2119
+ // b == number of days since epoch
2120
+ // day of epoch was a thursday. Add + 4 so sunday == 0...
2121
+ tm->tm_wday = (b + 4) % 7;
2122
+ } else {
2123
+ // for seconds up to weekdays, we reduce the reminder every step.
2124
+ a = (ssize_t)timer;
2125
+ b = a / 60; // b == time in minutes
2126
+ if (b * 60 != a) {
2127
+ /* seconds passed */
2128
+ tm->tm_sec = (a - (b * 60)) + 60;
2141
2129
  --b;
2142
- }
2143
- #undef DAYS_PER_100_YEARS
2144
- #define DAYS_PER_32_YEARS ((32 * 365) + 8)
2145
- while (b >= DAYS_PER_32_YEARS) {
2146
- tmbuf->tm_year += 32;
2147
- b -= DAYS_PER_32_YEARS;
2148
- }
2149
- #undef DAYS_PER_32_YEARS
2150
- #define DAYS_PER_8_YEARS ((8 * 365) + 2)
2151
- while (b >= DAYS_PER_8_YEARS) {
2152
- tmbuf->tm_year += 8;
2153
- b -= DAYS_PER_8_YEARS;
2154
- }
2155
- #undef DAYS_PER_8_YEARS
2156
- #define DAYS_PER_4_YEARS ((4 * 365) + 1)
2157
- while (b >= DAYS_PER_4_YEARS) {
2158
- tmbuf->tm_year += 4;
2159
- b -= DAYS_PER_4_YEARS;
2160
- }
2161
- #undef DAYS_PER_4_YEARS
2162
- while (b >= 365) {
2163
- tmbuf->tm_year += 1;
2164
- b -= 365;
2165
- if ((tmbuf->tm_year & 3) == 0) { // leap year
2166
- if (b > 0) {
2167
- --b;
2168
- continue;
2169
- } else {
2170
- b += 365;
2171
- --tmbuf->tm_year;
2172
- break;
2173
- }
2130
+ } else {
2131
+ /* no seconds */
2132
+ tm->tm_sec = 0;
2174
2133
  }
2175
- }
2176
- b++; /* day 1 of the year is 1, not 0. */
2177
- tmbuf->tm_yday = b;
2178
- if ((tmbuf->tm_year & 3) == 1) {
2179
- // regular year
2180
- for (size_t i = 0; i < 12; i++) {
2181
- if (b <= month_len[i])
2182
- break;
2183
- b -= month_len[i];
2184
- ++tmbuf->tm_mon;
2134
+ a = b / 60; // b == time in hours
2135
+ if (a * 60 != b) {
2136
+ /* minutes passed */
2137
+ tm->tm_min = (b - (a * 60)) + 60;
2138
+ --a;
2139
+ } else {
2140
+ /* no minutes */
2141
+ tm->tm_min = 0;
2185
2142
  }
2186
- } else {
2187
- // leap year
2188
- for (size_t i = 12; i < 24; i++) {
2189
- if (b <= month_len[i])
2190
- break;
2191
- b -= month_len[i];
2192
- ++tmbuf->tm_mon;
2143
+ b = a / 24; // b == time in days since epoch?
2144
+ if (b * 24 != a) {
2145
+ /* hours passed */
2146
+ tm->tm_hour = (a - (b * 24)) + 24;
2147
+ --b;
2148
+ } else {
2149
+ /* no hours */
2150
+ tm->tm_hour = 0;
2193
2151
  }
2152
+ // day of epoch was a thursday. Add + 4 so sunday == 0...
2153
+ tm->tm_wday = ((b - 3) % 7);
2154
+ if (tm->tm_wday)
2155
+ tm->tm_wday += 7;
2156
+ /* b == days from epoch */
2194
2157
  }
2195
- tmbuf->tm_mday = b;
2196
- return tmbuf;
2158
+
2159
+ // at this point we can apply the algorithm described here:
2160
+ // http://howardhinnant.github.io/date_algorithms.html#civil_from_days
2161
+ // Credit to Howard Hinnant.
2162
+ {
2163
+ b += 719468L; // adjust to March 1st, 2000 (post leap of 400 year era)
2164
+ // 146,097 = days in era (400 years)
2165
+ const size_t era = (b >= 0 ? b : b - 146096) / 146097;
2166
+ const uint32_t doe = (b - (era * 146097)); // day of era
2167
+ const uint16_t yoe =
2168
+ (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // year of era
2169
+ a = yoe;
2170
+ a += era * 400; // a == year number, assuming year starts on March 1st...
2171
+ const uint16_t doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
2172
+ const uint16_t mp = (5U * doy + 2) / 153;
2173
+ const uint16_t d = doy - (153U * mp + 2) / 5 + 1;
2174
+ const uint8_t m = mp + (mp < 10 ? 2 : -10);
2175
+ a += (m <= 1);
2176
+ tm->tm_year = a - 1900; // tm_year == years since 1900
2177
+ tm->tm_mon = m;
2178
+ tm->tm_mday = d;
2179
+ const uint8_t is_leap = (a % 4 == 0 && (a % 100 != 0 || a % 400 == 0));
2180
+ tm->tm_yday = (doy + (is_leap) + 28 + 31) % (365 + is_leap);
2181
+ }
2182
+
2183
+ return tm;
2197
2184
  }
2198
2185
 
2199
2186
  static const char *DAY_NAMES[] = {"Sun", "Mon", "Tue", "Wed",