1
+ /* vim: set sw=4 ts=4 sts=4 et : */
1
2
/********************************************************************\
2
3
* This program is free software; you can redistribute it and/or *
3
4
* modify it under the terms of the GNU General Public License as *
34
35
#include "../config.h"
35
36
#include "common.h"
36
37
#include "debug.h"
38
+ #include "pstring.h"
37
39
38
40
#ifdef USE_CYASSL
39
41
#include <cyassl/ssl.h>
48
50
static CYASSL_CTX * get_cyassl_ctx (void );
49
51
#endif
50
52
51
-
52
- int
53
- http_get (const int sockfd , char * buf ) {
54
-
53
+ /**
54
+ * Perform an HTTP request, caller frees both request and response,
55
+ * NULL returned on error.
56
+ * @param sockfd Socket to use, already connected
57
+ * @param req Request to send, fully formatted.
58
+ * @return char Response as a string
59
+ */
60
+ char *
61
+ http_get (const int sockfd , const char * req )
62
+ {
55
63
ssize_t numbytes ;
56
- size_t totalbytes ;
57
64
int done , nfds ;
58
65
fd_set readfds ;
59
66
struct timeval timeout ;
60
- size_t buflen = strlen (buf );
67
+ size_t reqlen = strlen (req );
68
+ char readbuf [MAX_BUF ];
69
+ char * retval ;
70
+ pstr_t * response = pstr_new ();
61
71
62
72
if (sockfd == -1 ) {
63
73
/* Could not connect to server */
64
74
debug (LOG_ERR , "Could not open socket to server!" );
65
- return -1 ;
75
+ goto error ;
66
76
}
67
77
68
- debug (LOG_DEBUG , "Sending HTTP request to auth server: [%s]\n" , buf );
69
- send (sockfd , buf , buflen , 0 );
70
-
71
- // Clear buffer and re-use for response
72
- memset (buf , 0 , buflen );
78
+ debug (LOG_DEBUG , "Sending HTTP request to auth server: [%s]\n" , req );
79
+ send (sockfd , req , reqlen , 0 );
73
80
74
81
debug (LOG_DEBUG , "Reading response" );
75
- totalbytes = 0 ;
76
82
done = 0 ;
77
83
do {
78
84
FD_ZERO (& readfds );
@@ -86,40 +92,40 @@ http_get(const int sockfd, char *buf) {
86
92
if (nfds > 0 ) {
87
93
/** We don't have to use FD_ISSET() because there
88
94
* was only one fd. */
89
- numbytes = read (sockfd , buf + totalbytes , MAX_BUF - (totalbytes + 1 ));
95
+ memset (readbuf , 0 , MAX_BUF );
96
+ numbytes = read (sockfd , readbuf , MAX_BUF - 1 );
90
97
if (numbytes < 0 ) {
91
98
debug (LOG_ERR , "An error occurred while reading from server: %s" , strerror (errno ));
92
- /* FIXME */
93
- close (sockfd );
94
- return -1 ;
99
+ goto error ;
95
100
}
96
101
else if (numbytes == 0 ) {
97
102
done = 1 ;
98
103
}
99
104
else {
100
- totalbytes += ( size_t ) numbytes ;
101
- debug (LOG_DEBUG , "Read %d bytes, total now %d " , numbytes , totalbytes );
105
+ pstr_cat ( response , readbuf ) ;
106
+ debug (LOG_DEBUG , "Read %d bytes" , numbytes );
102
107
}
103
108
}
104
109
else if (nfds == 0 ) {
105
110
debug (LOG_ERR , "Timed out reading data via select() from auth server" );
106
- /* FIXME */
107
- close (sockfd );
108
- return -1 ;
111
+ goto error ;
109
112
}
110
113
else if (nfds < 0 ) {
111
114
debug (LOG_ERR , "Error reading data via select() from auth server: %s" , strerror (errno ));
112
- /* FIXME */
113
- close (sockfd );
114
- return -1 ;
115
+ goto error ;
115
116
}
116
117
} while (!done );
117
118
118
119
close (sockfd );
119
-
120
- buf [totalbytes ] = '\0' ;
121
- debug (LOG_DEBUG , "HTTP Response from Server: [%s]" , buf );
122
- return totalbytes ;
120
+ retval = pstr_to_string (response );
121
+ debug (LOG_DEBUG , "HTTP Response from Server: [%s]" , retval );
122
+ return retval ;
123
+
124
+ error :
125
+ close (sockfd );
126
+ retval = pstr_to_string (response );
127
+ free (retval );
128
+ return NULL ;
123
129
}
124
130
125
131
@@ -198,38 +204,49 @@ get_cyassl_ctx(void)
198
204
}
199
205
200
206
201
- int
202
- https_get (const int sockfd , char * buf , const char * hostname ) {
203
-
207
+ /**
208
+ * Perform an HTTPS request, caller frees both request and response,
209
+ * NULL returned on error.
210
+ * @param sockfd Socket to use, already connected
211
+ * @param req Request to send, fully formatted.
212
+ * @param hostname Hostname to use in https request. Caller frees.
213
+ * @return char Response as a string
214
+ */
215
+ char *
216
+ https_get (const int sockfd , const char * req , const char * hostname )
217
+ {
204
218
ssize_t numbytes ;
205
- size_t totalbytes ;
206
219
int done , nfds ;
207
220
fd_set readfds ;
208
221
struct timeval timeout ;
209
222
unsigned long sslerr ;
210
223
char sslerrmsg [CYASSL_MAX_ERROR_SZ ];
211
- size_t buflen = strlen (buf );
224
+ size_t reqlen = strlen (req );
225
+ char readbuf [MAX_BUF ];
226
+ char * retval ;
227
+ pstr_t * response = pstr_new ();
228
+ CYASSL * ssl = NULL ;
229
+ CYASSL_CTX * ctx = NULL ;
212
230
213
231
s_config * config ;
214
232
config = config_get_config ();
215
233
216
- CYASSL_CTX * ctx = get_cyassl_ctx ();
234
+ ctx = get_cyassl_ctx ();
217
235
if (NULL == ctx ) {
218
236
debug (LOG_ERR , "Could not get CyaSSL Context!" );
219
- return -1 ;
237
+ goto error ;
220
238
}
221
239
222
240
if (sockfd == -1 ) {
223
241
/* Could not connect to server */
224
242
debug (LOG_ERR , "Could not open socket to server!" );
225
- return -1 ;
243
+ goto error ;
226
244
}
227
245
228
246
/* Create CYASSL object */
229
- CYASSL * ssl ;
230
247
if ( (ssl = CyaSSL_new (ctx )) == NULL ) {
231
248
debug (LOG_ERR , "Could not create CyaSSL context." );
232
- return -1 ;
249
+ goto error ;
233
250
}
234
251
if (config -> ssl_verify ) {
235
252
// Turn on domain name check
@@ -240,25 +257,21 @@ https_get(const int sockfd, char *buf, const char* hostname) {
240
257
CyaSSL_set_fd (ssl , sockfd );
241
258
242
259
243
- debug (LOG_DEBUG , "Sending HTTPS request to auth server: [%s]\n" , buf );
244
- numbytes = CyaSSL_send (ssl , buf , (int ) buflen , 0 );
260
+ debug (LOG_DEBUG , "Sending HTTPS request to auth server: [%s]\n" , req );
261
+ numbytes = CyaSSL_send (ssl , req , (int ) reqlen , 0 );
245
262
if (numbytes <= 0 ) {
246
263
sslerr = (unsigned long ) CyaSSL_get_error (ssl , numbytes );
247
264
CyaSSL_ERR_error_string (sslerr , sslerrmsg );
248
265
debug (LOG_ERR , "CyaSSL_send failed: %s" , sslerrmsg );
249
- return -1 ;
266
+ goto error ;
250
267
}
251
- else if (numbytes != ( int ) buflen ) {
268
+ else if (( size_t ) numbytes != reqlen ) {
252
269
debug (LOG_ERR , "CyaSSL_send failed: only %d bytes out of %d bytes sent!" ,
253
- numbytes , buflen );
254
- return -1 ;
270
+ numbytes , reqlen );
271
+ goto error ;
255
272
}
256
273
257
- // Clear buffer and re-use for response
258
- memset (buf , 0 , buflen );
259
-
260
274
debug (LOG_DEBUG , "Reading response" );
261
- totalbytes = 0 ;
262
275
done = 0 ;
263
276
do {
264
277
FD_ZERO (& readfds );
@@ -272,47 +285,50 @@ https_get(const int sockfd, char *buf, const char* hostname) {
272
285
if (nfds > 0 ) {
273
286
/** We don't have to use FD_ISSET() because there
274
287
* was only one fd. */
275
- numbytes = CyaSSL_read (ssl , buf + totalbytes , MAX_BUF - (totalbytes + 1 ));
288
+ memset (readbuf , 0 , MAX_BUF );
289
+ numbytes = CyaSSL_read (ssl , readbuf , MAX_BUF - 1 );
276
290
if (numbytes < 0 ) {
277
291
sslerr = (unsigned long ) CyaSSL_get_error (ssl , numbytes );
278
292
CyaSSL_ERR_error_string (sslerr , sslerrmsg );
279
293
debug (LOG_ERR , "An error occurred while reading from server: %s" , sslerrmsg );
280
- /* FIXME */
281
- close (sockfd );
282
- return -1 ;
294
+ goto error ;
283
295
}
284
296
else if (numbytes == 0 ) {
285
297
/* CyaSSL_read returns 0 on a clean shutdown or if the peer closed the
286
298
connection. We can't distinguish between these cases right now. */
287
299
done = 1 ;
288
300
}
289
301
else {
290
- totalbytes += ( size_t ) numbytes ;
291
- debug (LOG_DEBUG , "Read %d bytes, total now %d " , numbytes , totalbytes );
302
+ pstr_cat ( response , readbuf ) ;
303
+ debug (LOG_DEBUG , "Read %d bytes" , numbytes );
292
304
}
293
305
}
294
306
else if (nfds == 0 ) {
295
307
debug (LOG_ERR , "Timed out reading data via select() from auth server" );
296
- /* FIXME */
297
- close (sockfd );
298
- return -1 ;
308
+ goto error ;
299
309
}
300
310
else if (nfds < 0 ) {
301
311
debug (LOG_ERR , "Error reading data via select() from auth server: %s" , strerror (errno ));
302
- /* FIXME */
303
- close (sockfd );
304
- return -1 ;
312
+ goto error ;
305
313
}
306
314
} while (!done );
307
315
308
316
close (sockfd );
309
317
310
- buf [totalbytes ] = '\0' ;
311
- debug (LOG_DEBUG , "HTTP Response from Server: [%s]" , buf );
312
-
313
318
CyaSSL_free (ssl );
314
319
315
- return totalbytes ;
320
+ retval = pstr_to_string (response );
321
+ debug (LOG_DEBUG , "HTTPS Response from Server: [%s]" , retval );
322
+ return retval ;
323
+
324
+ error :
325
+ if (ssl ) {
326
+ CyaSSL_free (ssl );
327
+ }
328
+ close (sockfd );
329
+ retval = pstr_to_string (response );
330
+ free (retval );
331
+ return NULL ;
316
332
}
317
333
318
334
0 commit comments