Skip to content

Commit 1dab9b6

Browse files
authored
Add TLS/SSL backend: Windows Schannel (#3867)
1 parent 30829f0 commit 1dab9b6

File tree

18 files changed

+2071
-90
lines changed

18 files changed

+2071
-90
lines changed

.github/workflows/ci-win.yml

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -178,25 +178,10 @@ jobs:
178178
msbuild pjproject-vs14.sln /p:PlatformToolset=v143 /p:Configuration=Release /p:Platform=win32 /p:UseEnv=true
179179
shell: cmd
180180

181-
windows-with-video-libvpx-unit-test-1:
181+
windows-with-video-libvpx-schannel-unit-test-1:
182182
runs-on: windows-latest
183183
steps:
184184
- uses: actions/checkout@master
185-
- name: get openssl
186-
run: Invoke-WebRequest -Uri "https://github.com/pjsip/third_party_libs/raw/main/openssl-1.1.1s-win.zip" -OutFile ".\openssl.zip"
187-
shell: powershell
188-
- name: expand openssl
189-
run: |
190-
Expand-Archive -LiteralPath .\openssl.zip -DestinationPath .; pwd
191-
cd openssl_build
192-
Add-Content ..\openssl_dir.txt $pwd.Path
193-
shell: powershell
194-
- name: check openssl folder
195-
run: |
196-
set /P OPENSSL_DIR=<openssl_dir.txt
197-
dir "%OPENSSL_DIR%\include"
198-
dir "%OPENSSL_DIR%\lib"
199-
shell: cmd
200185
- name: get vpx
201186
run: Invoke-WebRequest -Uri "https://github.com/pjsip/third_party_libs/raw/main/vpx-1.12-win.zip" -Outfile "vpx.zip"
202187
shell: powershell
@@ -231,6 +216,8 @@ jobs:
231216
run: |
232217
cd pjlib/include/pj; cp config_site_test.h config_site.h
233218
Add-Content config_site.h "#define PJ_HAS_SSL_SOCK 1"
219+
Add-Content config_site.h "#define PJ_SSL_SOCK_IMP PJ_SSL_SOCK_IMP_SCHANNEL"
220+
Add-Content config_site.h "#undef PJMEDIA_SRTP_HAS_DTLS"
234221
Add-Content config_site.h "#define PJMEDIA_HAS_VIDEO 1"
235222
Add-Content config_site.h "#define PJMEDIA_VIDEO_DEV_HAS_DSHOW 1"
236223
Add-Content config_site.h "#define PJMEDIA_HAS_LIBYUV 1"
@@ -258,7 +245,7 @@ jobs:
258245
set /P SDL_DIR=<sdl_dir.txt
259246
cd tests/pjsua/tools
260247
set INCLUDE=%INCLUDE%;%OPENSSL_DIR%\include;%VPX_DIR%\include;%SDL_DIR%\include
261-
set LIB=%LIB%;%OPENSSL_DIR%\lib;%VPX_DIR%\lib;%SDL_DIR%\lib\x86
248+
set LIB=%LIB%;%VPX_DIR%\lib;%SDL_DIR%\lib\x86
262249
call "%PROGRAMFILES%\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat"
263250
msbuild cmp_wav.vcxproj /p:PlatformToolset=v143 /p:Configuration=Release /p:Platform=win32 /p:UseEnv=true
264251
shell: cmd
@@ -268,9 +255,8 @@ jobs:
268255
python-version: '3.10'
269256
- name: unit tests
270257
run: |
271-
$env:OPENSSL_DIR = Get-Content .\openssl_dir.txt
272258
$env:SDL_DIR = Get-Content .\sdl_dir.txt
273-
$env:PATH+=";$env:OPENSSL_DIR\bin;$env:SDL_DIR\lib\x86;"
259+
$env:PATH+=";$env:SDL_DIR\lib\x86;"
274260
cd tests/pjsua; python runall.py
275261
cd ../../pjlib/bin; ./pjlib-test-i386-Win32-vc14-Release.exe --ci-mode
276262
cd ../../pjlib-util/bin; ./pjlib-util-test-i386-Win32-vc14-Release.exe

pjlib/build/pjlib.vcxproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<ItemGroup Label="ProjectConfigurations">
44
<ProjectConfiguration Include="Debug-Dynamic|ARM">
@@ -998,6 +998,7 @@
998998
</ClCompile>
999999
<ClCompile Include="..\src\pj\ssl_sock_ossl.c" />
10001000
<ClCompile Include="..\src\pj\ssl_sock_gtls.c" />
1001+
<ClCompile Include="..\src\pj\ssl_sock_schannel.c" />
10011002
<ClCompile Include="..\src\pj\string.c" />
10021003
<ClCompile Include="..\src\pj\symbols.c">
10031004
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug-Dynamic|Win32'">true</ExcludedFromBuild>

pjlib/include/pj/config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,9 @@
10771077
/** Using Apple's Network framework */
10781078
#define PJ_SSL_SOCK_IMP_APPLE 4
10791079

1080+
/** Using Windows's Schannel */
1081+
#define PJ_SSL_SOCK_IMP_SCHANNEL 5
1082+
10801083
/**
10811084
* Select which SSL socket implementation to use. Currently pjlib supports
10821085
* PJ_SSL_SOCK_IMP_OPENSSL, which uses OpenSSL, and PJ_SSL_SOCK_IMP_GNUTLS,

pjlib/include/pj/ssl_sock.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ typedef enum pj_ssl_cert_verify_flag_t
117117
*/
118118
PJ_SSL_CERT_ECHAIN_TOO_LONG = (1 << 8),
119119

120+
/**
121+
* The certificate signature is created using a weak hashing algorithm.
122+
*/
123+
PJ_SSL_CERT_EWEAK_SIGNATURE = (1 << 9),
124+
120125
/**
121126
* The server identity does not match to any identities specified in
122127
* the certificate, e.g: subjectAltName extension, subject common name.
@@ -145,6 +150,59 @@ typedef enum pj_ssl_cert_name_type
145150
PJ_SSL_CERT_NAME_IP
146151
} pj_ssl_cert_name_type;
147152

153+
/**
154+
* Field type for looking up SSL certificate in the certificate stores.
155+
*/
156+
typedef enum pj_ssl_cert_lookup_type
157+
{
158+
/**
159+
* No certificate to be looked up.
160+
*/
161+
PJ_SSL_CERT_LOOKUP_NONE,
162+
163+
/**
164+
* Lookup by subject, this will lookup any first certificate whose
165+
* subject containing the specified keyword. Note that subject may not
166+
* be unique in the store, so the lookup may end up selecting a wrong
167+
* certificate.
168+
*/
169+
PJ_SSL_CERT_LOOKUP_SUBJECT,
170+
171+
/**
172+
* Lookup by fingerprint/thumbprint (SHA1 hash), this will lookup
173+
* any first certificate whose fingerprint matching the specified
174+
* keyword. The keyword is an array of hash octets.
175+
*/
176+
PJ_SSL_CERT_LOOKUP_FINGERPRINT,
177+
178+
/**
179+
* Lookup by friendly name, this will lookup any first certificate
180+
* whose friendly name containing the specified keyword. Note that
181+
* friendly name may not be unique in the store, so the lookup may end up
182+
* selecting a wrong certificate.
183+
*/
184+
PJ_SSL_CERT_LOOKUP_FRIENDLY_NAME
185+
186+
} pj_ssl_cert_lookup_type;
187+
188+
/**
189+
* Describe structure of certificate lookup criteria.
190+
*/
191+
typedef struct pj_ssl_cert_lookup_criteria
192+
{
193+
/**
194+
* Certificate field type to look.
195+
*/
196+
pj_ssl_cert_lookup_type type;
197+
198+
/*
199+
* Keyword to match on the field specified in \a type.
200+
*/
201+
pj_str_t keyword;
202+
203+
} pj_ssl_cert_lookup_criteria;
204+
205+
148206
/**
149207
* Describe structure of certificate info.
150208
*/
@@ -273,6 +331,30 @@ PJ_DECL(pj_status_t) pj_ssl_cert_load_from_buffer(pj_pool_t *pool,
273331
const pj_str_t *privkey_pass,
274332
pj_ssl_cert_t **p_cert);
275333

334+
/**
335+
* Create credential from OS certificate store, this function will lookup
336+
* certificate using the specified criterias.
337+
*
338+
* Currently this is used by Windows Schannel backend only, it will lookup
339+
* in the Current User store first, if no certificate with the specified
340+
* criteria is not found, it will lookup in the Local Machine store.
341+
*
342+
* Note that for manual verification (e.g: when pj_ssl_sock_param.verify_peer
343+
* is disabled), the backend will provide pre-verification result against
344+
* trusted CA certificates in Current User store only (will not check CA
345+
* certificates in the Local Machine store).
346+
*
347+
* @param pool The pool.
348+
* @param criteria The lookup criteria.
349+
* @param p_cert Pointer to credential instance to be created.
350+
*
351+
* @return PJ_SUCCESS when successful.
352+
*/
353+
PJ_DECL(pj_status_t) pj_ssl_cert_load_from_store(
354+
pj_pool_t *pool,
355+
const pj_ssl_cert_lookup_criteria *criteria,
356+
pj_ssl_cert_t **p_cert);
357+
276358
/**
277359
* Dump SSL certificate info.
278360
*

pjlib/src/pj/activesock.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,8 @@ static void ioqueue_on_read_complete(pj_ioqueue_key_t *key,
513513
ret = (*asock->cb.on_data_read)(asock, r->pkt, r->size,
514514
PJ_SUCCESS, &remainder);
515515
PJ_ASSERT_ON_FAIL(
516-
!asock->stream_oriented || remainder <= r->size, {
516+
!ret || !asock->stream_oriented || remainder <= r->size,
517+
{
517518
PJ_LOG(2, ("",
518519
"App bug! Invalid remainder length from "
519520
"activesock on_data_read()."));
@@ -589,7 +590,8 @@ static void ioqueue_on_read_complete(pj_ioqueue_key_t *key,
589590
ret = (*asock->cb.on_data_read)(asock, r->pkt, r->size,
590591
status, &remainder);
591592
PJ_ASSERT_ON_FAIL(
592-
!asock->stream_oriented || remainder <= r->size, {
593+
!ret || !asock->stream_oriented || remainder <= r->size,
594+
{
593595
PJ_LOG(2, ("",
594596
"App bug! Invalid remainder length from "
595597
"activesock on_data_read()."));

pjlib/src/pj/ssl_sock_common.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ PJ_DEF(pj_status_t) pj_ssl_cert_get_verify_status_strings(
173173
case PJ_SSL_CERT_ECHAIN_TOO_LONG:
174174
p = "The certificate chain length is too long";
175175
break;
176+
case PJ_SSL_CERT_EWEAK_SIGNATURE:
177+
p = "The certificate signature is created using a weak hashing "
178+
"algorithm";
179+
break;
176180
case PJ_SSL_CERT_EIDENTITY_NOT_MATCH:
177181
p = "The server identity does not match to any identities "
178182
"specified in the certificate";

0 commit comments

Comments
 (0)