pluto and scepclient use the curl and ldap fetcher plugins
[strongswan.git] / src / libstrongswan / plugins / curl / curl_fetcher.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <curl/curl.h>
20
21 #include <library.h>
22 #include <debug.h>
23
24 #include "curl_fetcher.h"
25
26 #define DEFAULT_TIMEOUT 10
27
28 typedef struct private_curl_fetcher_t private_curl_fetcher_t;
29
30 /**
31 * private data of a curl_fetcher_t object.
32 */
33 struct private_curl_fetcher_t {
34 /**
35 * Public data
36 */
37 curl_fetcher_t public;
38
39 /**
40 * CURL handle
41 */
42 CURL* curl;
43
44 /**
45 * Optional HTTP headers
46 */
47 struct curl_slist *headers;
48 };
49
50 /**
51 * writes data into a dynamically resizeable chunk_t
52 */
53 static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data)
54 {
55 size_t realsize = size * nmemb;
56
57 data->ptr = (u_char*)realloc(data->ptr, data->len + realsize);
58 if (data->ptr)
59 {
60 memcpy(&data->ptr[data->len], ptr, realsize);
61 data->len += realsize;
62 }
63 return realsize;
64 }
65
66 /**
67 * Implements fetcher_t.fetch.
68 */
69 static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result)
70 {
71 char error[CURL_ERROR_SIZE];
72 char buf[256];
73 status_t status;
74
75 *result = chunk_empty;
76
77 if (curl_easy_setopt(this->curl, CURLOPT_URL, uri) != CURLE_OK)
78 { /* URL type not supported by curl */
79 return NOT_SUPPORTED;
80 }
81 curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error);
82 curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
83 curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
84 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT);
85 curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)append);
86 curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void*)result);
87 if (this->headers)
88 {
89 curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, this->headers);
90 }
91
92 DBG2(" sending http request to '%s'...", uri);
93 switch (curl_easy_perform(this->curl))
94 {
95 case CURLE_UNSUPPORTED_PROTOCOL:
96 status = NOT_SUPPORTED;
97 break;
98 case CURLE_OK:
99 status = SUCCESS;
100 break;
101 default:
102 DBG1("libcurl http request failed: %s", error);
103 status = FAILED;
104 break;
105 }
106 return status;
107 }
108
109 /**
110 * Implementation of fetcher_t.set_option.
111 */
112 static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, ...)
113 {
114 va_list args;
115
116 va_start(args, option);
117 switch (option)
118 {
119 case FETCH_REQUEST_DATA:
120 {
121 chunk_t data = va_arg(args, chunk_t);
122
123 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, (char*)data.ptr);
124 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len);
125 return TRUE;
126 }
127 case FETCH_REQUEST_TYPE:
128 {
129 char header[BUF_LEN];
130 char *request_type = va_arg(args, char*);
131
132 snprintf(header, BUF_LEN, "Content-Type: %s", request_type);
133 this->headers = curl_slist_append(this->headers, header);
134 return TRUE;
135 }
136 case FETCH_REQUEST_HEADER:
137 {
138 char *header = va_arg(args, char*);
139
140 this->headers = curl_slist_append(this->headers, header);
141 return TRUE;
142 }
143 case FETCH_HTTP_VERSION_1_0:
144 {
145 curl_easy_setopt(this->curl, CURLOPT_HTTP_VERSION,
146 CURL_HTTP_VERSION_1_0);
147 return TRUE;
148 }
149 case FETCH_TIMEOUT:
150 {
151 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT,
152 va_arg(args, u_int));
153 return TRUE;
154 }
155 default:
156 return FALSE;
157 }
158 }
159
160 /**
161 * Implements fetcher_t.destroy
162 */
163 static void destroy(private_curl_fetcher_t *this)
164 {
165 curl_slist_free_all(this->headers);
166 curl_easy_cleanup(this->curl);
167 free(this);
168 }
169
170 /*
171 * Described in header.
172 */
173 curl_fetcher_t *curl_fetcher_create()
174 {
175 private_curl_fetcher_t *this = malloc_thing(private_curl_fetcher_t);
176
177 this->curl = curl_easy_init();
178 if (this->curl == NULL)
179 {
180 free(this);
181 return NULL;
182 }
183 this->headers = NULL;
184
185 this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch;
186 this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option;
187 this->public.interface.destroy = (void (*)(fetcher_t*))destroy;
188
189 return &this->public;
190 }
191