1 /*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007 Christian Grothoff
4
5 libmicrohttpd is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 libmicrohttpd is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libmicrohttpd; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21 /**
22 * @file curl_version_check.c
23 * @brief verify required cURL version is available to run tests
24 * @author Sagie Amir
25 */
26
27 #include "MHD_config.h"
28 #include "platform.h"
29 #include <curl/curl.h>
30
31 #ifndef WINDOWS
32 #include <unistd.h>
33 #endif
34
35 static int
parse_version_number(const char ** s)36 parse_version_number (const char **s)
37 {
38 int i = 0;
39 char num[17];
40
41 while (i < 16 && ((**s >= '0') & (**s <= '9')))
42 {
43 num[i] = **s;
44 (*s)++;
45 i++;
46 }
47
48 num[i] = '\0';
49
50 return atoi (num);
51 }
52
53 const char *
parse_version_string(const char * s,int * major,int * minor,int * micro)54 parse_version_string (const char *s, int *major, int *minor, int *micro)
55 {
56 if (!s)
57 return NULL;
58 *major = parse_version_number (&s);
59 if (*s != '.')
60 return NULL;
61 s++;
62 *minor = parse_version_number (&s);
63 if (*s != '.')
64 return NULL;
65 s++;
66 *micro = parse_version_number (&s);
67 return s;
68 }
69
70 #if HTTPS_SUPPORT
71 int
curl_uses_nss_ssl()72 curl_uses_nss_ssl()
73 {
74 return (strstr(curl_version(), " NSS/") != NULL) ? 0 : -1;
75 }
76 #endif
77
78 /*
79 * check local libcurl version matches required version
80 */
81 int
curl_check_version(const char * req_version)82 curl_check_version (const char *req_version)
83 {
84 const char *ver;
85 const char *curl_ver;
86 #if HTTPS_SUPPORT
87 const char *ssl_ver;
88 const char *req_ssl_ver;
89 #endif
90
91 int loc_major, loc_minor, loc_micro;
92 int rq_major, rq_minor, rq_micro;
93
94 ver = curl_version ();
95 #if HAVE_MESSAGES
96 fprintf (stderr, "curl version: %s\n", ver);
97 #endif
98 /*
99 * this call relies on the cURL string to be of the exact following format :
100 * 'libcurl/7.16.4 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/0.6.5' OR
101 * 'libcurl/7.18.2 GnuTLS/2.4.0 zlib/1.2.3.3 libidn/0.6.5'
102 */
103 curl_ver = strchr (ver, '/');
104 if (curl_ver == NULL)
105 return -1;
106 curl_ver++;
107 /* Parse version numbers */
108 if ( (NULL == parse_version_string (req_version, &rq_major, &rq_minor, &rq_micro)) ||
109 (NULL == parse_version_string (curl_ver, &loc_major, &loc_minor, &loc_micro)) )
110 return -1;
111
112 /* Compare version numbers. */
113 if ((loc_major > rq_major
114 || (loc_major == rq_major && loc_minor > rq_minor)
115 || (loc_major == rq_major && loc_minor == rq_minor
116 && loc_micro > rq_micro) || (loc_major == rq_major
117 && loc_minor == rq_minor
118 && loc_micro == rq_micro)) == 0)
119 {
120 fprintf (stderr,
121 "Error: running curl test depends on local libcurl version > %s\n",
122 req_version);
123 return -1;
124 }
125
126 /*
127 * enforce required gnutls/openssl version.
128 * TODO use curl version string to assert use of gnutls
129 */
130 #if HTTPS_SUPPORT
131 ssl_ver = strchr (curl_ver, ' ');
132 if (ssl_ver == NULL)
133 return -1;
134 ssl_ver++;
135 if (strncmp ("GnuTLS", ssl_ver, strlen ("GNUtls")) == 0)
136 {
137 ssl_ver = strchr (ssl_ver, '/');
138 req_ssl_ver = MHD_REQ_CURL_GNUTLS_VERSION;
139 }
140 else if (strncmp ("OpenSSL", ssl_ver, strlen ("OpenSSL")) == 0)
141 {
142 ssl_ver = strchr (ssl_ver, '/');
143 req_ssl_ver = MHD_REQ_CURL_OPENSSL_VERSION;
144 }
145 else if (strncmp ("NSS", ssl_ver, strlen ("NSS")) == 0)
146 {
147 ssl_ver = strchr (ssl_ver, '/');
148 req_ssl_ver = MHD_REQ_CURL_NSS_VERSION;
149 }
150 else
151 {
152 fprintf (stderr, "Error: unrecognized curl ssl library\n");
153 return -1;
154 }
155 if (ssl_ver == NULL)
156 return -1;
157 ssl_ver++;
158 if ( (NULL == parse_version_string (req_ssl_ver, &rq_major, &rq_minor, &rq_micro)) ||
159 (NULL == parse_version_string (ssl_ver, &loc_major, &loc_minor, &loc_micro)) )
160 return -1;
161
162 if ((loc_major > rq_major
163 || (loc_major == rq_major && loc_minor > rq_minor)
164 || (loc_major == rq_major && loc_minor == rq_minor
165 && loc_micro > rq_micro) || (loc_major == rq_major
166 && loc_minor == rq_minor
167 && loc_micro == rq_micro)) == 0)
168 {
169 fprintf (stderr,
170 "Error: running curl test depends on local libcurl SSL version > %s\n",
171 req_ssl_ver);
172 return -1;
173 }
174 #endif
175 return 0;
176 }
177