1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 #include "log.h"
22 #include "zbxhttp.h"
23 
24 #ifdef HAVE_LIBCURL
25 
26 extern char	*CONFIG_SOURCE_IP;
27 
28 extern char	*CONFIG_SSL_CA_LOCATION;
29 extern char	*CONFIG_SSL_CERT_LOCATION;
30 extern char	*CONFIG_SSL_KEY_LOCATION;
31 
zbx_http_prepare_ssl(CURL * easyhandle,const char * ssl_cert_file,const char * ssl_key_file,const char * ssl_key_password,unsigned char verify_peer,unsigned char verify_host,char ** error)32 int	zbx_http_prepare_ssl(CURL *easyhandle, const char *ssl_cert_file, const char *ssl_key_file,
33 		const char *ssl_key_password, unsigned char verify_peer, unsigned char verify_host,
34 		char **error)
35 {
36 	CURLcode	err;
37 
38 	if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYPEER, 0 == verify_peer ? 0L : 1L)))
39 	{
40 		*error = zbx_dsprintf(*error, "Cannot set verify the peer's SSL certificate: %s",
41 				curl_easy_strerror(err));
42 		return FAIL;
43 	}
44 
45 	if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYHOST, 0 == verify_host ? 0L : 2L)))
46 	{
47 		*error = zbx_dsprintf(*error, "Cannot set verify the certificate's name against host: %s",
48 				curl_easy_strerror(err));
49 		return FAIL;
50 	}
51 
52 	if (NULL != CONFIG_SOURCE_IP)
53 	{
54 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_INTERFACE, CONFIG_SOURCE_IP)))
55 		{
56 			*error = zbx_dsprintf(*error, "Cannot specify source interface for outgoing traffic: %s",
57 					curl_easy_strerror(err));
58 			return FAIL;
59 		}
60 	}
61 
62 	if (0 != verify_peer && NULL != CONFIG_SSL_CA_LOCATION)
63 	{
64 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_CAPATH, CONFIG_SSL_CA_LOCATION)))
65 		{
66 			*error = zbx_dsprintf(*error, "Cannot specify directory holding CA certificates: %s",
67 					curl_easy_strerror(err));
68 			return FAIL;
69 		}
70 	}
71 
72 	if ('\0' != *ssl_cert_file)
73 	{
74 		char	*file_name;
75 
76 		file_name = zbx_dsprintf(NULL, "%s/%s", CONFIG_SSL_CERT_LOCATION, ssl_cert_file);
77 		zabbix_log(LOG_LEVEL_DEBUG, "using SSL certificate file: '%s'", file_name);
78 
79 		err = curl_easy_setopt(easyhandle, CURLOPT_SSLCERT, file_name);
80 		zbx_free(file_name);
81 
82 		if (CURLE_OK != err)
83 		{
84 			*error = zbx_dsprintf(*error, "Cannot set SSL client certificate: %s", curl_easy_strerror(err));
85 			return FAIL;
86 		}
87 
88 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_SSLCERTTYPE, "PEM")))
89 		{
90 			*error = zbx_dsprintf(NULL, "Cannot specify type of the client SSL certificate: %s",
91 					curl_easy_strerror(err));
92 			return FAIL;
93 		}
94 	}
95 
96 	if ('\0' != *ssl_key_file)
97 	{
98 		char	*file_name;
99 
100 		file_name = zbx_dsprintf(NULL, "%s/%s", CONFIG_SSL_KEY_LOCATION, ssl_key_file);
101 		zabbix_log(LOG_LEVEL_DEBUG, "using SSL private key file: '%s'", file_name);
102 
103 		err = curl_easy_setopt(easyhandle, CURLOPT_SSLKEY, file_name);
104 		zbx_free(file_name);
105 
106 		if (CURLE_OK != err)
107 		{
108 			*error = zbx_dsprintf(NULL, "Cannot specify private keyfile for TLS and SSL client cert: %s",
109 					curl_easy_strerror(err));
110 			return FAIL;
111 		}
112 
113 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_SSLKEYTYPE, "PEM")))
114 		{
115 			*error = zbx_dsprintf(NULL, "Cannot set type of the private key file: %s",
116 					curl_easy_strerror(err));
117 			return FAIL;
118 		}
119 	}
120 
121 	if ('\0' != *ssl_key_password)
122 	{
123 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_KEYPASSWD, ssl_key_password)))
124 		{
125 			*error = zbx_dsprintf(NULL, "Cannot set passphrase to private key: %s",
126 					curl_easy_strerror(err));
127 			return FAIL;
128 		}
129 	}
130 
131 	return SUCCEED;
132 }
133 
zbx_http_prepare_auth(CURL * easyhandle,unsigned char authtype,const char * username,const char * password,char ** error)134 int	zbx_http_prepare_auth(CURL *easyhandle, unsigned char authtype, const char *username, const char *password,
135 		char **error)
136 {
137 	if (HTTPTEST_AUTH_NONE != authtype)
138 	{
139 		long		curlauth = 0;
140 		char		auth[MAX_STRING_LEN];
141 		CURLcode	err;
142 
143 		zabbix_log(LOG_LEVEL_DEBUG, "setting HTTPAUTH [%d]", authtype);
144 
145 		switch (authtype)
146 		{
147 			case HTTPTEST_AUTH_BASIC:
148 				curlauth = CURLAUTH_BASIC;
149 				break;
150 			case HTTPTEST_AUTH_NTLM:
151 				curlauth = CURLAUTH_NTLM;
152 				break;
153 			case HTTPTEST_AUTH_NEGOTIATE:
154 #if LIBCURL_VERSION_NUM >= 0x072600
155 				curlauth = CURLAUTH_NEGOTIATE;
156 #else
157 				curlauth = CURLAUTH_GSSNEGOTIATE;
158 #endif
159 				break;
160 			default:
161 				THIS_SHOULD_NEVER_HAPPEN;
162 				break;
163 		}
164 
165 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, curlauth)))
166 		{
167 			*error = zbx_dsprintf(*error, "Cannot set HTTP server authentication method: %s",
168 					curl_easy_strerror(err));
169 			return FAIL;
170 		}
171 
172 		zbx_snprintf(auth, sizeof(auth), "%s:%s", username, password);
173 		if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_USERPWD, auth)))
174 		{
175 			*error = zbx_dsprintf(*error, "Cannot set user name and password: %s",
176 					curl_easy_strerror(err));
177 			return FAIL;
178 		}
179 	}
180 
181 	return SUCCEED;
182 }
183 
zbx_http_get_header(char ** headers)184 char	*zbx_http_get_header(char **headers)
185 {
186 	while ('\0' != **headers)
187 	{
188 		char	c, *p_end, *line;
189 
190 		while ('\r' == **headers || '\n' == **headers)
191 			(*headers)++;
192 
193 		p_end = *headers;
194 
195 		while ('\0' != *p_end && '\r' != *p_end && '\n' != *p_end)
196 			p_end++;
197 
198 		if (*headers == p_end)
199 			return NULL;
200 
201 		if ('\0' != (c = *p_end))
202 			*p_end = '\0';
203 		line = zbx_strdup(NULL, *headers);
204 		if ('\0' != c)
205 			*p_end = c;
206 
207 		*headers = p_end;
208 
209 		zbx_lrtrim(line, " \t");
210 		if ('\0' == *line)
211 			zbx_free(line);
212 		else
213 			return line;
214 	}
215 
216 	return NULL;
217 }
218 
219 #endif
220