Skip to content

Commit 1a1875f

Browse files
committed
mbedtls: proper certificate verification
1 parent ca3b223 commit 1a1875f

File tree

1 file changed

+50
-26
lines changed

1 file changed

+50
-26
lines changed

src/streams/mbedtls.c

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -80,46 +80,73 @@ static int ssl_teardown(mbedtls_ssl_context *ssl)
8080
return ret;
8181
}
8282

83+
static int check_host_name(const char *name, const char *host)
84+
{
85+
if (!strcasecmp(name, host))
86+
return 0;
87+
88+
if (gitno__match_host(name, host) < 0)
89+
return -1;
90+
91+
return 0;
92+
}
93+
8394
static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
8495
{
8596
const mbedtls_x509_crt *cert;
86-
int flags;
87-
struct in6_addr addr6;
88-
struct in_addr addr4;
89-
void *addr;
97+
const mbedtls_x509_sequence *alts;
98+
int ret, matched = -1;
99+
size_t sn_size = 512;
100+
char subject_name[sn_size], alt_name[sn_size];
101+
90102

91-
if( ( flags = mbedtls_ssl_get_verify_result(ssl) ) != 0 )
92-
{
103+
if ((ret = mbedtls_ssl_get_verify_result(ssl)) != 0) {
93104
char vrfy_buf[512];
94-
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
105+
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret );
95106
giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
96107
return GIT_ECERTIFICATE;
97108
}
98109

99-
/* Try to parse the host as an IP address to see if it is */
100-
if (p_inet_pton(AF_INET, host, &addr4)) {
101-
addr = &addr4;
102-
} else {
103-
if(p_inet_pton(AF_INET6, host, &addr6)) {
104-
addr = &addr6;
105-
}
106-
}
107-
108110
cert = mbedtls_ssl_get_peer_cert(ssl);
109111
if (!cert) {
110112
giterr_set(GITERR_SSL, "the server did not provide a certificate");
111113
return -1;
112114
}
113115

114116
/* Check the alternative names */
115-
//TODO: cert->subject_alt_names
117+
alts = &cert->subject_alt_names;
118+
while (alts != NULL && matched != 1) {
119+
// Buffer is too small
120+
if( alts->buf.len >= sn_size )
121+
goto on_error;
122+
123+
memcpy(alt_name, alts->buf.p, alts->buf.len);
124+
alt_name[alts->buf.len] = '\0';
125+
126+
if (!memchr(alt_name, '\0', alts->buf.len)) {
127+
if (check_host_name(alt_name, host) < 0)
128+
matched = 0;
129+
else
130+
matched = 1;
131+
}
132+
133+
alts = alts->next;
134+
}
135+
if (matched == 0)
136+
goto cert_fail_name;
137+
138+
if (matched == 1)
139+
return 0;
116140

117141
/* If no alternative names are available, check the common name */
118-
/*TODO
119-
mbedtls_x509_name peer_name = cert->subject;
120-
if (peer_name == NULL)
142+
ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
143+
if (ret == 0)
121144
goto on_error;
122-
*/
145+
if (memchr(subject_name, '\0', ret))
146+
goto cert_fail_name;
147+
148+
if (check_host_name(subject_name, host) < 0)
149+
goto cert_fail_name;
123150

124151
return 0;
125152

@@ -151,12 +178,9 @@ int mbedtls_connect(git_stream *stream)
151178

152179
st->connected = true;
153180

154-
mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
155-
156-
/* specify the host in case SNI is needed */
157-
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
158181
mbedtls_ssl_set_hostname(st->ssl, st->host);
159-
#endif
182+
183+
mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
160184

161185
if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
162186
return ssl_set_error(st->ssl, ret);

0 commit comments

Comments
 (0)