source: TI12-security/trunk/NDGSecurity/C/openDapPatch/http.c @ 6834

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/C/openDapPatch/http.c@6834
Revision 6834, 7.9 KB checked in by srcrothers, 10 years ago (diff)

netcdf patch for secure url's via environment variables

  • Property svn:executable set to *
Line 
1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2 See the COPYRIGHT file for more information. */
3
4#include <sys/stat.h>
5#include <unistd.h>
6#include <fcntl.h>
7#include "ocinternal.h"
8#include "ocdebug.h"
9#include "http.h"
10#include "rc.h"
11
12static size_t WriteFileCallback(void*, size_t, size_t, void*);
13static size_t WriteMemoryCallback(void*, size_t, size_t, void*);
14
15struct Fetchdata {
16        FILE* stream;
17        size_t size;
18};
19
20long
21ocfetchhttpcode(CURL* curl)
22{
23    long httpcode;
24    CURLcode cstat = CURLE_OK;
25    /* Extract the http code */
26    cstat = curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&httpcode);
27    if(cstat != CURLE_OK) httpcode = 0;
28    return httpcode;
29}
30
31int
32ocfetchurl_file(CURL* curl, char* url, FILE* stream, unsigned long* sizep)
33{
34        int stat = OC_NOERR;
35        CURLcode cstat = CURLE_OK;
36        struct Fetchdata fetchdata;
37
38
39        /* These four conditionals look for value in four globals set when the
40         * .dodsrc file was read.
41         */
42        if (dods_verify) {
43                if (set_verify(curl) != OC_NOERR)
44                        goto fail;
45        }
46        if (dods_compress) {
47                if (set_compression(curl) != OC_NOERR)
48                        goto fail;
49        }
50        if (pstructProxy) {
51                if (set_proxy(curl, pstructProxy) != OC_NOERR)
52                        goto fail;
53        }
54        if (cook) {
55                if (set_cookies(curl, cook) != OC_NOERR)
56                        goto fail;
57        }
58
59        if (credentials_in_url(url)) {
60                char *result_url = NULL;
61                if (extract_credentials(url, &userName, &password, &result_url) != OC_NOERR)
62                        goto fail;
63                url = result_url;
64        }
65
66        if (userName && password) {
67                if (set_user_password(curl, userName, password) != OC_NOERR)
68                        goto fail;
69        }
70
71        /* Set the URL */
72        cstat = curl_easy_setopt(curl, CURLOPT_URL, (void*)url);
73        if (cstat != CURLE_OK)
74                goto fail;
75
76        /* send all data to this function  */
77        cstat = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteFileCallback);
78        if (cstat != CURLE_OK)
79                goto fail;
80
81        /* we pass our file to the callback function */
82        cstat = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&fetchdata);
83        if (cstat != CURLE_OK)
84                goto fail;
85
86        fetchdata.stream = stream;
87        fetchdata.size = 0;
88        cstat = curl_easy_perform(curl);
89        if (cstat != CURLE_OK) {
90            goto fail;
91        }
92
93        if (stat == OC_NOERR) {
94                /* return the file size*/
95                if (sizep != NULL)
96                        *sizep = fetchdata.size;
97        }
98        return THROW(stat);
99
100        fail: oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
101        return THROW(OC_ECURL);
102}
103
104int
105ocfetchurl(CURL* curl, char* url, OCbytes* buf)
106{
107        int stat = OC_NOERR;
108        CURLcode cstat = CURLE_OK;
109        size_t len;
110
111        /* These conditionals look for value in four globals set when the
112         * .dodsrc file was read.
113         */
114        if (dods_verify) {
115                if (set_verify(curl) != OC_NOERR)
116                        goto fail;
117        }
118        if (dods_compress) {
119                if (set_compression(curl) != OC_NOERR)
120                        goto fail;
121        }
122        if (pstructProxy) {
123                if (set_proxy(curl, pstructProxy) != OC_NOERR)
124                        goto fail;
125        }
126        if (cook) {
127                if (set_cookies(curl, cook) != OC_NOERR)
128                        goto fail;
129        }
130
131        if (credentials_in_url(url)) {
132                char *result_url = NULL;
133                if (extract_credentials(url, &userName, &password, &result_url) != OC_NOERR)
134                        goto fail;
135                url = result_url;
136        }
137
138        if (userName && password) {
139                if (set_user_password(curl, userName, password) != OC_NOERR)
140                        goto fail;
141        }
142
143        /* Set the URL */
144        cstat = curl_easy_setopt(curl, CURLOPT_URL, (void*)url);
145        if (cstat != CURLE_OK)
146                goto fail;
147
148        /* send all data to this function  */
149        cstat = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
150        if (cstat != CURLE_OK)
151                goto fail;
152
153        /* we pass our file to the callback function */
154        cstat = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)buf);
155        if (cstat != CURLE_OK)
156                goto fail;
157
158        cstat = curl_easy_perform(curl);
159        if (cstat != CURLE_OK) {
160            goto fail;
161        }
162
163        /* Null terminate the buffer*/
164        len = ocbyteslength(buf);
165        ocbytesappend(buf, '\0');
166        ocbytessetlength(buf, len); /* dont count null in buffer size*/
167
168        return THROW(stat);
169
170fail: oc_log(LOGERR, "curl error: %s", curl_easy_strerror(cstat));
171        return THROW(OC_ECURL);
172}
173
174static size_t
175WriteFileCallback(void* ptr, size_t size, size_t nmemb, void* data)
176{
177        size_t count;
178        struct Fetchdata* fetchdata;
179        fetchdata = (struct Fetchdata*) data;
180        count = fwrite(ptr, size, nmemb, fetchdata->stream);
181        if (count > 0) {
182                fetchdata->size += (count * size);
183        }
184        return count;
185}
186
187static size_t
188WriteMemoryCallback(void *ptr, size_t size, size_t nmemb,       void *data)
189{
190        size_t realsize = size * nmemb;
191        OCbytes* buf = (OCbytes*) data;
192        ocbytesappendn(buf, ptr, realsize);
193        return realsize;
194}
195
196#if 0
197static void
198assembleurl(DAPURL* durl, OCbytes* buf, int what)
199{
200        encodeurltext(durl->url,buf);
201        if(what & WITHPROJ) {
202                ocbytescat(buf,"?");
203                encodeurltext(durl->projection,buf);
204        }
205        if(what & WITHSEL) encodeurltext(durl->selection,buf);
206
207}
208
209static char mustencode="";
210static char hexchars[16] = {
211        '0', '1', '2', '3',
212        '4', '5', '6', '7',
213        '8', '9', 'a', 'b',
214        'c', 'd', 'e', 'f',
215};
216
217static void
218encodeurltext(char* text, OCbytes* buf)
219{
220        /* Encode the URL to handle illegal characters */
221        len = strlen(url);
222        encoded = ocmalloc(len*4+1); /* should never be larger than this*/
223        if(encoded==NULL) return;
224        p = url; q = encoded;
225        while((c=*p++)) {
226                if(strchr(mustencode,c) != NULL) {
227                        char tmp[8];
228                        int hex1, hex2;
229                        hex1 = (c & 0x0F);
230                        hex2 = (c & 0xF0) >> 4;
231                        tmp[0] = '0'; tmp[1] = 'x';
232                        tmp[2] = hexchars[hex2]; tmp[3] = hexchars[hex1];
233                        tmp[4] = '\0';
234                        ocbytescat(buf,tmp);
235                } else *q++ = (char)c;
236        }
237
238}
239
240#endif
241
242/* hack for adding extra curl options via env variables */
243
244CURLcode curl_getenv_opt(CURL* curl) {
245        CURLcode cstat=CURLE_OK;
246        char *envVar;
247        long envVal;
248
249        if ((envVar=getenv("CURLOPT_SSLCERT"))!=NULL) {
250                cstat = curl_easy_setopt(curl,CURLOPT_SSLCERT,envVar);
251                if (cstat != CURLE_OK ) return cstat;
252        }
253        if ((envVar=getenv("CURLOPT_SSLKEY"))!=NULL) {
254                cstat = curl_easy_setopt(curl,CURLOPT_SSLKEY,envVar);
255                if (cstat != CURLE_OK ) return cstat;
256        }
257        if ((envVar=getenv("CURLOPT_CAINFO"))!=NULL) {
258                cstat = curl_easy_setopt(curl,CURLOPT_CAINFO,envVar);
259                if (cstat != CURLE_OK ) return cstat;
260        }
261        if ((envVar=getenv("CURLOPT_CAPATH"))!=NULL) {
262                cstat = curl_easy_setopt(curl,CURLOPT_CAPATH,envVar);
263                if (cstat != CURLE_OK ) return cstat;
264        }
265        if ((envVar=getenv("CURLOPT_COOKIEFILE"))!=NULL) {
266                cstat = curl_easy_setopt(curl,CURLOPT_COOKIEFILE,envVar);
267                if (cstat != CURLE_OK ) return cstat;
268        }
269        if ((envVar=getenv("CURLOPT_COOKIEJAR"))!=NULL) {
270                cstat = curl_easy_setopt(curl,CURLOPT_COOKIEJAR,envVar);
271                if (cstat != CURLE_OK ) return cstat;
272        }
273        if ((envVar=getenv("CURLOPT_VERBOSE"))!=NULL) {
274                if(sscanf(envVar,"%ld",&envVal)==1) {
275                        cstat = curl_easy_setopt(curl,CURLOPT_VERBOSE,envVal);
276                } else {
277                        cstat = CURLE_BAD_FUNCTION_ARGUMENT;
278                }
279                if (cstat != CURLE_OK ) return cstat;
280        }
281        if ((envVar=getenv("CURLOPT_FOLLOWLOCATION"))!=NULL) {
282                if(sscanf(envVar,"%ld",&envVal)==1) {
283                        cstat = curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,envVal);
284                } else {
285                        cstat = CURLE_BAD_FUNCTION_ARGUMENT;
286                }
287                if (cstat != CURLE_OK ) return cstat;
288        }
289        if ((envVar=getenv("CURLOPT_MAXREDIRS"))!=NULL) {
290                if(sscanf(envVar,"%ld",&envVal)==1) {
291                        cstat = curl_easy_setopt(curl,CURLOPT_MAXREDIRS,envVal);
292                } else {
293                        cstat = CURLE_BAD_FUNCTION_ARGUMENT;
294                }
295                if (cstat != CURLE_OK ) return cstat;
296        }
297}
298 
299/* end hack for adding extra curl options via env variables */
300
301int
302curlopen(CURL** curlp)
303{
304        int stat = OC_NOERR;
305        CURLcode cstat;
306        CURL* curl;
307        /* initialize curl*/
308        curl = curl_easy_init();
309        if (curl == NULL)
310                stat = OC_ECURL;
311        else {
312                cstat = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
313                if (cstat != CURLE_OK)
314                        stat = OC_ECURL;
315                /* some servers don't like requests that are made without a user-agent */
316                cstat = curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
317/* hack for adding extra curl options via env variables */
318                if (cstat == CURLE_OK) cstat=curl_getenv_opt(curl);
319/* end */
320
321                if (cstat != CURLE_OK)
322                        stat = OC_ECURL;
323               
324        }
325       
326        if (curlp)
327                *curlp = curl;
328        return THROW(stat);
329}
330
331void
332curlclose(CURL* curl)
333{
334        if (curl != NULL)
335                curl_easy_cleanup(curl);
336}
Note: See TracBrowser for help on using the repository browser.