Unified · Split
| @@ -608,6 +608,10 @@ typedef struct TLSContext { · 607 unmodified lines | |||
| 608 | int dec_buf_size; | 608 | int dec_buf_size; |
| 609 | int dec_buf_offset; | 609 | int dec_buf_offset; |
| 610 | 610 | ||
| 611 | char *send_buf; | ||
| 612 | int send_buf_size; | ||
| 613 | int send_buf_offset; | ||
| 614 | |||
| 611 | SecPkgContext_StreamSizes sizes; | 615 | SecPkgContext_StreamSizes sizes; |
| 612 | 616 | ||
| 613 | int connected; | 617 | int connected; |
| @@ -692,6 +696,35 @@ static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, · 78 unmodified lines | |||
| 692 | desc->cBuffers = buffer_count; | 696 | desc->cBuffers = buffer_count; |
| 693 | } | 697 | } |
| 694 | 698 | ||
| 699 | static int tls_process_send_buffer(URLContext *h) | ||
| 700 | { | ||
| 701 | TLSContext *c = h->priv_data; | ||
| 702 | TLSShared *s = &c->tls_shared; | ||
| 703 | URLContext *uc = s->is_dtls ? s->udp : s->tcp; | ||
| 704 | int ret; | ||
| 705 | |||
| 706 | if (!c->send_buf) | ||
| 707 | return 0; | ||
| 708 | |||
| 709 | ret = ffurl_write(uc, c->send_buf + c->send_buf_offset, c->send_buf_size - c->send_buf_offset); | ||
| 710 | if (ret == AVERROR(EAGAIN)) { | ||
| 711 | return AVERROR(EAGAIN); | ||
| 712 | } else if (ret < 0) { | ||
| 713 | av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n"); | ||
| 714 | return AVERROR(EIO); | ||
| 715 | } | ||
| 716 | |||
| 717 | c->send_buf_offset += ret; | ||
| 718 | |||
| 719 | if (c->send_buf_offset < c->send_buf_size) | ||
| 720 | return AVERROR(EAGAIN); | ||
| 721 | |||
| 722 | av_freep(&c->send_buf); | ||
| 723 | c->send_buf_size = c->send_buf_offset = 0; | ||
| 724 | |||
| 725 | return 0; | ||
| 726 | } | ||
| 727 | |||
| 695 | static int tls_shutdown_client(URLContext *h) | 728 | static int tls_shutdown_client(URLContext *h) |
| 696 | { | 729 | { |
| 697 | TLSContext *c = h->priv_data; | 730 | TLSContext *c = h->priv_data; |
| @@ -710,6 +743,11 @@ static int tls_shutdown_client(URLContext *h) · 12 unmodified lines | |||
| 710 | init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); | 743 | init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); |
| 711 | init_sec_buffer_desc(&BuffDesc, &Buffer, 1); | 744 | init_sec_buffer_desc(&BuffDesc, &Buffer, 1); |
| 712 | 745 | ||
| 746 | uc->flags &= ~AVIO_FLAG_NONBLOCK; | ||
| 747 | ret = tls_process_send_buffer(h); | ||
| 748 | if (ret < 0) | ||
| 749 | return ret; | ||
| 750 | |||
| 713 | sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc); | 751 | sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc); |
| 714 | if (sspi_ret != SEC_E_OK) | 752 | if (sspi_ret != SEC_E_OK) |
| 715 | av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n"); | 753 | av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n"); |
| @@ -729,7 +767,6 @@ static int tls_shutdown_client(URLContext *h) · 13 unmodified lines | |||
| 729 | 767 | ||
| 730 | if (outbuf.pvBuffer) { | 768 | if (outbuf.pvBuffer) { |
| 731 | if (outbuf.cbBuffer > 0) { | 769 | if (outbuf.cbBuffer > 0) { |
| 732 | uc->flags &= ~AVIO_FLAG_NONBLOCK; | ||
| 733 | ret = ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer); | 770 | ret = ffurl_write(uc, outbuf.pvBuffer, outbuf.cbBuffer); |
| 734 | if (ret < 0 || ret != outbuf.cbBuffer) | 771 | if (ret < 0 || ret != outbuf.cbBuffer) |
| 735 | av_log(h, AV_LOG_ERROR, "Failed to send close message\n"); | 772 | av_log(h, AV_LOG_ERROR, "Failed to send close message\n"); |
| @@ -761,6 +798,9 @@ static int tls_close(URLContext *h) · 25 unmodified lines | |||
| 761 | av_freep(&c->dec_buf); | 798 | av_freep(&c->dec_buf); |
| 762 | c->dec_buf_size = c->dec_buf_offset = 0; | 799 | c->dec_buf_size = c->dec_buf_offset = 0; |
| 763 | 800 | ||
| 801 | av_freep(&c->send_buf); | ||
| 802 | c->send_buf_size = c->send_buf_offset = 0; | ||
| 803 | |||
| 764 | if (s->is_dtls) { | 804 | if (s->is_dtls) { |
| 765 | if (!s->external_sock) | 805 | if (!s->external_sock) |
| 766 | ffurl_closep(&c->tls_shared.udp); | 806 | ffurl_closep(&c->tls_shared.udp); |
| @@ -1264,6 +1304,11 @@ static int tls_read(URLContext *h, uint8_t *buf, int len) · 497 unmodified lines | |||
| 1264 | goto cleanup; | 1304 | goto cleanup; |
| 1265 | } | 1305 | } |
| 1266 | sspi_ret = SEC_E_OK; | 1306 | sspi_ret = SEC_E_OK; |
| 1307 | |||
| 1308 | /* if somehow any send data was left, it is now invalid */ | ||
| 1309 | av_freep(&c->send_buf); | ||
| 1310 | c->send_buf_size = c->send_buf_offset = 0; | ||
| 1311 | |||
| 1267 | continue; | 1312 | continue; |
| 1268 | } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) { | 1313 | } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) { |
| 1269 | c->sspi_close_notify = 1; | 1314 | c->sspi_close_notify = 1; |
| @@ -1308,10 +1353,16 @@ static int tls_write(URLContext *h, const uint8_t *buf, int len) · 38 unmodified lines | |||
| 1308 | TLSShared *s = &c->tls_shared; | 1353 | TLSShared *s = &c->tls_shared; |
| 1309 | URLContext *uc = s->is_dtls ? s->udp : s->tcp; | 1354 | URLContext *uc = s->is_dtls ? s->udp : s->tcp; |
| 1310 | SECURITY_STATUS sspi_ret; | 1355 | SECURITY_STATUS sspi_ret; |
| 1311 | int ret = 0, data_size; | ||
| 1312 | uint8_t *data = NULL; | ||
| 1313 | SecBuffer outbuf[4]; | 1356 | SecBuffer outbuf[4]; |
| 1314 | SecBufferDesc outbuf_desc; | 1357 | SecBufferDesc outbuf_desc; |
| 1358 | int ret = 0; | ||
| 1359 | |||
| 1360 | uc->flags &= ~AVIO_FLAG_NONBLOCK; | ||
| 1361 | uc->flags |= h->flags & AVIO_FLAG_NONBLOCK; | ||
| 1362 | |||
| 1363 | ret = tls_process_send_buffer(h); | ||
| 1364 | if (ret < 0) | ||
| 1365 | return ret; | ||
| 1315 | 1366 | ||
| 1316 | if (c->sizes.cbMaximumMessage == 0) { | 1367 | if (c->sizes.cbMaximumMessage == 0) { |
| 1317 | sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes); | 1368 | sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes); |
| @@ -1322,50 +1373,46 @@ static int tls_write(URLContext *h, const uint8_t *buf, int len) · 4 unmodified lines | |||
| 1322 | /* limit how much data we can consume */ | 1373 | /* limit how much data we can consume */ |
| 1323 | len = FFMIN(len, c->sizes.cbMaximumMessage - c->sizes.cbHeader - c->sizes.cbTrailer); | 1374 | len = FFMIN(len, c->sizes.cbMaximumMessage - c->sizes.cbHeader - c->sizes.cbTrailer); |
| 1324 | 1375 | ||
| 1325 | data_size = c->sizes.cbHeader + len + c->sizes.cbTrailer; | 1376 | c->send_buf_size = c->sizes.cbHeader + len + c->sizes.cbTrailer; |
| 1326 | data = av_malloc(data_size); | 1377 | c->send_buf = av_malloc(c->send_buf_size); |
| 1327 | if (data == NULL) | 1378 | if (c->send_buf == NULL) |
| 1328 | return AVERROR(ENOMEM); | 1379 | return AVERROR(ENOMEM); |
| 1329 | 1380 | ||
| 1330 | init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER, | 1381 | init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER, |
| 1331 | data, c->sizes.cbHeader); | 1382 | c->send_buf, c->sizes.cbHeader); |
| 1332 | init_sec_buffer(&outbuf[1], SECBUFFER_DATA, | 1383 | init_sec_buffer(&outbuf[1], SECBUFFER_DATA, |
| 1333 | data + c->sizes.cbHeader, len); | 1384 | c->send_buf + c->sizes.cbHeader, len); |
| 1334 | init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, | 1385 | init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER, |
| 1335 | data + c->sizes.cbHeader + len, | 1386 | c->send_buf + c->sizes.cbHeader + len, |
| 1336 | c->sizes.cbTrailer); | 1387 | c->sizes.cbTrailer); |
| 1337 | init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); | 1388 | init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0); |
| 1338 | init_sec_buffer_desc(&outbuf_desc, outbuf, 4); | 1389 | init_sec_buffer_desc(&outbuf_desc, outbuf, 4); |
| 1339 | 1390 | ||
| 1340 | memcpy(outbuf[1].pvBuffer, buf, len); | 1391 | memcpy(outbuf[1].pvBuffer, buf, len); |
| 1341 | 1392 | ||
| 1342 | sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0); | 1393 | sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0); |
| 1343 | if (sspi_ret == SEC_E_OK) { | 1394 | if (sspi_ret != SEC_E_OK) { |
| 1344 | len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; | 1395 | av_freep(&c->send_buf); |
| 1345 | |||
| 1346 | uc->flags &= ~AVIO_FLAG_NONBLOCK; | ||
| 1347 | uc->flags |= h->flags & AVIO_FLAG_NONBLOCK; | ||
| 1348 | |||
| 1349 | ret = ffurl_write(uc, data, len); | ||
| 1350 | if (ret == AVERROR(EAGAIN)) { | ||
| 1351 | goto done; | ||
| 1352 | } else if (ret < 0 || ret != len) { | ||
| 1353 | ret = AVERROR(EIO); | ||
| 1354 | av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n"); | ||
| 1355 | goto done; | ||
| 1356 | } | ||
| 1357 | } else { | ||
| 1358 | av_log(h, AV_LOG_ERROR, "Encrypting data failed\n"); | 1396 | av_log(h, AV_LOG_ERROR, "Encrypting data failed\n"); |
| 1359 | if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY) | 1397 | if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY) |
| 1360 | ret = AVERROR(ENOMEM); | 1398 | return AVERROR(ENOMEM); |
| 1361 | else | 1399 | return AVERROR(EIO); |
| 1362 | ret = AVERROR(EIO); | 1400 | } |
| 1363 | goto done; | 1401 | |
| 1402 | c->send_buf_size = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer; | ||
| 1403 | c->send_buf_offset = 0; | ||
| 1404 | |||
| 1405 | ret = tls_process_send_buffer(h); | ||
| 1406 | if (ret == AVERROR(EAGAIN)) { | ||
| 1407 | /* We always need to signal that we consumed all (encryped) data since schannel must not | ||
| 1408 | be fed the same data again. Sending will then be completed next call to this function, | ||
| 1409 | and EAGAIN returned until all remaining buffer is sent. */ | ||
| 1410 | return outbuf[1].cbBuffer; | ||
| 1411 | } else if (ret < 0) { | ||
| 1412 | return ret; | ||
| 1364 | } | 1413 | } |
| 1365 | 1414 | ||
| 1366 | done: | 1415 | return outbuf[1].cbBuffer; |
| 1367 | av_freep(&data); | ||
| 1368 | return ret < 0 ? ret : outbuf[1].cbBuffer; | ||
| 1369 | } | 1416 | } |
| 1370 | 1417 | ||
| 1371 | static int tls_get_file_handle(URLContext *h) | 1418 | static int tls_get_file_handle(URLContext *h) |