• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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