Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf75a959

Browse files
committed
Refactor client-side SSL certificate checking code
Separate the parts specific to the SSL library from the general logic.The previous code structure wasopen_client_SSL()calls verify_peer_name_matches_certificate()calls verify_peer_name_matches_certificate_name()calls wildcard_certificate_match()and was completely in fe-secure-openssl.c. The new structure isopen_client_SSL() [openssl]calls pq_verify_peer_name_matches_certificate() [generic]calls pgtls_verify_peer_name_matches_certificate_guts() [openssl]calls openssl_verify_peer_name_matches_certificate_name() [openssl]calls pq_verify_peer_name_matches_certificate_name() [generic]calls wildcard_certificate_match() [generic]Move the generic functions into a new file fe-secure-common.c, so thecalls generally go fe-connect.c -> fe-secure.c -> fe-secure-${impl}.c ->fe-secure-common.c, although there is a bit of back-and-forth betweenthe last two.Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
1 parent38d485f commitf75a959

File tree

7 files changed

+271
-187
lines changed

7 files changed

+271
-187
lines changed

‎src/interfaces/libpq/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ OBJS += encnames.o wchar.o
5252
OBJS += base64.o ip.o md5.o scram-common.o saslprep.o unicode_norm.o
5353

5454
ifeq ($(with_openssl),yes)
55-
OBJS += fe-secure-openssl.o sha2_openssl.o
55+
OBJS += fe-secure-openssl.ofe-secure-common.osha2_openssl.o
5656
else
5757
OBJS += sha2.o
5858
endif
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* fe-secure-common.c
4+
*
5+
* common implementation-independent SSL support code
6+
*
7+
* While fe-secure.c contains the interfaces that the rest of libpq call, this
8+
* file contains support routines that are used by the library-specific
9+
* implementations such as fe-secure-openssl.c.
10+
*
11+
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
12+
* Portions Copyright (c) 1994, Regents of the University of California
13+
*
14+
* IDENTIFICATION
15+
* src/interfaces/libpq/fe-secure-common.c
16+
*
17+
*-------------------------------------------------------------------------
18+
*/
19+
20+
#include"postgres_fe.h"
21+
22+
#include"fe-secure-common.h"
23+
24+
#include"libpq-int.h"
25+
#include"pqexpbuffer.h"
26+
27+
/*
28+
* Check if a wildcard certificate matches the server hostname.
29+
*
30+
* The rule for this is:
31+
*1. We only match the '*' character as wildcard
32+
*2. We match only wildcards at the start of the string
33+
*3. The '*' character does *not* match '.', meaning that we match only
34+
* a single pathname component.
35+
*4. We don't support more than one '*' in a single pattern.
36+
*
37+
* This is roughly in line with RFC2818, but contrary to what most browsers
38+
* appear to be implementing (point 3 being the difference)
39+
*
40+
* Matching is always case-insensitive, since DNS is case insensitive.
41+
*/
42+
staticbool
43+
wildcard_certificate_match(constchar*pattern,constchar*string)
44+
{
45+
intlenpat=strlen(pattern);
46+
intlenstr=strlen(string);
47+
48+
/* If we don't start with a wildcard, it's not a match (rule 1 & 2) */
49+
if (lenpat<3||
50+
pattern[0]!='*'||
51+
pattern[1]!='.')
52+
return false;
53+
54+
/* If pattern is longer than the string, we can never match */
55+
if (lenpat>lenstr)
56+
return false;
57+
58+
/*
59+
* If string does not end in pattern (minus the wildcard), we don't match
60+
*/
61+
if (pg_strcasecmp(pattern+1,string+lenstr-lenpat+1)!=0)
62+
return false;
63+
64+
/*
65+
* If there is a dot left of where the pattern started to match, we don't
66+
* match (rule 3)
67+
*/
68+
if (strchr(string,'.')<string+lenstr-lenpat)
69+
return false;
70+
71+
/* String ended with pattern, and didn't have a dot before, so we match */
72+
return true;
73+
}
74+
75+
/*
76+
* Check if a name from a server's certificate matches the peer's hostname.
77+
*
78+
* Returns 1 if the name matches, and 0 if it does not. On error, returns
79+
* -1, and sets the libpq error message.
80+
*
81+
* The name extracted from the certificate is returned in *store_name. The
82+
* caller is responsible for freeing it.
83+
*/
84+
int
85+
pq_verify_peer_name_matches_certificate_name(PGconn*conn,
86+
constchar*namedata,size_tnamelen,
87+
char**store_name)
88+
{
89+
char*name;
90+
intresult;
91+
char*host=PQhost(conn);
92+
93+
*store_name=NULL;
94+
95+
/*
96+
* There is no guarantee the string returned from the certificate is
97+
* NULL-terminated, so make a copy that is.
98+
*/
99+
name=malloc(namelen+1);
100+
if (name==NULL)
101+
{
102+
printfPQExpBuffer(&conn->errorMessage,
103+
libpq_gettext("out of memory\n"));
104+
return-1;
105+
}
106+
memcpy(name,namedata,namelen);
107+
name[namelen]='\0';
108+
109+
/*
110+
* Reject embedded NULLs in certificate common or alternative name to
111+
* prevent attacks like CVE-2009-4034.
112+
*/
113+
if (namelen!=strlen(name))
114+
{
115+
free(name);
116+
printfPQExpBuffer(&conn->errorMessage,
117+
libpq_gettext("SSL certificate's name contains embedded null\n"));
118+
return-1;
119+
}
120+
121+
if (pg_strcasecmp(name,host)==0)
122+
{
123+
/* Exact name match */
124+
result=1;
125+
}
126+
elseif (wildcard_certificate_match(name,host))
127+
{
128+
/* Matched wildcard name */
129+
result=1;
130+
}
131+
else
132+
{
133+
result=0;
134+
}
135+
136+
*store_name=name;
137+
returnresult;
138+
}
139+
140+
/*
141+
* Verify that the server certificate matches the hostname we connected to.
142+
*
143+
* The certificate's Common Name and Subject Alternative Names are considered.
144+
*/
145+
bool
146+
pq_verify_peer_name_matches_certificate(PGconn*conn)
147+
{
148+
char*host=PQhost(conn);
149+
intrc;
150+
intnames_examined=0;
151+
char*first_name=NULL;
152+
153+
/*
154+
* If told not to verify the peer name, don't do it. Return true
155+
* indicating that the verification was successful.
156+
*/
157+
if (strcmp(conn->sslmode,"verify-full")!=0)
158+
return true;
159+
160+
/* Check that we have a hostname to compare with. */
161+
if (!(host&&host[0]!='\0'))
162+
{
163+
printfPQExpBuffer(&conn->errorMessage,
164+
libpq_gettext("host name must be specified for a verified SSL connection\n"));
165+
return false;
166+
}
167+
168+
rc=pgtls_verify_peer_name_matches_certificate_guts(conn,&names_examined,&first_name);
169+
170+
if (rc==0)
171+
{
172+
/*
173+
* No match. Include the name from the server certificate in the error
174+
* message, to aid debugging broken configurations. If there are
175+
* multiple names, only print the first one to avoid an overly long
176+
* error message.
177+
*/
178+
if (names_examined>1)
179+
{
180+
printfPQExpBuffer(&conn->errorMessage,
181+
libpq_ngettext("server certificate for \"%s\" (and %d other name) does not match host name \"%s\"\n",
182+
"server certificate for \"%s\" (and %d other names) does not match host name \"%s\"\n",
183+
names_examined-1),
184+
first_name,names_examined-1,host);
185+
}
186+
elseif (names_examined==1)
187+
{
188+
printfPQExpBuffer(&conn->errorMessage,
189+
libpq_gettext("server certificate for \"%s\" does not match host name \"%s\"\n"),
190+
first_name,host);
191+
}
192+
else
193+
{
194+
printfPQExpBuffer(&conn->errorMessage,
195+
libpq_gettext("could not get server's host name from server certificate\n"));
196+
}
197+
}
198+
199+
/* clean up */
200+
if (first_name)
201+
free(first_name);
202+
203+
return (rc==1);
204+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* fe-secure-common.h
4+
*
5+
* common implementation-independent SSL support code
6+
*
7+
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
9+
*
10+
* IDENTIFICATION
11+
* src/interfaces/libpq/fe-secure-common.h
12+
*
13+
*-------------------------------------------------------------------------
14+
*/
15+
16+
#ifndefFE_SECURE_COMMON_H
17+
#defineFE_SECURE_COMMON_H
18+
19+
#include"libpq-fe.h"
20+
21+
externintpq_verify_peer_name_matches_certificate_name(PGconn*conn,
22+
constchar*namedata,size_tnamelen,
23+
char**store_name);
24+
externboolpq_verify_peer_name_matches_certificate(PGconn*conn);
25+
26+
#endif/* FE_SECURE_COMMON_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp