cisco / libest Goto Github PK
View Code? Open in Web Editor NEWLicense: Other
License: Other
This directory contains the libest project, which is an EST stack written in C. EST is used for secure certificate enrollment and is compatible with Suite B certs (as well as RSA and DSA certificates). EST is a suitable replacement for SCEP. Directory contents: /src This directory contains the EST library. The target built from this directory is libest.a. /example This directory contains sample code for implementing an application that uses the libEST library. /test This directory contains unit test code to verify the libest capabilities. Getting started --------------- 1. ./configure; make ; make install 2. Descend into the example/server directory and run the sample EST server. There is a README in this directory with detailed instructions. 3. Descend into the example/client directory and run the sample EST client. There is a README in this directory with detailed instructions. For further detailed instructions, build the reference manual PDF for libEST and refer to it. Steps to build the reference manual are in README.doxy Getting started - Windows -------------------------- libEST can be built natively on Windows, but only client functionality has been explictly tested. libEST uses Gradle for Windows build automation and the Visual Studio toolchain. To build using Gradle you must have Visual Studio 2010, 2012, or 2013 and at least Gradle 2.12 on your system. Follow the steps below to build an EST dll with Gradle: 1. Have OpenSSL built and installed on your Windows system 2. Set the following environment variables to tell the Gradle build script where to find your installations of OpenSSL and EST SSL_DIR - must contain an "include" subdirectory for the OpenSSL header files, a "bin" subdirectory for the OpenSSL dll binaries, and a "lib" subdirectory for the OpenSSL link files set SSL_DIR=C:\PathToYourLibraryInstalls\OpenSSL URIPARSER_DIR - Specify only if path segment support is required. Must contain an "include" subdirectory for uriparser header files and a "lib" subdirectory for the uriparser.lib static library file. set URIPARSER_DIR=C:\PathToYourLibraryInstalls\uriparser PATH - must contain the path to your Visual Studio 2010/2012/2013 VC bin directory prior to any other Visual Studio bin directory and the path to your Gradle executable (which should already be in PATH) set PATH=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin;%PATH% 3. Invoke Gradle: gradle estReleaseSharedLibrary The est.dll binary and est.lib link file can then be found at the path below: build\libs\est\shared\release To see all build related tasks Gradle can perform for EST, type: gradle tasks Cross-compiling --------------- It has been quite a while, but libEST has been cross-compiled for Android, but no testing has been performed. Follow these steps to compile using the Android NDK: 1. Compile and install OpenSSL for Android. See OpenSSL docs for details. 2. Set the following environment variables to setup your cross-compile. This assumes you've installed OpenSSL into /usr/local/OpenSSL-Android: export CC=arm-linux-androideabi-gcc export LDFLAGS=-L/usr/local/OpenSSL-Android/lib export CFLAGS="-DDISABLE_BACKTRACE -DDISABLE_TSEARCH -DIS_FREEBSD" **Note: you may not need all the CFLAGS values above depending on your tool chain. 3. Configure libEST for cross-compiling and specify the location of your OpenSSL build: ./configure --with-ssl-dir=/usr/local/OpenSSL-Android \ --host=arm-linux-androideabi \ --disable-shared --disable-pthreads \ --prefix=/var/android/libest 4. Compile and install: make make install
Hello!
I would like to understand difference (both comparing to spec. and in terms of configuration) between EST server running on testrfc7030.cisco.com and an example of EST server located in example/server directory.
I see from my tests that at least enabled ciphers are different. Please, consider, tests below.
So, my questions:
Thank you in advance.
When using the est_client_enroll_csr() API to enroll and externally generated CSR, libest does not always include the challengePassword in the CSR even when PoP is forced on by using est_client_force_pop().
The root of the problem has to do with how OpenSSL handles the X509_REQ struct internally when serializing the data to DER format. There is a cached copy of the DER encoded representation of the data. Libest will modify the attributes under X509_REQ to add the challengePassword attribute. But the cached DER copy is used when serializing the data again. Therefore, when an application passes in an X509_REQ* through the est_client_enroll_csr() API, and it already contains a cached copy of the DER representation, then the challengePassword attribute is not serialized on the wire when libest invokes i2d_X509_REQ_bio().
Openssl shows the certificate is expired, which causes any https connection failed. Can you please take a look at it? Thanks.
jerry@jerry-linux:~/est$ openssl s_client -connect testrfc7030.com:8443
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = testrfc7030.com
verify error:num=10:certificate has expired
notAfter=Dec 13 21:51:36 2018 GMT
verify return:1
depth=0 CN = testrfc7030.com
notAfter=Dec 13 21:51:36 2018 GMT
verify return:1
Hi I just followed the instructions in the README but I'm getting a file not found issue.
In file included from est.c:22:
./est.h:17:10: fatal error: 'openssl/srp.h' file not found
#include <openssl/srp.h>
The macros to invoke the logging facility use variadic arguments that are not compliant with C99. This creates a problem for some compilers.
Meanwhile I'm not sure if my latest pull request 10 days ago went to the correct location.
For some reason, it is shown at DDvO#1 but it does not appear on https://github.com/cisco/libest/pulls which would have been my intention.
If I did a mistake, how to properly submit the differences between ddvo_contrib2 and ddvo_contrib3 as given in DDvO/libest@ddvo_contrib2...DDvO:ddvo_contrib3 ?
I came across the last parameter 'ex_data' of the server callback functions:
int (*est_enroll_pkcs10_cb)(unsigned char *pkcs10, int p10_len,
unsigned char **pkcs7, int *cert_len,
char *user_id, X509 *peer_cert,
void *ex_data);
int (*est_reenroll_pkcs10_cb)(unsigned char *pkcs10, int p10_len,
unsigned char **pkcs7, int *cert_len,
char *user_id, X509 *peer_cert,
void *ex_data);
unsigned char *(*est_get_csr_cb)(int *csr_len, void *ex_data);
int (*est_http_auth_cb)(struct est_ctx *ctx, EST_HTTP_AUTH_HDR *ah,
X509 *peer_cert, void *ex_data);
partially documented at the est_set_ex_data() function declaration in est.c .
I suggest completing its documentation in est_server.c and est_locl.h and removing its test use in estserver.c, as done tentatively in the diff I'm going to provide,
Hi,
I'm trying to use this lib but when I try to compile the client example (with make) I have this issue :
libtool: error: cannot determine absolute directory name of '../../src/est/.libs'
Before that I have executed "export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/est/lib"
(because the libcrypto.so is in the folder /x86_64-linux-gnu and libest.so is in /est/lib) and "export EST_OPENSSL_CACERT=../server/estCA/cacert.crt".
Thank's for your help
This is an request for enhancement and is not a bug. RFC 7894 updates RFC 7030. As a result, please add support for RFC 7894. Thank you.
I am trying to develop an Android application for provisioning derived credentials that uses an EST client. As a result, support for RFC 7894 is required.
any plan for openssl 1.1.0 support??
I was able to create est.dll using the instructions in the README. While I see that you're not supporting the jest client any longer, do you have any tips/suggestions on how to modify build.gradle to add in building a jest.dll after the est.dll?
I was able to reach more than 100 MiB ram usage on the server by issuing /cacerts requests.
This only happens when using TLS mutual authentication.
When i use http authentication it stops increasing heap after reaching 28.8 MiB.
The analysis with valgrind memcheck does not find any memory leaks.
server:
#create CA for the server
cd example/server/
./createCA.sh
#launch server
./runserver.sh
client:
cd example/client/
export EST_OPENSSL_CACERT=../server/estCA/cacert.crt
#create client certificate
openssl ecparam -name prime256v1 -genkey -out privkey.pem
./estclient -e -s 127.0.0.1 -p 8085 -u estuser -h estpwd -x privkey.pem -o ./
cat cert-0-0.pkcs7 | base64 -d | openssl pkcs7 -inform DER -print_certs > cert.pem
#execute the client
for i in {1..50000};
do ./estclient -g -s 127.0.0.1 -p 8085 -c cert.pem -k privkey.pem -o ./;
echo "$i";
done
look at the increasing memory of the process lt-estserver.
You can speed up the process by running multiple clients (i used three clients).
While using digest auth the server responds with:
HTTP/1.1 401 Unauthorized
Content-Length: 0
WWW-Authenticate: Digest qop="auth", realm="estreal", nonce="1485916038"
However the pre-calculated digest from
https://github.com/cisco/libest/blob/master/example/server/estserver.c#L743
uses "estrealm" not "estreal"
For example:
meganwoods$ md5 -s "estuser:estrealm:estpwd"
MD5 ("estuser:estrealm:estpwd") = 36807fa200741bb0e8fb04fcf08e2de6
Vs:
meganwoods$ md5 -s "estuser:estreal:estpwd"
MD5 ("estuser:estreal:estpwd") = f0386ad8a5dfdc3d77914c5442c24233
The wrong version information for the run-time OpenSSL linkage is displayed when invoking est_log_version(). For example, when compiling against OpenSSL 1.0.1h, and then run-time linking against CiscoSSL 1.0.1g, the following is displayed:
**EST [INFO][est_log_version:164]--> libest 1.0.1 (API level 2)
*__EST [INFO][est_log_version:168]--> Compiled against OpenSSL-1.0.1h
**EST [INFO][est_log_version:169]--> Linking to OpenSSL-1.0.1h
RFC 7030 states the content type in the HTTP header for the enroll and re-enroll messages should be:
Content-Type: application/pkcs7-mime; smime-type=certs-only
CiscoEST omits the certs-only parameter in the enroll and re-enroll messages.
I get the following error when trying to compile after configure. What flags should I use to get over this? Thanks
est_client.c:3663:23: error: dereferencing pointer to incomplete type ‘X509_STORE {aka struct x509_store_st}’
if (store && store->objs && sk_X509_OBJECT_num(store->objs) > 0) {
I just wanted to analyze the TLS encrypted data,to check whats happening.
Since the captured data b/w EST-Client and EST server is encrypted but how can i see this data in wireshark?? I know some keys are required but how to fetch those keys which can be imported in wireshark..
Hi,
I have an EST server which is listening on https://192.168.101.21:8443/.well-known/est/cacerts
for providing CA certificate.
From libest client when I try to get the cert using below command
./estclient -g -s 192.168.101.21 -p 8443 -o certs
I am getting below message. Looks like it is able to read the certificate, but not able to trust it.
CN = TestIntermediate CA, O = Test Org Inc, L = Seattle, ST = Washington, C = US
***EST [ERROR][est_client_send_cacerts_request:2694]--> Returned CACerts chain was invalid
Get CA Cert failed with code 58 (EST_ERR_CACERT_VERIFICATION)
########################################################
Setup Details:
URL https://192.168.101.21:8443/.well-known/est/cacerts is having selfsigned cert.
received CAcert is having properties CN = TestIntermediate CA, O = Test Org Inc, L = Seattle, ST = Washington, C = US, which libest is able to read.
In "export EST_OPENSSL_CACERT=selfsigned.crt" Used listening url's selfsigned cert.it worked with below error
CN = TestIntermediate CA, O = Test Org Inc, L = Seattle, ST = Washington, C = US
***EST [ERROR][est_client_send_cacerts_request:2694]--> Returned CACerts chain was invalid
Get CA Cert failed with code 58 (EST_ERR_CACERT_VERIFICATION)
In "export EST_OPENSSL_CACERT=cacerts.crt" Used actual cacert in EST server,it failed with below error
***EST [ERROR][est_client_connect:2515]--> Error connecting TLS context. 1
Get CA Cert failed with code 38 (EST_ERR_SSL_CONNECT)
In "export EST_OPENSSL_CACERT=merged_self_cacert.crt" it failed with below error
CN = TestIntermediate CA, O = Test Org Inc, L = Seattle, ST = Washington, C = US
***EST [ERROR][est_client_send_cacerts_request:2694]--> Returned CACerts chain was invalid
Get CA Cert failed with code 58 (EST_ERR_CACERT_VERIFICATION)
How can I handle this scenario, where my getca cacert , and est listening url cert are signed differently.
########################################################################
In testrfc7030.com
Looks like both are same and it works.
Could you please provide a solution for this?
Regards
Dev
I've successfully built libest on FreeBSD 11.0 using clang 3.8.0, with this change (needed to get sockaddr_in
):
--- src/est/est_client_proxy.c.orig 2017-03-27 16:36:25 UTC
+++ src/est/est_client_proxy.c
@@ -26,6 +26,7 @@
# include <unistd.h>
# include <arpa/inet.h>
#endif /* WIN32 */
+#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
However, running the self test leads to these failures:
Here is a summary of the failed test cases:
1. US899/us899.c:393 - rv == expected_enroll_rv
2. US899/us899.c:399 - rv == expected_enroll_rv
3. US899/us899.c:393 - rv == expected_enroll_rv
4. US899/us899.c:399 - rv == expected_enroll_rv
5. US899/us899.c:393 - rv == expected_enroll_rv
6. US899/us899.c:399 - rv == expected_enroll_rv
7. US899/us899.c:393 - rv == expected_enroll_rv
8. US899/us899.c:399 - rv == expected_enroll_rv
9. US899/us899.c:393 - rv == expected_enroll_rv
10. US899/us899.c:399 - rv == expected_enroll_rv
11. US899/us899.c:393 - rv == expected_enroll_rv
12. US899/us899.c:399 - rv == expected_enroll_rv
Here is the complete self-test output
libest.test.txt
I would appreciate assistance in debugging and fixing these.
test/UT/runtest does not return a non-zero value when one or more unit tests fail. As a result, scripts are not able to determine if unit tests are failing, making it difficult to automate the unit test. For instance, invoking runtest from Jenkins becomes a problem. Since runtest returns a zero all the time, Jenkins thinks the unit tests are passing. Runtest should be updated to return zero only when all the unit tests have passed.
It is a regression from libest 1.x. This behavior was not observed before 2.x release.
The following error appears:
gcc -DPACKAGE_NAME=\"libest\" -DPACKAGE_TARNAME=\"libest\" -DPACKAGE_VERSION=\"2.0.0p\" -DPACKAGE_STRING=\"libest\ 2.0.0p\" -DPACKAGE_BUGREPORT=\"libest-dev\" -DPACKAGE_URL=\"\" -DPACKAGE=\"libest\" -DVERSION=\"2.0.0p\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DHAVE_LIBDL=1 -DHAVE_LIBPTHREAD=1 -DHAVE_LIBCRYPTO=1 -DHAVE_LIBSSL=1 -I. -I../../../libest/safe_c_stub/lib -I../include -fPIC -g -O2 -Wall -I/usr/local/ssl/include -Wall -I/home/tysonite/fossa/libest_build/safe_c_stub/include -MT libsafe_lib_a-safe_mem_stub.o -MD -MP -MF .deps/libsafe_lib_a-safe_mem_stub.Tpo -c -o libsafe_lib_a-safe_mem_stub.o `test -f '../src/safe_mem_stub.c' || echo '../../../libest/safe_c_stub/lib/'`../src/safe_mem_stub.c
../../../libest/safe_c_stub/lib/../src/safe_mem_stub.c:38:22: fatal error: safe_lib.h: No such file or directory
#include "safe_lib.h"
I have a case where the TLS certificate used on the EST server for HTTPS is issued by publicly trusted CA (Let’s Encrypt), but the EST CA which is used to issue client certificates (requested via /simpleenroll) is internal (AD CS).
Reading “2.1. Obtaining CA Certificates” section of RFC 7030 you can see:
2.1. Obtaining CA Certificates
The EST client can request a copy of the current EST CA
certificate(s) from the EST server. The EST client is assumed to
perform this operation before performing other operations.
Throughout this document we assume the EST CA has a certificate that
is used by the client to verify signed objects issued by the CA,
e.g., certificates and certificate revocation lists (CRLs), and that
a different certificate than the one used to verify signatures on
certificates and CRLs is used when EST protocol communication
requires additional encryption.
This makes me think that the /cacerts must return the certificate chain of the internal CA (AD CS), because the EST client will use it to verify the signed objects (cert/crl).
However, reading the following “4.1.1. Bootstrap Distribution of CA Certificates” and “4.1.3. CA Certificates Response”
4.1.1. Bootstrap Distribution of CA Certificates
...
The EST client uses the /cacerts response to establish an Explicit
Trust Anchor database for subsequent TLS authentication of the EST
server. EST clients MUST NOT engage in any other protocol exchange
until after the /cacerts response has been accepted and a new TLS
session has been established (using TLS certificate-based
authentication).4.1.3. CA Certificates Response
...
The EST server MUST include the current root CA certificate in the
response. The EST server MUST include any additional certificates
the client would need to build a chain from an EST CA-issued
certificate to the current EST CA TA. For example, if the EST CA is
a subordinate CA, then all the appropriate subordinate CA
certificates necessary to build a chain to the root EST CA are
included in the response.
...
Here the RFC is talking about the TLS certificate used for server authentication. In my case this is the publicly trusted CA (Let’s Encrypt).
So, which certificate chain the “/cacerts” operation is supposed to return?
Around line 242 of example/client/estclient.c there is currently this ...
if (force_pop) {
rv = est_client_force_pop(ectx);
if (rv == EST_ERR_NONE) {
printf("\nFailed to enable force PoP");
}
}
I believe it should be "if (rv != EST_ERR_NONE) {"
This will allow the error message to be printed under the correct circumstances.
$ make
[--snip--]
Making all in src
Making all in est
CC est.lo
CC est_ossl_util.lo
CC est_client_proxy.lo
CC est_client.lo
CC est_client_http.lo
CC multipart_parser.lo
CC jsmn.lo
CCLD libest_client.la
make[4]: Nothing to be done for 'all-am'.
Making all in java/jni
make[3]: *** No rule to make target '../../src/est/libest.la', needed by 'libjest.la'. Stop.
est.h:27:25: fatal error: openssl/srp.h: No such file or directory
$ openssl version
OpenSSL 1.0.2d 9 Jul 2015
Seeing error compiling for RHEL 7.
Would you like to add the configuration script "AX_PTHREAD" to your build specification?
Thanks to PR #73, I largely have libest working with OpenSSL 1.1.1c on Alpine Linux 3.10.2, as well as OpenSSL 1.0.2g on Ubuntu 16.04 LTS.
However, I cannot run example/server/estserver correctly under Alpine. When a client requests /csrattrs the server errors because it fails its sanity check of the attributes before returning them. Here is the relevant output from the estserver process:
***EST [INFO][parse_http_message:1243]--> request uri=/.well-known/est/csrattrs
***EST [INFO][handle_request:1358]--> /.well-known/est/csrattrs
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=16, len=38, j=32, out_len=40
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=6, len=7, j=0, out_len=38
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=11, len=6, j=32, out_len=36
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=9, len=42, j=128, out_len=28
***EST [ERROR][est_asn1_parse_attributes:1221]--> Invalid ASN1 encoded data. rv = 63 (EST_ERR_BAD_ASN1_HEX)
In comparison, on Ubuntu using OpenSSL 1.0.2.g:
***EST [INFO][parse_http_message:1243]--> request uri=/.well-known/est/csrattrs
***EST [INFO][handle_request:1358]--> /.well-known/est/csrattrs
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=16, len=38, j=32, out_len=40
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=6, len=7, j=0, out_len=38
***EST [INFO][est_asn1_sanity_test:1138]--> NID=0
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=6, len=9, j=0, out_len=29
***EST [INFO][est_asn1_sanity_test:1138]--> NID=48
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=6, len=5, j=0, out_len=18
***EST [INFO][est_asn1_sanity_test:1138]--> NID=715
***EST [INFO][est_asn1_sanity_test:1124]--> Sanity: tag=6, len=9, j=0, out_len=11
***EST [INFO][est_asn1_sanity_test:1138]--> NID=673
***EST [INFO][log_access:1396]--> 127.0.0.1 [12/Jun/2020:15:13:01 -0600] "GET /.well-known/est/csrattrs HTTP/1.1" -1 0
The first thing I don't understand is why the two systems seem to report a different set of CSR attributes via est_asn1_sanity_test(). It's the exact same code running on both systems, which includes a custom .cnf file and a script that builds all the certs used using the native openssl binary (so the certs aren't exactly the same but built on both platforms using the same commands). Here is the script that starts estserver:
export EST_CACERTS_RESP=estserver.cacerts
export EST_TRUSTED_CERTS=estserver.certs
export EST_OPENSSL_CACONFIG=fiinca/openssl-fiin.cnf
ulimit -c unlimited # allow core dumps
../libest/example/server/estserver -v \
-c fiinca/certs/pki1.fiin.com.pem -k fiinca/private/pki1.fiin.com.key -o \
-r estrealm -p 8443 --keypass_arg fiin
The other problem I'm having is trying to decode what these CSR attributes are when running under Ubuntu. The NID is not reported. Code from src/est/est.c:
while (out_len > 0) {
j = ASN1_get_object(&string, &len, &tag, &xclass, out_len);
EST_LOG_INFO("Sanity: tag=%d, len=%d, j=%d, out_len=%d", tag, len, j, out_len);
if (j & 0x80) {
return (EST_ERR_BAD_ASN1_HEX);
}
switch (tag)
{
case V_ASN1_OBJECT:
#if OPENSSL_VERSION_NUMBER < 0x10100000L
a_object = c2i_ASN1_OBJECT(NULL, &string, len);
#else
a_object = d2i_ASN1_OBJECT(NULL, &string, len);
#endif
if (a_object != NULL) {
nid = OBJ_obj2nid(a_object);
EST_LOG_INFO("NID=%d", nid);
I'm assuming d2i_ASN1_OBJECT() is returning NULL, since tag is clearly V_ASN1_OBJECT (6). Looking at the code for d2i_ASN1_OBJECT, which calls ASN1_get_object(), it seems that the logical reason for returning NULL is that the encoded attribute is in the incorrect form.
I'm not too familiar with openssl or PKI. Any pointers on how to dig into this problem?
How can I add an optional or custom Path in the libest client. When I try to use --path-segment, i am getting the message "Use of path segments not supported in this build of libEST". Can we expect another build which supports this ?
The EST server should support the HTTP "Connection: keep-alive" header from the client. Several people have reported this problem when trying to interop with testrfc7030.cisco.com.
The function est_get_tls_uid() is miscalculating the TLS unique ID to be included in the challengePassword field of the CSR. The current implementation includes an extra newline character. This should be removed.
When using objdump to view the soname in libest.so, the wrong soname is embedded in the ELF header. It should read the same value in configure.ac (currently 1.1.0). Here's the current output from objdump:
objdump -x ./src/est/.libs/libest.so | grep SONAME
SONAME libest.so.1
$ make
[--snip--]
est_server_coap.c:2658:25: error: 'COAP_PKI_KEY_OSSL' undeclared (first
use in this function); did you mean 'COAP_PKI_KEY_ASN1'?
2658 | dtls_key.key_type = COAP_PKI_KEY_OSSL;
In a topology where there is an EST client / proxy / server.
The client attempts an EST re-enroll with an invalid password using either basic or digest authorization.
The server properly responds with an "Authorization Failed"
As the message passes through the proxy,
the client sees a "Bad Request - Invalid PKCS10 message" error instead.
When the client attempts a simple enroll (with invalid password) through a proxy,
the correct error message is received.
When the client attempts a re-enroll (with invalid password) without a proxy,
the correct error message is received.
I would like to understand how can I properly terminate call to est_server_handle_request
, if EST client does not shutdown SSL session?
Right now, probably I am doing something wrong, but if EST client does not close SSL socket on its own side, est_server_handle_request
function will block in SSL_read. Is there anyway to configure libest to return from est_server_handle_request
if EST client freezes, for instance, for some time.
May be any other ways? Should I handle this situation in my own code (with select() with timeout, for example)?
An extra null pointer check is not needed in functions like the following.
Would you like to apply the following semantic patch to find more update candidates?
@Remove_unnecessary_pointer_checks@
expression x;
@@
-if (x)
free(x);
For the server:
Add the distinction between Explicit TA database and Implicit TA database, as this is required according to RFC 7030, section 3.3.2:
The server validates the TLS client certificate using the EST server
Explicit and, if enabled, Implicit TA database(s). The server MUST
maintain a distinction between the use of Explicit and Implicit TA
databases during authentication in order to support proper authorization.
For the client:
Add the distinction between Explicit TA database and Implicit TA database, as this is required according to RFC 7030, section 3.3.1:
The client validates the TLS server certificate using the EST client
Explicit and, if enabled, Implicit TA database(s). The client MUST
maintain a distinction between the use of Explicit and Implicit TA
databases during authentication in order to support proper authorization.
Add id-kp-cmcRA support in est_client_check_fqdn(), making use of the distinction between Explicit TA database and Implicit TA database.
Add the "Trusted CA Indication" according to RFC 7030, section 4.1.3:
The EST client MUST store the extracted EST CA certificate as an
Explicit TA database entry for subsequent EST server authentication.
The EST client SHOULD disable use of Implicit TA database entries for
this EST server now that an Explicit TA database entry is available.
If the client disables the Implicit TA database, and if the EST
server certificate was verified using an Implicit TA database entry,
then the client MUST include the "Trusted CA Indication" extension in
future TLS sessions [RFC6066]. This indicates to the server that
only an EST server certificate authenticatable by the Explicit TA
database entry is now acceptable (otherwise, the EST server might
continue to use a server certificate that is only verifiable by a now
disabled Implicit TA).
Hi again John,
for officially publishing and using libest (and any further updates by us or others) possibly outside the country, we need to confirm to our lawyers that it has a valid TSU, and to this end provide the ECCN (or other relevant information for a TSU exception).
I presume that in order to publish your code at github from Cisco side, you have already had the need to go though the U.S. export control bureaucracy. Could you please share its outcome, also for the benefit of other users, ideally here and e.g., in a central file like the COPYING file?
Thanks,
David
Looking at the nightly build logs (https://openssl-sanity.cisco.com:8443/view/libest/job/libest_master/), some of the SRP unit tests are failing. You'll need to scroll to the bottom of the build log to see the failures.
Upon further investigation, this is a result of using Curl 7.42.1 for testing. Curl has changed behavior when SRP is enabled. This commit improves integration with Curl 7.42.1: e2cd5a3
However, Curl still needs to be patched to pass these SRP test cases. It appears Curl has changed the behavior of server certificate verification. Curl now always attempts to verify the server certificate, regardless of the CURLOPT_SSL_VERIFYHOST setting. Also, when SRP is used, the server doesn't even need to provide a certificate. The bug is in Curl 7.42.1 lib/vtls/openssl.c within the servercert() function. The following logic fixes the issue:
if(!connssl->server_cert) {
if(strict) {
failf(data, "SSL: couldn't get peer certificate!");
return CURLE_PEER_FAILED_VERIFICATION;
}
else {
return CURLE_OK;
}
}
I would like to use syslog logger library. So,i thought of overriding est_init_logger function, I am referring to est_init_logger in est.c.
EST_ERROR est_init_logger (EST_LOG_LEVEL lvl, void (*loggerfunc)(char *, va_list))
//logger function only accepts format and list of arguments. Its doesn't have log_level information. Could you please guide me how to pass that information.
We need this information while setting the priority in syslog function.
void syslog(int priority, const char *format, ...);
could you please suggest log library for est server written in c?
Here is a list of adaptations, mostly on the example client and server,
that I so far did locally and suggest to commit/push::
When client requests CSR attributes, function est_client_build_csr_header use URI EST_SIMPLE_ENROLL_URI but not EST_CSR_ATTRS_URI. Is it a typo?
It seems the repository is only compatible with version 1.0
. It would be nice if the project will continue and compatible with the latest versions of OpenSSL.
Related pull request for version 1.1.1
is available in #73.
Hello,
I’m trying to build the library on Windows. I’ve followed the instructions listed out at the README and was unable to get it working. This is from a clean clone with no modifications. I was able to get this built fine with no issues on Ubuntu16.
Steps I’ve done up to this point:
Here is the output after running gradle estReleaseSharedLibrary task. Any help or suggestions would be appreciated.
Thank you.
C:\Development\work\libest3>gradle estReleaseSharedLibrary
:compileEstReleaseSharedLibraryEstC
est.c
c:\development\work\libest3\src\est\est_client_proxy.h(53) : error C2061: syntax error : identifier 'SOCKET'
c:\development\work\libest3\src\est\est_client_proxy.h(54) : error C2059: syntax error : '}'
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2143: syntax error : missing ')' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2143: syntax error : missing '{' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2371: 'tcw_opts_t' : redefinition; different basic types
c:\development\work\libest3\src\est\est_client_proxy.h(46) : see declaration of 'tcw_opts_t'
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2143: syntax error : missing ';' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2059: syntax error : 'type'
c:\development\work\libest3\src\est\est_client_proxy.h(57) : error C2059: syntax error : ')'
c:\development\work\libest3\src\est\est_client_proxy.h(58) : error C2143: syntax error : missing ')' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(58) : error C2143: syntax error : missing '{' before '*'
c:\development\work\libest3\src\est\est_client_proxy.h(58) : error C2059: syntax error : ')'
c:\development\work\libest3\src\est\est_locl.h(261) : error C2061: syntax error : identifier 'tcw_sock_t'
c:\development\work\libest3\src\est\est_locl.h(294) : error C2059: syntax error : '}'
C:\Development\work\libest3\src\est\est.c(590) : error C2037: left of 'est_mode' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(612) : error C2037: left of 'ca_certs_len' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(613) : error C2037: left of 'ca_certs_len' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(620) : error C2037: left of 'ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(620) : error C2037: left of 'ca_certs_len' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(620) : error C2198: 'malloc' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(621) : error C2037: left of 'ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(627) : error C2037: left of 'ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(627) : error C2037: left of 'ca_certs_len' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(627) : error C2198: 'memcpy_s' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(651) : error C2037: left of 'trusted_certs_store' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(652) : error C2037: left of 'trusted_certs_store' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(656) : error C2037: left of 'trusted_certs_store' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(656) : warning C4047: 'function' : 'X509_STORE *' differs in levels of indirection from 'int (__cdecl *)(int,X509_STORE_CTX *)'
C:\Development\work\libest3\src\est\est.c(656) : warning C4024: 'X509_STORE_set_verify_cb' : different types for formal and actual parameter 1
C:\Development\work\libest3\src\est\est.c(656) : error C2198: 'X509_STORE_set_verify_cb' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(657) : error C2037: left of 'trusted_certs_store' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(657) : warning C4133: 'function' : incompatible types - from 'unsigned char *' to 'X509_STORE *'
C:\Development\work\libest3\src\est\est.c(657) : warning C4047: 'function' : 'unsigned char *' differs in levels of indirection from 'int'
C:\Development\work\libest3\src\est\est.c(657) : warning C4024: 'ossl_init_cert_store' : different types for formal and actual parameter 2
C:\Development\work\libest3\src\est\est.c(657) : error C2198: 'ossl_init_cert_store' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(691) : error C2037: left of 'ex_data' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(694) : error C2037: left of 'ex_data' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(715) : error C2037: left of 'ex_data' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(715) : warning C4033: 'est_get_ex_data' must return a value
C:\Development\work\libest3\src\est\est.c(735) : error C2037: left of 'trusted_certs_store' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(736) : error C2037: left of 'trusted_certs_store' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(736) : error C2198: 'X509_STORE_free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(739) : error C2037: left of 'ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(740) : error C2037: left of 'ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(740) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(743) : error C2037: left of 'retrieved_ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(744) : error C2037: left of 'retrieved_ca_certs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(744) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(747) : error C2037: left of 'retrieved_csrattrs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(748) : error C2037: left of 'retrieved_csrattrs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(748) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(751) : error C2037: left of 'server_csrattrs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(752) : error C2037: left of 'server_csrattrs' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(752) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(755) : error C2037: left of 'enrolled_client_cert' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(756) : error C2037: left of 'enrolled_client_cert' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(756) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(759) : error C2037: left of 'ca_chain_raw' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(760) : error C2037: left of 'ca_chain_raw' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(760) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(763) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(764) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(764) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(767) : error C2037: left of 'dh_tmp' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(768) : error C2037: left of 'dh_tmp' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(768) : error C2198: 'DH_free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(774) : error C2037: left of 'ssl_ctx' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(775) : error C2037: left of 'est_mode' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(781) : error C2037: left of 'sess' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(782) : error C2037: left of 'sess' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(782) : error C2198: 'SSL_SESSION_free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(784) : error C2037: left of 'ssl_ctx' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(784) : error C2198: 'SSL_CTX_free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(787) : error C2037: left of 'est_mode' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1089) : error C2037: left of 'enable_crl' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1131) : warning C4013: 'c2i_ASN1_OBJECT' undefined; assuming extern returning int
C:\Development\work\libest3\src\est\est.c(1131) : warning C4047: '=' : 'ASN1_OBJECT *' differs in levels of indirection from 'int'
C:\Development\work\libest3\src\est\est.c(1488) : warning C4047: '=' : 'ASN1_OBJECT *' differs in levels of indirection from 'int'
C:\Development\work\libest3\src\est\est.c(1815) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1816) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1816) : error C2198: 'free' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(1817) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1820) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1821) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1825) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
C:\Development\work\libest3\src\est\est.c(1825) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int'
C:\Development\work\libest3\src\est\est.c(1825) : warning C4024: 'strncpy_s' : different types for formal and actual parameter 1
C:\Development\work\libest3\src\est\est.c(1826) : warning C4047: 'function' : 'rsize_t' differs in levels of indirection from 'char *'
C:\Development\work\libest3\src\est\est.c(1826) : warning C4024: 'strncpy_s' : different types for formal and actual parameter 2
C:\Development\work\libest3\src\est\est.c(1826) : warning C4047: 'function' : 'const char *' differs in levels of indirection from 'int'
C:\Development\work\libest3\src\est\est.c(1826) : warning C4024: 'strncpy_s' : different types for formal and actual parameter 3
C:\Development\work\libest3\src\est\est.c(1826) : error C2198: 'strncpy_s' : too few arguments for call
C:\Development\work\libest3\src\est\est.c(1829) : error C2037: left of 'uri_path_segment' specifies undefined struct/union 'est_ctx'
est_client.c
C:\Development\work\libest3\src\est\est_client.c(101) : error C2079: 'mctx' uses undefined struct 'evp_md_ctx_st'
C:\Development\work\libest3\src\est\est_client.c(103) : warning C4133: 'function' : incompatible types - from 'int *' to 'EVP_MD_CTX *'
C:\Development\work\libest3\src\est\est_client.c(105) : warning C4133: 'function' : incompatible types - from 'int *' to 'EVP_MD_CTX *'
C:\Development\work\libest3\src\est\est_client.c(117) : error C2037: left of 'req_info' specifies undefined struct/union 'X509_req_st'
C:\Development\work\libest3\src\est\est_client.c(118) : warning C4133: 'function' : incompatible types - from 'int *' to 'EVP_MD_CTX *'
C:\Development\work\libest3\src\est\est_client.c(120) : warning C4013: 'EVP_MD_CTX_cleanup' undefined; assuming extern returning int
C:\Development\work\libest3\src\est\est_client.c(589) : error C2037: left of 'name' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(623) : error C2037: left of 'name' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(631) : error C2037: left of 'name' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(1613) : error C2037: left of 'signature' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(1621) : error C2037: left of 'signature' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(1717) : error C2037: left of 'req_info' specifies undefined struct/union 'X509_req_st'
C:\Development\work\libest3\src\est\est_client.c(3238) : error C2037: left of 'cert_info' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(3239) : error C2037: left of 'cert_info' specifies undefined struct/union 'x509_st'
C:\Development\work\libest3\src\est\est_client.c(3239) : error C2198: 'X509_REQ_add_extensions' : too few arguments for call
C:\Development\work\libest3\src\est\est_client.c(3663) : error C2037: left of 'objs' specifies undefined struct/union 'x509_store_st'
C:\Development\work\libest3\src\est\est_client.c(3663) : error C2198: 'sk_X509_OBJECT_num' : too few arguments for call
est_ossl_util.c
c:\development\work\libest3\src\est\est_client_proxy.h(53) : error C2061: syntax error : identifier 'SOCKET'
c:\development\work\libest3\src\est\est_client_proxy.h(54) : error C2059: syntax error : '}'
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2143: syntax error : missing ')' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2143: syntax error : missing '{' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2371: 'tcw_opts_t' : redefinition; different basic types
c:\development\work\libest3\src\est\est_client_proxy.h(46) : see declaration of 'tcw_opts_t'
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2143: syntax error : missing ';' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(56) : error C2059: syntax error : 'type'
c:\development\work\libest3\src\est\est_client_proxy.h(57) : error C2059: syntax error : ')'
c:\development\work\libest3\src\est\est_client_proxy.h(58) : error C2143: syntax error : missing ')' before ''
c:\development\work\libest3\src\est\est_client_proxy.h(58) : error C2143: syntax error : missing '{' before '*'
c:\development\work\libest3\src\est\est_client_proxy.h(58) : error C2059: syntax error : ')'
c:\development\work\libest3\src\est\est_locl.h(261) : error C2061: syntax error : identifier 'tcw_sock_t'
c:\development\work\libest3\src\est\est_locl.h(294) : error C2059: syntax error : '}'
C:\Development\work\libest3\src\est\est_ossl_util.c(182) : error C2037: left of 'name' specifies undefined struct/union 'x509_st'
est_server.c
C:\Development\work\libest3\src\est\est_server.c(569) : error C2037: left of 'single' specifies undefined struct/union 'x509_attributes_st'
C:\Development\work\libest3\src\est\est_server.c(570) : error C2037: left of 'value' specifies undefined struct/union 'x509_attributes_st'
C:\Development\work\libest3\src\est\est_server.c(574) : error C2037: left of 'value' specifies undefined struct/union 'x509_attributes_st'
C:\Development\work\libest3\src\est\est_server.c(574) : warning C4047: 'function' : 'const stack_st_ASN1_TYPE *' differs in levels of indirection from 'int'
C:\Development\work\libest3\src\est\est_server.c(574) : warning C4024: 'sk_ASN1_TYPE_value' : different types for formal and actual parameter 1
C:\Development\work\libest3\src\est\est_server.c(574) : error C2198: 'sk_ASN1_TYPE_value' : too few arguments for call
C:\Development\work\libest3\src\est\est_server.c(973) : warning C4013: 'c2i_ASN1_OBJECT' undefined; assuming extern returning int
C:\Development\work\libest3\src\est\est_server.c(973) : warning C4047: '=' : 'ASN1_OBJECT *' differs in levels of indirection from 'int'
:compileEstReleaseSharedLibraryEstC FAILED
FAILURE: Build failed with an exception.
Multiple build operations failed.
C compiler failed while compiling est.c.
C compiler failed while compiling est_client.c.
C compiler failed while compiling est_ossl_util.c.
C compiler failed while compiling est_server.c.
See the complete log at: file:///C:/Development/work/libest3/build/tmp/compileEstReleaseSharedLibraryEstC/output.txt
BUILD FAILED
Total time: 10.452 secs
C:\Development\work\libest3>
The example client code should not hard-code the user ID and password used for HTTP authentication. It should be possible to specify these via the CLI.
Consider the API for creating a GET cacerts request from an EST Client as such:
est_client_get_cacerts(NULL, &retrieved_cacerts_len);
Notice there is no EST client context provided. In this case, the client will currently return an "EST_ERR_NO_SSL_CTX".
It seems the the correct error to return in this case should be "EST_ERR_NO_CTX".
A nit I know :-) But anything to help debugging would be great!
thx,
-jj
NOTE: The EST server ports at testrfc7030.com need to be briefly disabled for maintenance. They are going offline starting on 3/14/19 and will be down for one week.
Let'sEncrypt changed it's methods for verifying host name ownership and this change needs to be made to this system. There will be a couple of other necessary changes that need to be made as well. Once these changes have been made, we'll bring these EST server ports back online with a new cert and an updated version of libest running these EST server ports.
Its not possible to bind the est client(or server) socket to a specific ip interface.
An additional (optional) function for binding an ip address to the libEST for client and server would be great
Thank you
Lukas
Some of the certificates used for unit test have expired and need to be renewed. These are located in the US899, US903, and US1060 directories.
When not enabling SRP through the est_client_enable_srp() API, the SRP cipher suites should not be advertised in the ClientHello by the EST client. Using wireshark, this does not appear to be the case.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.