extensions/curl/curl-src/docs/libcurl/libcurl-tutorial.3
author Asher Baker <asherkin@gmail.com>
Sun Mar 17 22:23:20 2013 +0000 (2013-03-17)
changeset 3839 05c359144594
parent 2518 5d227a11b850
child 3842 04ca50d3cb60
permissions -rw-r--r--
Updated cURL version.
dvander@2518
     1
.\" **************************************************************************
dvander@2518
     2
.\" *                                  _   _ ____  _
dvander@2518
     3
.\" *  Project                     ___| | | |  _ \| |
dvander@2518
     4
.\" *                             / __| | | | |_) | |
dvander@2518
     5
.\" *                            | (__| |_| |  _ <| |___
dvander@2518
     6
.\" *                             \___|\___/|_| \_\_____|
dvander@2518
     7
.\" *
asherkin@3839
     8
.\" * Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, et al.
dvander@2518
     9
.\" *
dvander@2518
    10
.\" * This software is licensed as described in the file COPYING, which
dvander@2518
    11
.\" * you should have received as part of this distribution. The terms
dvander@2518
    12
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
dvander@2518
    13
.\" *
dvander@2518
    14
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
dvander@2518
    15
.\" * copies of the Software, and permit persons to whom the Software is
dvander@2518
    16
.\" * furnished to do so, under the terms of the COPYING file.
dvander@2518
    17
.\" *
dvander@2518
    18
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
dvander@2518
    19
.\" * KIND, either express or implied.
dvander@2518
    20
.\" *
dvander@2518
    21
.\" **************************************************************************
dvander@2518
    22
.\"
asherkin@3839
    23
.TH libcurl-tutorial 3 "4 Mar 2009" "libcurl" "libcurl programming"
dvander@2518
    24
.SH NAME
dvander@2518
    25
libcurl-tutorial \- libcurl programming tutorial
dvander@2518
    26
.SH "Objective"
dvander@2518
    27
This document attempts to describe the general principles and some basic
dvander@2518
    28
approaches to consider when programming with libcurl. The text will focus
dvander@2518
    29
mainly on the C interface but might apply fairly well on other interfaces as
dvander@2518
    30
well as they usually follow the C one pretty closely.
dvander@2518
    31
dvander@2518
    32
This document will refer to 'the user' as the person writing the source code
dvander@2518
    33
that uses libcurl. That would probably be you or someone in your position.
dvander@2518
    34
What will be generally referred to as 'the program' will be the collected
dvander@2518
    35
source code that you write that is using libcurl for transfers. The program
dvander@2518
    36
is outside libcurl and libcurl is outside of the program.
dvander@2518
    37
asherkin@3839
    38
To get more details on all options and functions described herein, please
dvander@2518
    39
refer to their respective man pages.
dvander@2518
    40
dvander@2518
    41
.SH "Building"
dvander@2518
    42
There are many different ways to build C programs. This chapter will assume a
asherkin@3839
    43
UNIX-style build process. If you use a different build system, you can still
dvander@2518
    44
read this to get general information that may apply to your environment as
dvander@2518
    45
well.
dvander@2518
    46
.IP "Compiling the Program"
dvander@2518
    47
Your compiler needs to know where the libcurl headers are located. Therefore
dvander@2518
    48
you must set your compiler's include path to point to the directory where you
dvander@2518
    49
installed them. The 'curl-config'[3] tool can be used to get this information:
dvander@2518
    50
dvander@2518
    51
$ curl-config --cflags
dvander@2518
    52
dvander@2518
    53
.IP "Linking the Program with libcurl"
dvander@2518
    54
When having compiled the program, you need to link your object files to create
dvander@2518
    55
a single executable. For that to succeed, you need to link with libcurl and
dvander@2518
    56
possibly also with other libraries that libcurl itself depends on. Like the
dvander@2518
    57
OpenSSL libraries, but even some standard OS libraries may be needed on the
dvander@2518
    58
command line. To figure out which flags to use, once again the 'curl-config'
dvander@2518
    59
tool comes to the rescue:
dvander@2518
    60
dvander@2518
    61
$ curl-config --libs
dvander@2518
    62
dvander@2518
    63
.IP "SSL or Not"
dvander@2518
    64
libcurl can be built and customized in many ways. One of the things that
dvander@2518
    65
varies from different libraries and builds is the support for SSL-based
dvander@2518
    66
transfers, like HTTPS and FTPS. If a supported SSL library was detected
dvander@2518
    67
properly at build-time, libcurl will be built with SSL support. To figure out
dvander@2518
    68
if an installed libcurl has been built with SSL support enabled, use
dvander@2518
    69
\&'curl-config' like this:
dvander@2518
    70
dvander@2518
    71
$ curl-config --feature
dvander@2518
    72
dvander@2518
    73
And if SSL is supported, the keyword 'SSL' will be written to stdout,
asherkin@3839
    74
possibly together with a few other features that could be either on or off on
asherkin@3839
    75
for different libcurls.
dvander@2518
    76
dvander@2518
    77
See also the "Features libcurl Provides" further down.
dvander@2518
    78
.IP "autoconf macro"
dvander@2518
    79
When you write your configure script to detect libcurl and setup variables
dvander@2518
    80
accordingly, we offer a prewritten macro that probably does everything you
dvander@2518
    81
need in this area. See docs/libcurl/libcurl.m4 file - it includes docs on how
dvander@2518
    82
to use it.
dvander@2518
    83
dvander@2518
    84
.SH "Portable Code in a Portable World"
dvander@2518
    85
The people behind libcurl have put a considerable effort to make libcurl work
dvander@2518
    86
on a large amount of different operating systems and environments.
dvander@2518
    87
dvander@2518
    88
You program libcurl the same way on all platforms that libcurl runs on. There
asherkin@3839
    89
are only very few minor considerations that differ. If you just make sure to
dvander@2518
    90
write your code portable enough, you may very well create yourself a very
dvander@2518
    91
portable program. libcurl shouldn't stop you from that.
dvander@2518
    92
dvander@2518
    93
.SH "Global Preparation"
dvander@2518
    94
The program must initialize some of the libcurl functionality globally. That
dvander@2518
    95
means it should be done exactly once, no matter how many times you intend to
dvander@2518
    96
use the library. Once for your program's entire life time. This is done using
dvander@2518
    97
dvander@2518
    98
 curl_global_init()
dvander@2518
    99
dvander@2518
   100
and it takes one parameter which is a bit pattern that tells libcurl what to
dvander@2518
   101
initialize. Using \fICURL_GLOBAL_ALL\fP will make it initialize all known
dvander@2518
   102
internal sub modules, and might be a good default option. The current two bits
dvander@2518
   103
that are specified are:
dvander@2518
   104
.RS
dvander@2518
   105
.IP "CURL_GLOBAL_WIN32"
dvander@2518
   106
which only does anything on Windows machines. When used on
dvander@2518
   107
a Windows machine, it'll make libcurl initialize the win32 socket
dvander@2518
   108
stuff. Without having that initialized properly, your program cannot use
dvander@2518
   109
sockets properly. You should only do this once for each application, so if
dvander@2518
   110
your program already does this or of another library in use does it, you
dvander@2518
   111
should not tell libcurl to do this as well.
dvander@2518
   112
.IP CURL_GLOBAL_SSL
dvander@2518
   113
which only does anything on libcurls compiled and built SSL-enabled. On these
dvander@2518
   114
systems, this will make libcurl initialize the SSL library properly for this
asherkin@3839
   115
application. This only needs to be done once for each application so if your
dvander@2518
   116
program or another library already does this, this bit should not be needed.
dvander@2518
   117
.RE
dvander@2518
   118
dvander@2518
   119
libcurl has a default protection mechanism that detects if
dvander@2518
   120
\fIcurl_global_init(3)\fP hasn't been called by the time
dvander@2518
   121
\fIcurl_easy_perform(3)\fP is called and if that is the case, libcurl runs the
dvander@2518
   122
function itself with a guessed bit pattern. Please note that depending solely
dvander@2518
   123
on this is not considered nice nor very good.
dvander@2518
   124
dvander@2518
   125
When the program no longer uses libcurl, it should call
dvander@2518
   126
\fIcurl_global_cleanup(3)\fP, which is the opposite of the init call. It will
dvander@2518
   127
then do the reversed operations to cleanup the resources the
dvander@2518
   128
\fIcurl_global_init(3)\fP call initialized.
dvander@2518
   129
dvander@2518
   130
Repeated calls to \fIcurl_global_init(3)\fP and \fIcurl_global_cleanup(3)\fP
dvander@2518
   131
should be avoided. They should only be called once each.
dvander@2518
   132
dvander@2518
   133
.SH "Features libcurl Provides"
dvander@2518
   134
It is considered best-practice to determine libcurl features at run-time
dvander@2518
   135
rather than at build-time (if possible of course). By calling
dvander@2518
   136
\fIcurl_version_info(3)\fP and checking out the details of the returned
dvander@2518
   137
struct, your program can figure out exactly what the currently running libcurl
dvander@2518
   138
supports.
dvander@2518
   139
dvander@2518
   140
.SH "Handle the Easy libcurl"
dvander@2518
   141
libcurl first introduced the so called easy interface. All operations in the
dvander@2518
   142
easy interface are prefixed with 'curl_easy'.
dvander@2518
   143
dvander@2518
   144
Recent libcurl versions also offer the multi interface. More about that
dvander@2518
   145
interface, what it is targeted for and how to use it is detailed in a separate
dvander@2518
   146
chapter further down. You still need to understand the easy interface first,
dvander@2518
   147
so please continue reading for better understanding.
dvander@2518
   148
dvander@2518
   149
To use the easy interface, you must first create yourself an easy handle. You
dvander@2518
   150
need one handle for each easy session you want to perform. Basically, you
dvander@2518
   151
should use one handle for every thread you plan to use for transferring. You
dvander@2518
   152
must never share the same handle in multiple threads.
dvander@2518
   153
dvander@2518
   154
Get an easy handle with
dvander@2518
   155
dvander@2518
   156
 easyhandle = curl_easy_init();
dvander@2518
   157
dvander@2518
   158
It returns an easy handle. Using that you proceed to the next step: setting
dvander@2518
   159
up your preferred actions. A handle is just a logic entity for the upcoming
dvander@2518
   160
transfer or series of transfers.
dvander@2518
   161
dvander@2518
   162
You set properties and options for this handle using
dvander@2518
   163
\fIcurl_easy_setopt(3)\fP. They control how the subsequent transfer or
dvander@2518
   164
transfers will be made. Options remain set in the handle until set again to
dvander@2518
   165
something different. Alas, multiple requests using the same handle will use
dvander@2518
   166
the same options.
dvander@2518
   167
dvander@2518
   168
Many of the options you set in libcurl are "strings", pointers to data
asherkin@3839
   169
terminated with a zero byte. When you set strings with
asherkin@3839
   170
\fIcurl_easy_setopt(3)\fP, libcurl makes its own copy so that they don't
asherkin@3839
   171
need to be kept around in your application after being set[4].
dvander@2518
   172
dvander@2518
   173
One of the most basic properties to set in the handle is the URL. You set
dvander@2518
   174
your preferred URL to transfer with CURLOPT_URL in a manner similar to:
dvander@2518
   175
dvander@2518
   176
.nf
dvander@2518
   177
 curl_easy_setopt(handle, CURLOPT_URL, "http://domain.com/");
dvander@2518
   178
.fi
dvander@2518
   179
dvander@2518
   180
Let's assume for a while that you want to receive data as the URL identifies a
dvander@2518
   181
remote resource you want to get here. Since you write a sort of application
dvander@2518
   182
that needs this transfer, I assume that you would like to get the data passed
dvander@2518
   183
to you directly instead of simply getting it passed to stdout. So, you write
dvander@2518
   184
your own function that matches this prototype:
dvander@2518
   185
dvander@2518
   186
 size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
dvander@2518
   187
dvander@2518
   188
You tell libcurl to pass all data to this function by issuing a function
dvander@2518
   189
similar to this:
dvander@2518
   190
dvander@2518
   191
 curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
dvander@2518
   192
asherkin@3839
   193
You can control what data your callback function gets in the fourth argument
asherkin@3839
   194
by setting another property:
dvander@2518
   195
dvander@2518
   196
 curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &internal_struct);
dvander@2518
   197
dvander@2518
   198
Using that property, you can easily pass local data between your application
dvander@2518
   199
and the function that gets invoked by libcurl. libcurl itself won't touch the
dvander@2518
   200
data you pass with \fICURLOPT_WRITEDATA\fP.
dvander@2518
   201
asherkin@3839
   202
libcurl offers its own default internal callback that will take care of the data
dvander@2518
   203
if you don't set the callback with \fICURLOPT_WRITEFUNCTION\fP. It will then
dvander@2518
   204
simply output the received data to stdout. You can have the default callback
dvander@2518
   205
write the data to a different file handle by passing a 'FILE *' to a file
dvander@2518
   206
opened for writing with the \fICURLOPT_WRITEDATA\fP option.
dvander@2518
   207
dvander@2518
   208
Now, we need to take a step back and have a deep breath. Here's one of those
dvander@2518
   209
rare platform-dependent nitpicks. Did you spot it? On some platforms[2],
dvander@2518
   210
libcurl won't be able to operate on files opened by the program. Thus, if you
dvander@2518
   211
use the default callback and pass in an open file with
dvander@2518
   212
\fICURLOPT_WRITEDATA\fP, it will crash. You should therefore avoid this to
dvander@2518
   213
make your program run fine virtually everywhere.
dvander@2518
   214
dvander@2518
   215
(\fICURLOPT_WRITEDATA\fP was formerly known as \fICURLOPT_FILE\fP. Both names
dvander@2518
   216
still work and do the same thing).
dvander@2518
   217
dvander@2518
   218
If you're using libcurl as a win32 DLL, you MUST use the
dvander@2518
   219
\fICURLOPT_WRITEFUNCTION\fP if you set \fICURLOPT_WRITEDATA\fP - or you will
dvander@2518
   220
experience crashes.
dvander@2518
   221
dvander@2518
   222
There are of course many more options you can set, and we'll get back to a few
dvander@2518
   223
of them later. Let's instead continue to the actual transfer:
dvander@2518
   224
dvander@2518
   225
 success = curl_easy_perform(easyhandle);
dvander@2518
   226
dvander@2518
   227
\fIcurl_easy_perform(3)\fP will connect to the remote site, do the necessary
dvander@2518
   228
commands and receive the transfer. Whenever it receives data, it calls the
dvander@2518
   229
callback function we previously set. The function may get one byte at a time,
dvander@2518
   230
or it may get many kilobytes at once. libcurl delivers as much as possible as
dvander@2518
   231
often as possible. Your callback function should return the number of bytes it
dvander@2518
   232
\&"took care of". If that is not the exact same amount of bytes that was
dvander@2518
   233
passed to it, libcurl will abort the operation and return with an error code.
dvander@2518
   234
dvander@2518
   235
When the transfer is complete, the function returns a return code that informs
dvander@2518
   236
you if it succeeded in its mission or not. If a return code isn't enough for
dvander@2518
   237
you, you can use the CURLOPT_ERRORBUFFER to point libcurl to a buffer of yours
dvander@2518
   238
where it'll store a human readable error message as well.
dvander@2518
   239
dvander@2518
   240
If you then want to transfer another file, the handle is ready to be used
dvander@2518
   241
again. Mind you, it is even preferred that you re-use an existing handle if
dvander@2518
   242
you intend to make another transfer. libcurl will then attempt to re-use the
dvander@2518
   243
previous connection.
dvander@2518
   244
asherkin@3839
   245
For some protocols, downloading a file can involve a complicated process of
asherkin@3839
   246
logging in, setting the transfer mode, changing the current directory and
asherkin@3839
   247
finally transferring the file data. libcurl takes care of all that
asherkin@3839
   248
complication for you. Given simply the URL to a file, libcurl will take care
asherkin@3839
   249
of all the details needed to get the file moved from one machine to another.
asherkin@3839
   250
dvander@2518
   251
.SH "Multi-threading Issues"
asherkin@3839
   252
The first basic rule is that you must \fBnever\fP simultaneously share a
asherkin@3839
   253
libcurl handle (be it easy or multi or whatever) between multiple
asherkin@3839
   254
threads. Only use one handle in one thread at any time. You can pass the
asherkin@3839
   255
handles around among threads, but you must never use a single handle from more
asherkin@3839
   256
than one thread at any given time.
dvander@2518
   257
dvander@2518
   258
libcurl is completely thread safe, except for two issues: signals and SSL/TLS
asherkin@3839
   259
handlers. Signals are used for timing out name resolves (during DNS lookup) -
asherkin@3839
   260
when built without c-ares support and not on Windows.
dvander@2518
   261
dvander@2518
   262
If you are accessing HTTPS or FTPS URLs in a multi-threaded manner, you are
dvander@2518
   263
then of course using the underlying SSL library multi-threaded and those libs
dvander@2518
   264
might have their own requirements on this issue. Basically, you need to
dvander@2518
   265
provide one or two functions to allow it to function properly. For all
dvander@2518
   266
details, see this:
dvander@2518
   267
dvander@2518
   268
OpenSSL
dvander@2518
   269
dvander@2518
   270
 http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
dvander@2518
   271
dvander@2518
   272
GnuTLS
dvander@2518
   273
dvander@2518
   274
 http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html
dvander@2518
   275
dvander@2518
   276
NSS
asherkin@3839
   277
asherkin@3839
   278
 is claimed to be thread-safe already without anything required.
asherkin@3839
   279
asherkin@3839
   280
PolarSSL
asherkin@3839
   281
asherkin@3839
   282
 Required actions unknown.
dvander@2518
   283
dvander@2518
   284
yassl
dvander@2518
   285
asherkin@3839
   286
 Required actions unknown.
asherkin@3839
   287
asherkin@3839
   288
axTLS
asherkin@3839
   289
asherkin@3839
   290
 Required actions unknown.
dvander@2518
   291
dvander@2518
   292
When using multiple threads you should set the CURLOPT_NOSIGNAL option to 1
dvander@2518
   293
for all handles. Everything will or might work fine except that timeouts are
dvander@2518
   294
not honored during the DNS lookup - which you can work around by building
dvander@2518
   295
libcurl with c-ares support. c-ares is a library that provides asynchronous
asherkin@3839
   296
name resolves. On some platforms, libcurl simply will not function properly
asherkin@3839
   297
multi-threaded unless this option is set.
dvander@2518
   298
dvander@2518
   299
Also, note that CURLOPT_DNS_USE_GLOBAL_CACHE is not thread-safe.
dvander@2518
   300
dvander@2518
   301
.SH "When It Doesn't Work"
dvander@2518
   302
There will always be times when the transfer fails for some reason. You might
dvander@2518
   303
have set the wrong libcurl option or misunderstood what the libcurl option
dvander@2518
   304
actually does, or the remote server might return non-standard replies that
dvander@2518
   305
confuse the library which then confuses your program.
dvander@2518
   306
dvander@2518
   307
There's one golden rule when these things occur: set the CURLOPT_VERBOSE
dvander@2518
   308
option to 1. It'll cause the library to spew out the entire protocol
dvander@2518
   309
details it sends, some internal info and some received protocol data as well
dvander@2518
   310
(especially when using FTP). If you're using HTTP, adding the headers in the
dvander@2518
   311
received output to study is also a clever way to get a better understanding
dvander@2518
   312
why the server behaves the way it does. Include headers in the normal body
dvander@2518
   313
output with CURLOPT_HEADER set 1.
dvander@2518
   314
asherkin@3839
   315
Of course, there are bugs left. We need to know about them to be able
dvander@2518
   316
to fix them, so we're quite dependent on your bug reports! When you do report
asherkin@3839
   317
suspected bugs in libcurl, please include as many details as you possibly can: a
dvander@2518
   318
protocol dump that CURLOPT_VERBOSE produces, library version, as much as
dvander@2518
   319
possible of your code that uses libcurl, operating system name and version,
dvander@2518
   320
compiler name and version etc.
dvander@2518
   321
dvander@2518
   322
If CURLOPT_VERBOSE is not enough, you increase the level of debug data your
dvander@2518
   323
application receive by using the CURLOPT_DEBUGFUNCTION.
dvander@2518
   324
dvander@2518
   325
Getting some in-depth knowledge about the protocols involved is never wrong,
dvander@2518
   326
and if you're trying to do funny things, you might very well understand
dvander@2518
   327
libcurl and how to use it better if you study the appropriate RFC documents
dvander@2518
   328
at least briefly.
dvander@2518
   329
dvander@2518
   330
.SH "Upload Data to a Remote Site"
dvander@2518
   331
libcurl tries to keep a protocol independent approach to most transfers, thus
dvander@2518
   332
uploading to a remote FTP site is very similar to uploading data to a HTTP
dvander@2518
   333
server with a PUT request.
dvander@2518
   334
dvander@2518
   335
Of course, first you either create an easy handle or you re-use one existing
dvander@2518
   336
one. Then you set the URL to operate on just like before. This is the remote
dvander@2518
   337
URL, that we now will upload.
dvander@2518
   338
dvander@2518
   339
Since we write an application, we most likely want libcurl to get the upload
dvander@2518
   340
data by asking us for it. To make it do that, we set the read callback and
dvander@2518
   341
the custom pointer libcurl will pass to our read callback. The read callback
dvander@2518
   342
should have a prototype similar to:
dvander@2518
   343
dvander@2518
   344
 size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
dvander@2518
   345
dvander@2518
   346
Where bufptr is the pointer to a buffer we fill in with data to upload and
dvander@2518
   347
size*nitems is the size of the buffer and therefore also the maximum amount
dvander@2518
   348
of data we can return to libcurl in this call. The 'userp' pointer is the
dvander@2518
   349
custom pointer we set to point to a struct of ours to pass private data
dvander@2518
   350
between the application and the callback.
dvander@2518
   351
dvander@2518
   352
 curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_function);
dvander@2518
   353
dvander@2518
   354
 curl_easy_setopt(easyhandle, CURLOPT_READDATA, &filedata);
dvander@2518
   355
dvander@2518
   356
Tell libcurl that we want to upload:
dvander@2518
   357
dvander@2518
   358
 curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, 1L);
dvander@2518
   359
dvander@2518
   360
A few protocols won't behave properly when uploads are done without any prior
dvander@2518
   361
knowledge of the expected file size. So, set the upload file size using the
dvander@2518
   362
CURLOPT_INFILESIZE_LARGE for all known file sizes like this[1]:
dvander@2518
   363
dvander@2518
   364
.nf
asherkin@3839
   365
 /* in this example, file_size must be an curl_off_t variable */
dvander@2518
   366
 curl_easy_setopt(easyhandle, CURLOPT_INFILESIZE_LARGE, file_size);
dvander@2518
   367
.fi
dvander@2518
   368
dvander@2518
   369
When you call \fIcurl_easy_perform(3)\fP this time, it'll perform all the
dvander@2518
   370
necessary operations and when it has invoked the upload it'll call your
dvander@2518
   371
supplied callback to get the data to upload. The program should return as much
dvander@2518
   372
data as possible in every invoke, as that is likely to make the upload perform
dvander@2518
   373
as fast as possible. The callback should return the number of bytes it wrote
dvander@2518
   374
in the buffer. Returning 0 will signal the end of the upload.
dvander@2518
   375
dvander@2518
   376
.SH "Passwords"
dvander@2518
   377
Many protocols use or even require that user name and password are provided
dvander@2518
   378
to be able to download or upload the data of your choice. libcurl offers
dvander@2518
   379
several ways to specify them.
dvander@2518
   380
dvander@2518
   381
Most protocols support that you specify the name and password in the URL
dvander@2518
   382
itself. libcurl will detect this and use them accordingly. This is written
dvander@2518
   383
like this:
dvander@2518
   384
dvander@2518
   385
 protocol://user:[email protected]/path/
dvander@2518
   386
dvander@2518
   387
If you need any odd letters in your user name or password, you should enter
dvander@2518
   388
them URL encoded, as %XX where XX is a two-digit hexadecimal number.
dvander@2518
   389
dvander@2518
   390
libcurl also provides options to set various passwords. The user name and
dvander@2518
   391
password as shown embedded in the URL can instead get set with the
dvander@2518
   392
CURLOPT_USERPWD option. The argument passed to libcurl should be a char * to
asherkin@3839
   393
a string in the format "user:password". In a manner like this:
dvander@2518
   394
dvander@2518
   395
 curl_easy_setopt(easyhandle, CURLOPT_USERPWD, "myname:thesecret");
dvander@2518
   396
dvander@2518
   397
Another case where name and password might be needed at times, is for those
dvander@2518
   398
users who need to authenticate themselves to a proxy they use. libcurl offers
dvander@2518
   399
another option for this, the CURLOPT_PROXYUSERPWD. It is used quite similar
dvander@2518
   400
to the CURLOPT_USERPWD option like this:
dvander@2518
   401
dvander@2518
   402
 curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
asherkin@3839
   403
asherkin@3839
   404
There's a long time UNIX "standard" way of storing ftp user names and
dvander@2518
   405
passwords, namely in the $HOME/.netrc file. The file should be made private
dvander@2518
   406
so that only the user may read it (see also the "Security Considerations"
dvander@2518
   407
chapter), as it might contain the password in plain text. libcurl has the
dvander@2518
   408
ability to use this file to figure out what set of user name and password to
dvander@2518
   409
use for a particular host. As an extension to the normal functionality,
dvander@2518
   410
libcurl also supports this file for non-FTP protocols such as HTTP. To make
dvander@2518
   411
curl use this file, use the CURLOPT_NETRC option:
dvander@2518
   412
dvander@2518
   413
 curl_easy_setopt(easyhandle, CURLOPT_NETRC, 1L);
dvander@2518
   414
dvander@2518
   415
And a very basic example of how such a .netrc file may look like:
dvander@2518
   416
dvander@2518
   417
.nf
dvander@2518
   418
 machine myhost.mydomain.com
dvander@2518
   419
 login userlogin
dvander@2518
   420
 password secretword
dvander@2518
   421
.fi
dvander@2518
   422
dvander@2518
   423
All these examples have been cases where the password has been optional, or
dvander@2518
   424
at least you could leave it out and have libcurl attempt to do its job
dvander@2518
   425
without it. There are times when the password isn't optional, like when
dvander@2518
   426
you're using an SSL private key for secure transfers.
dvander@2518
   427
dvander@2518
   428
To pass the known private key password to libcurl:
dvander@2518
   429
dvander@2518
   430
 curl_easy_setopt(easyhandle, CURLOPT_KEYPASSWD, "keypassword");
dvander@2518
   431
dvander@2518
   432
.SH "HTTP Authentication"
dvander@2518
   433
The previous chapter showed how to set user name and password for getting
dvander@2518
   434
URLs that require authentication. When using the HTTP protocol, there are
dvander@2518
   435
many different ways a client can provide those credentials to the server and
asherkin@3839
   436
you can control which way libcurl will (attempt to) use them. The default HTTP
dvander@2518
   437
authentication method is called 'Basic', which is sending the name and
dvander@2518
   438
password in clear-text in the HTTP request, base64-encoded. This is insecure.
dvander@2518
   439
asherkin@3839
   440
At the time of this writing, libcurl can be built to use: Basic, Digest, NTLM,
dvander@2518
   441
Negotiate, GSS-Negotiate and SPNEGO. You can tell libcurl which one to use
dvander@2518
   442
with CURLOPT_HTTPAUTH as in:
dvander@2518
   443
dvander@2518
   444
 curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
dvander@2518
   445
dvander@2518
   446
And when you send authentication to a proxy, you can also set authentication
dvander@2518
   447
type the same way but instead with CURLOPT_PROXYAUTH:
dvander@2518
   448
dvander@2518
   449
 curl_easy_setopt(easyhandle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
dvander@2518
   450
dvander@2518
   451
Both these options allow you to set multiple types (by ORing them together),
dvander@2518
   452
to make libcurl pick the most secure one out of the types the server/proxy
dvander@2518
   453
claims to support. This method does however add a round-trip since libcurl
dvander@2518
   454
must first ask the server what it supports:
dvander@2518
   455
dvander@2518
   456
 curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH,
dvander@2518
   457
 CURLAUTH_DIGEST|CURLAUTH_BASIC);
dvander@2518
   458
dvander@2518
   459
For convenience, you can use the 'CURLAUTH_ANY' define (instead of a list
dvander@2518
   460
with specific types) which allows libcurl to use whatever method it wants.
dvander@2518
   461
dvander@2518
   462
When asking for multiple types, libcurl will pick the available one it
dvander@2518
   463
considers "best" in its own internal order of preference.
dvander@2518
   464
dvander@2518
   465
.SH "HTTP POSTing"
dvander@2518
   466
We get many questions regarding how to issue HTTP POSTs with libcurl the
dvander@2518
   467
proper way. This chapter will thus include examples using both different
dvander@2518
   468
versions of HTTP POST that libcurl supports.
dvander@2518
   469
dvander@2518
   470
The first version is the simple POST, the most common version, that most HTML
dvander@2518
   471
pages using the <form> tag uses. We provide a pointer to the data and tell
dvander@2518
   472
libcurl to post it all to the remote site:
dvander@2518
   473
dvander@2518
   474
.nf
dvander@2518
   475
    char *data="name=daniel&project=curl";
dvander@2518
   476
    curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, data);
dvander@2518
   477
    curl_easy_setopt(easyhandle, CURLOPT_URL, "http://posthere.com/");
dvander@2518
   478
dvander@2518
   479
    curl_easy_perform(easyhandle); /* post away! */
dvander@2518
   480
.fi
dvander@2518
   481
dvander@2518
   482
Simple enough, huh? Since you set the POST options with the
dvander@2518
   483
CURLOPT_POSTFIELDS, this automatically switches the handle to use POST in the
dvander@2518
   484
upcoming request.
dvander@2518
   485
dvander@2518
   486
Ok, so what if you want to post binary data that also requires you to set the
asherkin@3839
   487
Content-Type: header of the post? Well, binary posts prevent libcurl from
dvander@2518
   488
being able to do strlen() on the data to figure out the size, so therefore we
dvander@2518
   489
must tell libcurl the size of the post data. Setting headers in libcurl
dvander@2518
   490
requests are done in a generic way, by building a list of our own headers and
dvander@2518
   491
then passing that list to libcurl.
dvander@2518
   492
dvander@2518
   493
.nf
dvander@2518
   494
 struct curl_slist *headers=NULL;
dvander@2518
   495
 headers = curl_slist_append(headers, "Content-Type: text/xml");
dvander@2518
   496
dvander@2518
   497
 /* post binary data */
dvander@2518
   498
 curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, binaryptr);
dvander@2518
   499
dvander@2518
   500
 /* set the size of the postfields data */
dvander@2518
   501
 curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDSIZE, 23L);
dvander@2518
   502
dvander@2518
   503
 /* pass our list of custom made headers */
dvander@2518
   504
 curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
dvander@2518
   505
dvander@2518
   506
 curl_easy_perform(easyhandle); /* post away! */
dvander@2518
   507
dvander@2518
   508
 curl_slist_free_all(headers); /* free the header list */
dvander@2518
   509
.fi
dvander@2518
   510
dvander@2518
   511
While the simple examples above cover the majority of all cases where HTTP
dvander@2518
   512
POST operations are required, they don't do multi-part formposts. Multi-part
dvander@2518
   513
formposts were introduced as a better way to post (possibly large) binary data
asherkin@3839
   514
and were first documented in the RFC1867 (updated in RFC2388). They're called
asherkin@3839
   515
multi-part because they're built by a chain of parts, each part being a single
asherkin@3839
   516
unit of data. Each part has its own name and contents. You can in fact create
asherkin@3839
   517
and post a multi-part formpost with the regular libcurl POST support described
asherkin@3839
   518
above, but that would require that you build a formpost yourself and provide
asherkin@3839
   519
to libcurl. To make that easier, libcurl provides \fIcurl_formadd(3)\fP. Using
asherkin@3839
   520
this function, you add parts to the form. When you're done adding parts, you
asherkin@3839
   521
post the whole form.
dvander@2518
   522
dvander@2518
   523
The following example sets two simple text parts with plain textual contents,
asherkin@3839
   524
and then a file with binary contents and uploads the whole thing.
dvander@2518
   525
dvander@2518
   526
.nf
dvander@2518
   527
 struct curl_httppost *post=NULL;
dvander@2518
   528
 struct curl_httppost *last=NULL;
dvander@2518
   529
 curl_formadd(&post, &last,
dvander@2518
   530
              CURLFORM_COPYNAME, "name",
dvander@2518
   531
              CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
dvander@2518
   532
 curl_formadd(&post, &last,
dvander@2518
   533
              CURLFORM_COPYNAME, "project",
dvander@2518
   534
              CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
dvander@2518
   535
 curl_formadd(&post, &last,
dvander@2518
   536
              CURLFORM_COPYNAME, "logotype-image",
dvander@2518
   537
              CURLFORM_FILECONTENT, "curl.png", CURLFORM_END);
dvander@2518
   538
dvander@2518
   539
 /* Set the form info */
dvander@2518
   540
 curl_easy_setopt(easyhandle, CURLOPT_HTTPPOST, post);
dvander@2518
   541
dvander@2518
   542
 curl_easy_perform(easyhandle); /* post away! */
dvander@2518
   543
dvander@2518
   544
 /* free the post data again */
dvander@2518
   545
 curl_formfree(post);
dvander@2518
   546
.fi
dvander@2518
   547
dvander@2518
   548
Multipart formposts are chains of parts using MIME-style separators and
dvander@2518
   549
headers. It means that each one of these separate parts get a few headers set
dvander@2518
   550
that describe the individual content-type, size etc. To enable your
dvander@2518
   551
application to handicraft this formpost even more, libcurl allows you to
dvander@2518
   552
supply your own set of custom headers to such an individual form part. You can
asherkin@3839
   553
of course supply headers to as many parts as you like, but this little example
dvander@2518
   554
will show how you set headers to one specific part when you add that to the
dvander@2518
   555
post handle:
dvander@2518
   556
dvander@2518
   557
.nf
dvander@2518
   558
 struct curl_slist *headers=NULL;
dvander@2518
   559
 headers = curl_slist_append(headers, "Content-Type: text/xml");
dvander@2518
   560
dvander@2518
   561
 curl_formadd(&post, &last,
dvander@2518
   562
              CURLFORM_COPYNAME, "logotype-image",
dvander@2518
   563
              CURLFORM_FILECONTENT, "curl.xml",
dvander@2518
   564
              CURLFORM_CONTENTHEADER, headers,
dvander@2518
   565
              CURLFORM_END);
dvander@2518
   566
dvander@2518
   567
 curl_easy_perform(easyhandle); /* post away! */
dvander@2518
   568
dvander@2518
   569
 curl_formfree(post); /* free post */
asherkin@3839
   570
 curl_slist_free_all(headers); /* free custom header list */
dvander@2518
   571
.fi
dvander@2518
   572
dvander@2518
   573
Since all options on an easyhandle are "sticky", they remain the same until
dvander@2518
   574
changed even if you do call \fIcurl_easy_perform(3)\fP, you may need to tell
asherkin@3839
   575
curl to go back to a plain GET request if you intend to do one as your
asherkin@3839
   576
next request. You force an easyhandle to go back to GET by using the
dvander@2518
   577
CURLOPT_HTTPGET option:
dvander@2518
   578
dvander@2518
   579
 curl_easy_setopt(easyhandle, CURLOPT_HTTPGET, 1L);
dvander@2518
   580
dvander@2518
   581
Just setting CURLOPT_POSTFIELDS to "" or NULL will *not* stop libcurl from
dvander@2518
   582
doing a POST. It will just make it POST without any data to send!
dvander@2518
   583
dvander@2518
   584
.SH "Showing Progress"
dvander@2518
   585
dvander@2518
   586
For historical and traditional reasons, libcurl has a built-in progress meter
asherkin@3839
   587
that can be switched on and then makes it present a progress meter in your
dvander@2518
   588
terminal.
dvander@2518
   589
asherkin@3839
   590
Switch on the progress meter by, oddly enough, setting CURLOPT_NOPROGRESS to
dvander@2518
   591
zero. This option is set to 1 by default.
dvander@2518
   592
dvander@2518
   593
For most applications however, the built-in progress meter is useless and
dvander@2518
   594
what instead is interesting is the ability to specify a progress
dvander@2518
   595
callback. The function pointer you pass to libcurl will then be called on
dvander@2518
   596
irregular intervals with information about the current transfer.
dvander@2518
   597
dvander@2518
   598
Set the progress callback by using CURLOPT_PROGRESSFUNCTION. And pass a
dvander@2518
   599
pointer to a function that matches this prototype:
dvander@2518
   600
dvander@2518
   601
.nf
dvander@2518
   602
 int progress_callback(void *clientp,
dvander@2518
   603
                       double dltotal,
dvander@2518
   604
                       double dlnow,
dvander@2518
   605
                       double ultotal,
dvander@2518
   606
                       double ulnow);
dvander@2518
   607
.fi
dvander@2518
   608
dvander@2518
   609
If any of the input arguments is unknown, a 0 will be passed. The first
dvander@2518
   610
argument, the 'clientp' is the pointer you pass to libcurl with
dvander@2518
   611
CURLOPT_PROGRESSDATA. libcurl won't touch it.
dvander@2518
   612
dvander@2518
   613
.SH "libcurl with C++"
dvander@2518
   614
dvander@2518
   615
There's basically only one thing to keep in mind when using C++ instead of C
dvander@2518
   616
when interfacing libcurl:
dvander@2518
   617
dvander@2518
   618
The callbacks CANNOT be non-static class member functions
dvander@2518
   619
dvander@2518
   620
Example C++ code:
dvander@2518
   621
dvander@2518
   622
.nf
dvander@2518
   623
class AClass {
dvander@2518
   624
    static size_t write_data(void *ptr, size_t size, size_t nmemb,
dvander@2518
   625
                             void *ourpointer)
dvander@2518
   626
    {
dvander@2518
   627
      /* do what you want with the data */
dvander@2518
   628
    }
dvander@2518
   629
 }
dvander@2518
   630
.fi
dvander@2518
   631
dvander@2518
   632
.SH "Proxies"
dvander@2518
   633
dvander@2518
   634
What "proxy" means according to Merriam-Webster: "a person authorized to act
dvander@2518
   635
for another" but also "the agency, function, or office of a deputy who acts as
dvander@2518
   636
a substitute for another".
dvander@2518
   637
dvander@2518
   638
Proxies are exceedingly common these days. Companies often only offer Internet
dvander@2518
   639
access to employees through their proxies. Network clients or user-agents ask
dvander@2518
   640
the proxy for documents, the proxy does the actual request and then it returns
dvander@2518
   641
them.
dvander@2518
   642
dvander@2518
   643
libcurl supports SOCKS and HTTP proxies. When a given URL is wanted, libcurl
dvander@2518
   644
will ask the proxy for it instead of trying to connect to the actual host
dvander@2518
   645
identified in the URL.
dvander@2518
   646
dvander@2518
   647
If you're using a SOCKS proxy, you may find that libcurl doesn't quite support
dvander@2518
   648
all operations through it.
dvander@2518
   649
dvander@2518
   650
For HTTP proxies: the fact that the proxy is a HTTP proxy puts certain
dvander@2518
   651
restrictions on what can actually happen. A requested URL that might not be a
dvander@2518
   652
HTTP URL will be still be passed to the HTTP proxy to deliver back to
dvander@2518
   653
libcurl. This happens transparently, and an application may not need to
dvander@2518
   654
know. I say "may", because at times it is very important to understand that
asherkin@3839
   655
all operations over a HTTP proxy use the HTTP protocol. For example, you
dvander@2518
   656
can't invoke your own custom FTP commands or even proper FTP directory
dvander@2518
   657
listings.
dvander@2518
   658
dvander@2518
   659
.IP "Proxy Options"
dvander@2518
   660
dvander@2518
   661
To tell libcurl to use a proxy at a given port number:
dvander@2518
   662
dvander@2518
   663
 curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080");
dvander@2518
   664
dvander@2518
   665
Some proxies require user authentication before allowing a request, and you
dvander@2518
   666
pass that information similar to this:
dvander@2518
   667
dvander@2518
   668
 curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password");
dvander@2518
   669
dvander@2518
   670
If you want to, you can specify the host name only in the CURLOPT_PROXY
dvander@2518
   671
option, and set the port number separately with CURLOPT_PROXYPORT.
dvander@2518
   672
dvander@2518
   673
Tell libcurl what kind of proxy it is with CURLOPT_PROXYTYPE (if not, it will
dvander@2518
   674
default to assume a HTTP proxy):
dvander@2518
   675
dvander@2518
   676
 curl_easy_setopt(easyhandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
dvander@2518
   677
dvander@2518
   678
.IP "Environment Variables"
dvander@2518
   679
asherkin@3839
   680
libcurl automatically checks and uses a set of environment variables to know
asherkin@3839
   681
what proxies to use for certain protocols. The names of the variables are
asherkin@3839
   682
following an ancient de facto standard and are built up as "[protocol]_proxy"
asherkin@3839
   683
(note the lower casing). Which makes the variable \&'http_proxy' checked for a
asherkin@3839
   684
name of a proxy to use when the input URL is HTTP. Following the same rule,
asherkin@3839
   685
the variable named 'ftp_proxy' is checked for FTP URLs. Again, the proxies are
asherkin@3839
   686
always HTTP proxies, the different names of the variables simply allows
asherkin@3839
   687
different HTTP proxies to be used.
dvander@2518
   688
dvander@2518
   689
The proxy environment variable contents should be in the format
dvander@2518
   690
\&"[protocol://][user:password@]machine[:port]". Where the protocol:// part is
dvander@2518
   691
simply ignored if present (so http://proxy and bluerk://proxy will do the
dvander@2518
   692
same) and the optional port number specifies on which port the proxy operates
dvander@2518
   693
on the host. If not specified, the internal default port number will be used
dvander@2518
   694
and that is most likely *not* the one you would like it to be.
dvander@2518
   695
dvander@2518
   696
There are two special environment variables. 'all_proxy' is what sets proxy
dvander@2518
   697
for any URL in case the protocol specific variable wasn't set, and
dvander@2518
   698
\&'no_proxy' defines a list of hosts that should not use a proxy even though a
dvander@2518
   699
variable may say so. If 'no_proxy' is a plain asterisk ("*") it matches all
dvander@2518
   700
hosts.
dvander@2518
   701
dvander@2518
   702
To explicitly disable libcurl's checking for and using the proxy environment
dvander@2518
   703
variables, set the proxy name to "" - an empty string - with CURLOPT_PROXY.
dvander@2518
   704
.IP "SSL and Proxies"
dvander@2518
   705
dvander@2518
   706
SSL is for secure point-to-point connections. This involves strong encryption
dvander@2518
   707
and similar things, which effectively makes it impossible for a proxy to
dvander@2518
   708
operate as a "man in between" which the proxy's task is, as previously
dvander@2518
   709
discussed. Instead, the only way to have SSL work over a HTTP proxy is to ask
dvander@2518
   710
the proxy to tunnel trough everything without being able to check or fiddle
dvander@2518
   711
with the traffic.
dvander@2518
   712
dvander@2518
   713
Opening an SSL connection over a HTTP proxy is therefor a matter of asking the
dvander@2518
   714
proxy for a straight connection to the target host on a specified port. This
dvander@2518
   715
is made with the HTTP request CONNECT. ("please mr proxy, connect me to that
dvander@2518
   716
remote host").
dvander@2518
   717
dvander@2518
   718
Because of the nature of this operation, where the proxy has no idea what kind
dvander@2518
   719
of data that is passed in and out through this tunnel, this breaks some of the
dvander@2518
   720
very few advantages that come from using a proxy, such as caching.  Many
dvander@2518
   721
organizations prevent this kind of tunneling to other destination port numbers
dvander@2518
   722
than 443 (which is the default HTTPS port number).
dvander@2518
   723
dvander@2518
   724
.IP "Tunneling Through Proxy"
dvander@2518
   725
As explained above, tunneling is required for SSL to work and often even
dvander@2518
   726
restricted to the operation intended for SSL; HTTPS.
dvander@2518
   727
dvander@2518
   728
This is however not the only time proxy-tunneling might offer benefits to
dvander@2518
   729
you or your application.
dvander@2518
   730
dvander@2518
   731
As tunneling opens a direct connection from your application to the remote
dvander@2518
   732
machine, it suddenly also re-introduces the ability to do non-HTTP
dvander@2518
   733
operations over a HTTP proxy. You can in fact use things such as FTP
dvander@2518
   734
upload or FTP custom commands this way.
dvander@2518
   735
dvander@2518
   736
Again, this is often prevented by the administrators of proxies and is
dvander@2518
   737
rarely allowed.
dvander@2518
   738
dvander@2518
   739
Tell libcurl to use proxy tunneling like this:
dvander@2518
   740
dvander@2518
   741
 curl_easy_setopt(easyhandle, CURLOPT_HTTPPROXYTUNNEL, 1L);
dvander@2518
   742
dvander@2518
   743
In fact, there might even be times when you want to do plain HTTP
dvander@2518
   744
operations using a tunnel like this, as it then enables you to operate on
dvander@2518
   745
the remote server instead of asking the proxy to do so. libcurl will not
dvander@2518
   746
stand in the way for such innovative actions either!
dvander@2518
   747
dvander@2518
   748
.IP "Proxy Auto-Config"
dvander@2518
   749
dvander@2518
   750
Netscape first came up with this. It is basically a web page (usually using a
asherkin@3839
   751
\&.pac extension) with a Javascript that when executed by the browser with the
dvander@2518
   752
requested URL as input, returns information to the browser on how to connect
dvander@2518
   753
to the URL. The returned information might be "DIRECT" (which means no proxy
dvander@2518
   754
should be used), "PROXY host:port" (to tell the browser where the proxy for
dvander@2518
   755
this particular URL is) or "SOCKS host:port" (to direct the browser to a SOCKS
dvander@2518
   756
proxy).
dvander@2518
   757
asherkin@3839
   758
libcurl has no means to interpret or evaluate Javascript and thus it doesn't
dvander@2518
   759
support this. If you get yourself in a position where you face this nasty
dvander@2518
   760
invention, the following advice have been mentioned and used in the past:
dvander@2518
   761
asherkin@3839
   762
- Depending on the Javascript complexity, write up a script that translates it
dvander@2518
   763
to another language and execute that.
dvander@2518
   764
asherkin@3839
   765
- Read the Javascript code and rewrite the same logic in another language.
dvander@2518
   766
asherkin@3839
   767
- Implement a Javascript interpreter; people have successfully used the
asherkin@3839
   768
Mozilla Javascript engine in the past.
dvander@2518
   769
dvander@2518
   770
- Ask your admins to stop this, for a static proxy setup or similar.
dvander@2518
   771
dvander@2518
   772
.SH "Persistence Is The Way to Happiness"
dvander@2518
   773
dvander@2518
   774
Re-cycling the same easy handle several times when doing multiple requests is
dvander@2518
   775
the way to go.
dvander@2518
   776
dvander@2518
   777
After each single \fIcurl_easy_perform(3)\fP operation, libcurl will keep the
dvander@2518
   778
connection alive and open. A subsequent request using the same easy handle to
dvander@2518
   779
the same host might just be able to use the already open connection! This
dvander@2518
   780
reduces network impact a lot.
dvander@2518
   781
dvander@2518
   782
Even if the connection is dropped, all connections involving SSL to the same
dvander@2518
   783
host again, will benefit from libcurl's session ID cache that drastically
dvander@2518
   784
reduces re-connection time.
dvander@2518
   785
asherkin@3839
   786
FTP connections that are kept alive save a lot of time, as the command-
dvander@2518
   787
response round-trips are skipped, and also you don't risk getting blocked
dvander@2518
   788
without permission to login again like on many FTP servers only allowing N
dvander@2518
   789
persons to be logged in at the same time.
dvander@2518
   790
dvander@2518
   791
libcurl caches DNS name resolving results, to make lookups of a previously
dvander@2518
   792
looked up name a lot faster.
dvander@2518
   793
dvander@2518
   794
Other interesting details that improve performance for subsequent requests
dvander@2518
   795
may also be added in the future.
dvander@2518
   796
dvander@2518
   797
Each easy handle will attempt to keep the last few connections alive for a
dvander@2518
   798
while in case they are to be used again. You can set the size of this "cache"
asherkin@3839
   799
with the CURLOPT_MAXCONNECTS option. Default is 5. There is very seldom any
dvander@2518
   800
point in changing this value, and if you think of changing this it is often
dvander@2518
   801
just a matter of thinking again.
dvander@2518
   802
dvander@2518
   803
To force your upcoming request to not use an already existing connection (it
dvander@2518
   804
will even close one first if there happens to be one alive to the same host
dvander@2518
   805
you're about to operate on), you can do that by setting CURLOPT_FRESH_CONNECT
dvander@2518
   806
to 1. In a similar spirit, you can also forbid the upcoming request to be
dvander@2518
   807
"lying" around and possibly get re-used after the request by setting
dvander@2518
   808
CURLOPT_FORBID_REUSE to 1.
dvander@2518
   809
dvander@2518
   810
.SH "HTTP Headers Used by libcurl"
dvander@2518
   811
When you use libcurl to do HTTP requests, it'll pass along a series of headers
asherkin@3839
   812
automatically. It might be good for you to know and understand these. You
dvander@2518
   813
can replace or remove them by using the CURLOPT_HTTPHEADER option.
dvander@2518
   814
dvander@2518
   815
.IP "Host"
dvander@2518
   816
This header is required by HTTP 1.1 and even many 1.0 servers and should be
dvander@2518
   817
the name of the server we want to talk to. This includes the port number if
dvander@2518
   818
anything but default.
dvander@2518
   819
dvander@2518
   820
.IP "Accept"
dvander@2518
   821
\&"*/*".
dvander@2518
   822
dvander@2518
   823
.IP "Expect"
dvander@2518
   824
When doing POST requests, libcurl sets this header to \&"100-continue" to ask
dvander@2518
   825
the server for an "OK" message before it proceeds with sending the data part
dvander@2518
   826
of the post. If the POSTed data amount is deemed "small", libcurl will not use
dvander@2518
   827
this header.
dvander@2518
   828
dvander@2518
   829
.SH "Customizing Operations"
dvander@2518
   830
There is an ongoing development today where more and more protocols are built
dvander@2518
   831
upon HTTP for transport. This has obvious benefits as HTTP is a tested and
asherkin@3839
   832
reliable protocol that is widely deployed and has excellent proxy-support.
dvander@2518
   833
dvander@2518
   834
When you use one of these protocols, and even when doing other kinds of
dvander@2518
   835
programming you may need to change the traditional HTTP (or FTP or...)
dvander@2518
   836
manners. You may need to change words, headers or various data.
dvander@2518
   837
dvander@2518
   838
libcurl is your friend here too.
dvander@2518
   839
dvander@2518
   840
.IP CUSTOMREQUEST
dvander@2518
   841
If just changing the actual HTTP request keyword is what you want, like when
dvander@2518
   842
GET, HEAD or POST is not good enough for you, CURLOPT_CUSTOMREQUEST is there
dvander@2518
   843
for you. It is very simple to use:
dvander@2518
   844
asherkin@3839
   845
 curl_easy_setopt(easyhandle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST");
dvander@2518
   846
dvander@2518
   847
When using the custom request, you change the request keyword of the actual
asherkin@3839
   848
request you are performing. Thus, by default you make a GET request but you can
dvander@2518
   849
also make a POST operation (as described before) and then replace the POST
dvander@2518
   850
keyword if you want to. You're the boss.
dvander@2518
   851
dvander@2518
   852
.IP "Modify Headers"
dvander@2518
   853
HTTP-like protocols pass a series of headers to the server when doing the
dvander@2518
   854
request, and you're free to pass any amount of extra headers that you
asherkin@3839
   855
think fit. Adding headers is this easy:
dvander@2518
   856
dvander@2518
   857
.nf
dvander@2518
   858
 struct curl_slist *headers=NULL; /* init to NULL is important */
dvander@2518
   859
dvander@2518
   860
 headers = curl_slist_append(headers, "Hey-server-hey: how are you?");
dvander@2518
   861
 headers = curl_slist_append(headers, "X-silly-content: yes");
dvander@2518
   862
dvander@2518
   863
 /* pass our list of custom made headers */
dvander@2518
   864
 curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
dvander@2518
   865
dvander@2518
   866
 curl_easy_perform(easyhandle); /* transfer http */
dvander@2518
   867
dvander@2518
   868
 curl_slist_free_all(headers); /* free the header list */
dvander@2518
   869
.fi
dvander@2518
   870
dvander@2518
   871
\&... and if you think some of the internally generated headers, such as
dvander@2518
   872
Accept: or Host: don't contain the data you want them to contain, you can
dvander@2518
   873
replace them by simply setting them too:
dvander@2518
   874
dvander@2518
   875
.nf
dvander@2518
   876
 headers = curl_slist_append(headers, "Accept: Agent-007");
dvander@2518
   877
 headers = curl_slist_append(headers, "Host: munged.host.line");
dvander@2518
   878
.fi
dvander@2518
   879
dvander@2518
   880
.IP "Delete Headers"
dvander@2518
   881
If you replace an existing header with one with no contents, you will prevent
asherkin@3839
   882
the header from being sent. For instance, if you want to completely prevent the
asherkin@3839
   883
\&"Accept:" header from being sent, you can disable it with code similar to this:
dvander@2518
   884
dvander@2518
   885
 headers = curl_slist_append(headers, "Accept:");
dvander@2518
   886
dvander@2518
   887
Both replacing and canceling internal headers should be done with careful
dvander@2518
   888
consideration and you should be aware that you may violate the HTTP protocol
dvander@2518
   889
when doing so.
dvander@2518
   890
dvander@2518
   891
.IP "Enforcing chunked transfer-encoding"
dvander@2518
   892
dvander@2518
   893
By making sure a request uses the custom header "Transfer-Encoding: chunked"
dvander@2518
   894
when doing a non-GET HTTP operation, libcurl will switch over to "chunked"
dvander@2518
   895
upload, even though the size of the data to upload might be known. By default,
dvander@2518
   896
libcurl usually switches over to chunked upload automatically if the upload
dvander@2518
   897
data size is unknown.
dvander@2518
   898
dvander@2518
   899
.IP "HTTP Version"
dvander@2518
   900
dvander@2518
   901
All HTTP requests includes the version number to tell the server which version
asherkin@3839
   902
we support. libcurl speaks HTTP 1.1 by default. Some very old servers don't
dvander@2518
   903
like getting 1.1-requests and when dealing with stubborn old things like that,
dvander@2518
   904
you can tell libcurl to use 1.0 instead by doing something like this:
dvander@2518
   905
dvander@2518
   906
 curl_easy_setopt(easyhandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
dvander@2518
   907
dvander@2518
   908
.IP "FTP Custom Commands"
dvander@2518
   909
dvander@2518
   910
Not all protocols are HTTP-like, and thus the above may not help you when
asherkin@3839
   911
you want to make, for example, your FTP transfers to behave differently.
dvander@2518
   912
dvander@2518
   913
Sending custom commands to a FTP server means that you need to send the
dvander@2518
   914
commands exactly as the FTP server expects them (RFC959 is a good guide
dvander@2518
   915
here), and you can only use commands that work on the control-connection
asherkin@3839
   916
alone. All kinds of commands that require data interchange and thus need
asherkin@3839
   917
a data-connection must be left to libcurl's own judgement. Also be aware
dvander@2518
   918
that libcurl will do its very best to change directory to the target
dvander@2518
   919
directory before doing any transfer, so if you change directory (with CWD
dvander@2518
   920
or similar) you might confuse libcurl and then it might not attempt to
dvander@2518
   921
transfer the file in the correct remote directory.
dvander@2518
   922
dvander@2518
   923
A little example that deletes a given file before an operation:
dvander@2518
   924
dvander@2518
   925
.nf
dvander@2518
   926
 headers = curl_slist_append(headers, "DELE file-to-remove");
dvander@2518
   927
dvander@2518
   928
 /* pass the list of custom commands to the handle */
dvander@2518
   929
 curl_easy_setopt(easyhandle, CURLOPT_QUOTE, headers);
dvander@2518
   930
dvander@2518
   931
 curl_easy_perform(easyhandle); /* transfer ftp data! */
dvander@2518
   932
dvander@2518
   933
 curl_slist_free_all(headers); /* free the header list */
dvander@2518
   934
.fi
dvander@2518
   935
dvander@2518
   936
If you would instead want this operation (or chain of operations) to happen
dvander@2518
   937
_after_ the data transfer took place the option to \fIcurl_easy_setopt(3)\fP
dvander@2518
   938
would instead be called CURLOPT_POSTQUOTE and used the exact same way.
dvander@2518
   939
dvander@2518
   940
The custom FTP command will be issued to the server in the same order they are
dvander@2518
   941
added to the list, and if a command gets an error code returned back from the
dvander@2518
   942
server, no more commands will be issued and libcurl will bail out with an
dvander@2518
   943
error code (CURLE_QUOTE_ERROR). Note that if you use CURLOPT_QUOTE to send
dvander@2518
   944
commands before a transfer, no transfer will actually take place when a quote
dvander@2518
   945
command has failed.
dvander@2518
   946
dvander@2518
   947
If you set the CURLOPT_HEADER to 1, you will tell libcurl to get
dvander@2518
   948
information about the target file and output "headers" about it. The headers
dvander@2518
   949
will be in "HTTP-style", looking like they do in HTTP.
dvander@2518
   950
dvander@2518
   951
The option to enable headers or to run custom FTP commands may be useful to
dvander@2518
   952
combine with CURLOPT_NOBODY. If this option is set, no actual file content
dvander@2518
   953
transfer will be performed.
dvander@2518
   954
dvander@2518
   955
.IP "FTP Custom CUSTOMREQUEST"
asherkin@3839
   956
If you do want to list the contents of a FTP directory using your own defined FTP
dvander@2518
   957
command, CURLOPT_CUSTOMREQUEST will do just that. "NLST" is the default one
dvander@2518
   958
for listing directories but you're free to pass in your idea of a good
dvander@2518
   959
alternative.
dvander@2518
   960
dvander@2518
   961
.SH "Cookies Without Chocolate Chips"
dvander@2518
   962
In the HTTP sense, a cookie is a name with an associated value. A server sends
dvander@2518
   963
the name and value to the client, and expects it to get sent back on every
dvander@2518
   964
subsequent request to the server that matches the particular conditions
dvander@2518
   965
set. The conditions include that the domain name and path match and that the
dvander@2518
   966
cookie hasn't become too old.
dvander@2518
   967
asherkin@3839
   968
In real-world cases, servers send new cookies to replace existing ones to
dvander@2518
   969
update them. Server use cookies to "track" users and to keep "sessions".
dvander@2518
   970
dvander@2518
   971
Cookies are sent from server to clients with the header Set-Cookie: and
dvander@2518
   972
they're sent from clients to servers with the Cookie: header.
dvander@2518
   973
dvander@2518
   974
To just send whatever cookie you want to a server, you can use CURLOPT_COOKIE
dvander@2518
   975
to set a cookie string like this:
dvander@2518
   976
dvander@2518
   977
 curl_easy_setopt(easyhandle, CURLOPT_COOKIE, "name1=var1; name2=var2;");
dvander@2518
   978
dvander@2518
   979
In many cases, that is not enough. You might want to dynamically save
dvander@2518
   980
whatever cookies the remote server passes to you, and make sure those cookies
asherkin@3839
   981
are then used accordingly on later requests.
dvander@2518
   982
dvander@2518
   983
One way to do this, is to save all headers you receive in a plain file and
dvander@2518
   984
when you make a request, you tell libcurl to read the previous headers to
asherkin@3839
   985
figure out which cookies to use. Set the header file to read cookies from with
dvander@2518
   986
CURLOPT_COOKIEFILE.
dvander@2518
   987
dvander@2518
   988
The CURLOPT_COOKIEFILE option also automatically enables the cookie parser in
dvander@2518
   989
libcurl. Until the cookie parser is enabled, libcurl will not parse or
dvander@2518
   990
understand incoming cookies and they will just be ignored. However, when the
dvander@2518
   991
parser is enabled the cookies will be understood and the cookies will be kept
dvander@2518
   992
in memory and used properly in subsequent requests when the same handle is
dvander@2518
   993
used. Many times this is enough, and you may not have to save the cookies to
asherkin@3839
   994
disk at all. Note that the file you specify to CURLOPT_COOKIEFILE doesn't have
asherkin@3839
   995
to exist to enable the parser, so a common way to just enable the parser and
asherkin@3839
   996
not read any cookies is to use the name of a file you know doesn't exist.
dvander@2518
   997
asherkin@3839
   998
If you would rather use existing cookies that you've previously received with
asherkin@3839
   999
your Netscape or Mozilla browsers, you can make libcurl use that cookie file
asherkin@3839
  1000
as input. The CURLOPT_COOKIEFILE is used for that too, as libcurl will
dvander@2518
  1001
automatically find out what kind of file it is and act accordingly.
dvander@2518
  1002
asherkin@3839
  1003
Perhaps the most advanced cookie operation libcurl offers, is saving the
dvander@2518
  1004
entire internal cookie state back into a Netscape/Mozilla formatted cookie
dvander@2518
  1005
file. We call that the cookie-jar. When you set a file name with
dvander@2518
  1006
CURLOPT_COOKIEJAR, that file name will be created and all received cookies
asherkin@3839
  1007
will be stored in it when \fIcurl_easy_cleanup(3)\fP is called. This enables
dvander@2518
  1008
cookies to get passed on properly between multiple handles without any
dvander@2518
  1009
information getting lost.
dvander@2518
  1010
dvander@2518
  1011
.SH "FTP Peculiarities We Need"
dvander@2518
  1012
dvander@2518
  1013
FTP transfers use a second TCP/IP connection for the data transfer. This is
dvander@2518
  1014
usually a fact you can forget and ignore but at times this fact will come
asherkin@3839
  1015
back to haunt you. libcurl offers several different ways to customize how the
dvander@2518
  1016
second connection is being made.
dvander@2518
  1017
dvander@2518
  1018
libcurl can either connect to the server a second time or tell the server to
dvander@2518
  1019
connect back to it. The first option is the default and it is also what works
dvander@2518
  1020
best for all the people behind firewalls, NATs or IP-masquerading setups.
dvander@2518
  1021
libcurl then tells the server to open up a new port and wait for a second
dvander@2518
  1022
connection. This is by default attempted with EPSV first, and if that doesn't
dvander@2518
  1023
work it tries PASV instead. (EPSV is an extension to the original FTP spec
dvander@2518
  1024
and does not exist nor work on all FTP servers.)
dvander@2518
  1025
dvander@2518
  1026
You can prevent libcurl from first trying the EPSV command by setting
dvander@2518
  1027
CURLOPT_FTP_USE_EPSV to zero.
dvander@2518
  1028
dvander@2518
  1029
In some cases, you will prefer to have the server connect back to you for the
dvander@2518
  1030
second connection. This might be when the server is perhaps behind a firewall
dvander@2518
  1031
or something and only allows connections on a single port. libcurl then
dvander@2518
  1032
informs the remote server which IP address and port number to connect to.
dvander@2518
  1033
This is made with the CURLOPT_FTPPORT option. If you set it to "-", libcurl
dvander@2518
  1034
will use your system's "default IP address". If you want to use a particular
dvander@2518
  1035
IP, you can set the full IP address, a host name to resolve to an IP address
dvander@2518
  1036
or even a local network interface name that libcurl will get the IP address
dvander@2518
  1037
from.
dvander@2518
  1038
dvander@2518
  1039
When doing the "PORT" approach, libcurl will attempt to use the EPRT and the
dvander@2518
  1040
LPRT before trying PORT, as they work with more protocols. You can disable
dvander@2518
  1041
this behavior by setting CURLOPT_FTP_USE_EPRT to zero.
dvander@2518
  1042
dvander@2518
  1043
.SH "Headers Equal Fun"
dvander@2518
  1044
dvander@2518
  1045
Some protocols provide "headers", meta-data separated from the normal
dvander@2518
  1046
data. These headers are by default not included in the normal data stream,
dvander@2518
  1047
but you can make them appear in the data stream by setting CURLOPT_HEADER to
dvander@2518
  1048
1.
dvander@2518
  1049
dvander@2518
  1050
What might be even more useful, is libcurl's ability to separate the headers
dvander@2518
  1051
from the data and thus make the callbacks differ. You can for example set a
dvander@2518
  1052
different pointer to pass to the ordinary write callback by setting
dvander@2518
  1053
CURLOPT_WRITEHEADER.
dvander@2518
  1054
dvander@2518
  1055
Or, you can set an entirely separate function to receive the headers, by
dvander@2518
  1056
using CURLOPT_HEADERFUNCTION.
dvander@2518
  1057
dvander@2518
  1058
The headers are passed to the callback function one by one, and you can
dvander@2518
  1059
depend on that fact. It makes it easier for you to add custom header parsers
dvander@2518
  1060
etc.
dvander@2518
  1061
dvander@2518
  1062
\&"Headers" for FTP transfers equal all the FTP server responses. They aren't
dvander@2518
  1063
actually true headers, but in this case we pretend they are! ;-)
dvander@2518
  1064
dvander@2518
  1065
.SH "Post Transfer Information"
dvander@2518
  1066
dvander@2518
  1067
 [ curl_easy_getinfo ]
dvander@2518
  1068
dvander@2518
  1069
.SH "Security Considerations"
dvander@2518
  1070
asherkin@3839
  1071
The libcurl project takes security seriously.  The library is written with
asherkin@3839
  1072
caution and precautions are taken to mitigate many kinds of risks encountered
asherkin@3839
  1073
while operating with potentially malicious servers on the Internet.  It is a
asherkin@3839
  1074
powerful library, however, which allows application writers to make trade offs
asherkin@3839
  1075
between ease of writing and exposure to potential risky operations.  If
asherkin@3839
  1076
used the right way, you can use libcurl to transfer data pretty safely.
dvander@2518
  1077
asherkin@3839
  1078
Many applications are used in closed networks where users and servers
asherkin@3839
  1079
can be trusted, but many others are used on arbitrary servers and are fed
asherkin@3839
  1080
input from potentially untrusted users.  Following is a discussion about
asherkin@3839
  1081
some risks in the ways in which applications commonly use libcurl and
asherkin@3839
  1082
potential mitigations of those risks. It is by no means comprehensive, but
asherkin@3839
  1083
shows classes of attacks that robust applications should consider. The
asherkin@3839
  1084
Common Weakness Enumeration project at http://cwe.mitre.org/ is a good
asherkin@3839
  1085
reference for many of these and similar types of weaknesses of which
asherkin@3839
  1086
application writers should be aware.
dvander@2518
  1087
dvander@2518
  1088
.IP "Command Lines"
dvander@2518
  1089
If you use a command line tool (such as curl) that uses libcurl, and you give
asherkin@3839
  1090
options to the tool on the command line those options can very likely get read
dvander@2518
  1091
by other users of your system when they use 'ps' or other tools to list
dvander@2518
  1092
currently running processes.
dvander@2518
  1093
dvander@2518
  1094
To avoid this problem, never feed sensitive things to programs using command
asherkin@3839
  1095
line options. Write them to a protected file and use the \-K option to
asherkin@3839
  1096
avoid this.
dvander@2518
  1097
dvander@2518
  1098
.IP ".netrc"
dvander@2518
  1099
\&.netrc is a pretty handy file/feature that allows you to login quickly and
dvander@2518
  1100
automatically to frequently visited sites. The file contains passwords in
dvander@2518
  1101
clear text and is a real security risk. In some cases, your .netrc is also
dvander@2518
  1102
stored in a home directory that is NFS mounted or used on another network
dvander@2518
  1103
based file system, so the clear text password will fly through your network
dvander@2518
  1104
every time anyone reads that file!
dvander@2518
  1105
dvander@2518
  1106
To avoid this problem, don't use .netrc files and never store passwords in
dvander@2518
  1107
plain text anywhere.
dvander@2518
  1108
dvander@2518
  1109
.IP "Clear Text Passwords"
dvander@2518
  1110
Many of the protocols libcurl supports send name and password unencrypted as
dvander@2518
  1111
clear text (HTTP Basic authentication, FTP, TELNET etc). It is very easy for
asherkin@3839
  1112
anyone on your network or a network nearby yours to just fire up a network
dvander@2518
  1113
analyzer tool and eavesdrop on your passwords. Don't let the fact that HTTP
asherkin@3839
  1114
Basic uses base64 encoded passwords fool you. They may not look readable at a
asherkin@3839
  1115
first glance, but they very easily "deciphered" by anyone within seconds.
asherkin@3839
  1116
asherkin@3839
  1117
To avoid this problem, use HTTP authentication methods or other protocols that
asherkin@3839
  1118
don't let snoopers see your password: HTTP with Digest, NTLM or GSS
asherkin@3839
  1119
authentication, HTTPS, FTPS, SCP, SFTP and FTP-Kerberos are a few examples.
asherkin@3839
  1120
asherkin@3839
  1121
.IP "Redirects"
asherkin@3839
  1122
The CURLOPT_FOLLOWLOCATION option automatically follows HTTP redirects sent
asherkin@3839
  1123
by a remote server.  These redirects can refer to any kind of URL, not just
asherkin@3839
  1124
HTTP.  A redirect to a file: URL would cause the libcurl to read (or write)
asherkin@3839
  1125
arbitrary files from the local filesystem.  If the application returns
asherkin@3839
  1126
the data back to the user (as would happen in some kinds of CGI scripts),
asherkin@3839
  1127
an attacker could leverage this to read otherwise forbidden data (e.g.
asherkin@3839
  1128
file://localhost/etc/passwd).
asherkin@3839
  1129
asherkin@3839
  1130
If authentication credentials are stored in the ~/.netrc file, or Kerberos
asherkin@3839
  1131
is in use, any other URL type (not just file:) that requires
asherkin@3839
  1132
authentication is also at risk.  A redirect such as
asherkin@3839
  1133
ftp://some-internal-server/private-file would then return data even when
asherkin@3839
  1134
the server is password protected.
asherkin@3839
  1135
asherkin@3839
  1136
In the same way, if an unencrypted SSH private key has been configured for
asherkin@3839
  1137
the user running the libcurl application, SCP: or SFTP: URLs could access
asherkin@3839
  1138
password or private-key protected resources,
asherkin@3839
  1139
e.g. sftp://user@some-internal-server/etc/passwd
asherkin@3839
  1140
asherkin@3839
  1141
The CURLOPT_REDIR_PROTOCOLS and CURLOPT_NETRC options can be used to
asherkin@3839
  1142
mitigate against this kind of attack.
asherkin@3839
  1143
asherkin@3839
  1144
A redirect can also specify a location available only on the machine running
asherkin@3839
  1145
libcurl, including servers hidden behind a firewall from the attacker.
asherkin@3839
  1146
e.g. http://127.0.0.1/ or http://intranet/delete-stuff.cgi?delete=all or
asherkin@3839
  1147
tftp://bootp-server/pc-config-data
asherkin@3839
  1148
asherkin@3839
  1149
Apps can mitigate against this by disabling CURLOPT_FOLLOWLOCATION and
asherkin@3839
  1150
handling redirects itself, sanitizing URLs as necessary. Alternately, an
asherkin@3839
  1151
app could leave CURLOPT_FOLLOWLOCATION enabled but set CURLOPT_REDIR_PROTOCOLS
asherkin@3839
  1152
and install a CURLOPT_OPENSOCKETFUNCTION callback function in which addresses
asherkin@3839
  1153
are sanitized before use.
asherkin@3839
  1154
asherkin@3839
  1155
.IP "Private Resources"
asherkin@3839
  1156
A user who can control the DNS server of a domain being passed in within
asherkin@3839
  1157
a URL can change the address of the host to a local, private address
asherkin@3839
  1158
which the libcurl application will then use. e.g. The innocuous URL
asherkin@3839
  1159
http://fuzzybunnies.example.com/ could actually resolve to the IP address
asherkin@3839
  1160
of a server behind a firewall, such as 127.0.0.1 or 10.1.2.3
asherkin@3839
  1161
Apps can mitigate against this by setting a CURLOPT_OPENSOCKETFUNCTION
asherkin@3839
  1162
and checking the address before a connection.
asherkin@3839
  1163
asherkin@3839
  1164
All the malicious scenarios regarding redirected URLs apply just as well
asherkin@3839
  1165
to non-redirected URLs, if the user is allowed to specify an arbitrary URL
asherkin@3839
  1166
that could point to a private resource. For example, a web app providing
asherkin@3839
  1167
a translation service might happily translate file://localhost/etc/passwd
asherkin@3839
  1168
and display the result.  Apps can mitigate against this with the
asherkin@3839
  1169
CURLOPT_PROTOCOLS option as well as by similar mitigation techniques for
asherkin@3839
  1170
redirections.
asherkin@3839
  1171
asherkin@3839
  1172
A malicious FTP server could in response to the PASV command return an
asherkin@3839
  1173
IP address and port number for a server local to the app running libcurl
asherkin@3839
  1174
but behind a firewall.  Apps can mitigate against this by using the
asherkin@3839
  1175
CURLOPT_FTP_SKIP_PASV_IP option or CURLOPT_FTPPORT.
asherkin@3839
  1176
asherkin@3839
  1177
.IP Uploads
asherkin@3839
  1178
When uploading, a redirect can cause a local (or remote) file to be
asherkin@3839
  1179
overwritten.  Apps must not allow any unsanitized URL to be passed in
asherkin@3839
  1180
for uploads.  Also, CURLOPT_FOLLOWLOCATION should not be used on uploads.
asherkin@3839
  1181
Instead, the app should handle redirects itself, sanitizing each URL first.
dvander@2518
  1182
asherkin@3839
  1183
.IP Authentication
asherkin@3839
  1184
Use of CURLOPT_UNRESTRICTED_AUTH could cause authentication information to
asherkin@3839
  1185
be sent to an unknown second server.  Apps can mitigate against this
asherkin@3839
  1186
by disabling CURLOPT_FOLLOWLOCATION and handling redirects itself,
asherkin@3839
  1187
sanitizing where necessary.
asherkin@3839
  1188
asherkin@3839
  1189
Use of the CURLAUTH_ANY option to CURLOPT_HTTPAUTH could result in user
asherkin@3839
  1190
name and password being sent in clear text to an HTTP server.  Instead,
asherkin@3839
  1191
use CURLAUTH_ANYSAFE which ensures that the password is encrypted over
asherkin@3839
  1192
the network, or else fail the request.
asherkin@3839
  1193
asherkin@3839
  1194
Use of the CURLUSESSL_TRY option to CURLOPT_USE_SSL could result in user
asherkin@3839
  1195
name and password being sent in clear text to an FTP server.  Instead,
asherkin@3839
  1196
use CURLUSESSL_CONTROL to ensure that an encrypted connection is used or
asherkin@3839
  1197
else fail the request.
asherkin@3839
  1198
asherkin@3839
  1199
.IP Cookies
asherkin@3839
  1200
If cookies are enabled and cached, then a user could craft a URL which
asherkin@3839
  1201
performs some malicious action to a site whose authentication is already
asherkin@3839
  1202
stored in a cookie. e.g. http://mail.example.com/delete-stuff.cgi?delete=all
asherkin@3839
  1203
Apps can mitigate against this by disabling cookies or clearing them
asherkin@3839
  1204
between requests.
asherkin@3839
  1205
asherkin@3839
  1206
.IP "Dangerous URLs"
asherkin@3839
  1207
SCP URLs can contain raw commands within the scp: URL, which is a side effect
asherkin@3839
  1208
of how the SCP protocol is designed. e.g.
asherkin@3839
  1209
scp://user:pass@host/a;date >/tmp/test;
asherkin@3839
  1210
Apps must not allow unsanitized SCP: URLs to be passed in for downloads.
asherkin@3839
  1211
asherkin@3839
  1212
.IP "Denial of Service"
asherkin@3839
  1213
A malicious server could cause libcurl to effectively hang by sending
asherkin@3839
  1214
a trickle of data through, or even no data at all but just keeping the TCP
asherkin@3839
  1215
connection open.  This could result in a denial-of-service attack. The
asherkin@3839
  1216
CURLOPT_TIMEOUT and/or CURLOPT_LOW_SPEED_LIMIT options can be used to
asherkin@3839
  1217
mitigate against this.
asherkin@3839
  1218
asherkin@3839
  1219
A malicious server could cause libcurl to effectively hang by starting to
asherkin@3839
  1220
send data, then severing the connection without cleanly closing the
asherkin@3839
  1221
TCP connection.  The app could install a CURLOPT_SOCKOPTFUNCTION callback
asherkin@3839
  1222
function and set the TCP SO_KEEPALIVE option to mitigate against this.
asherkin@3839
  1223
Setting one of the timeout options would also work against this attack.
asherkin@3839
  1224
asherkin@3839
  1225
A malicious server could cause libcurl to download an infinite amount of
asherkin@3839
  1226
data, potentially causing all of memory or disk to be filled. Setting
asherkin@3839
  1227
the CURLOPT_MAXFILESIZE_LARGE option is not sufficient to guard against this.
asherkin@3839
  1228
Instead, the app should monitor the amount of data received within the
asherkin@3839
  1229
write or progress callback and abort once the limit is reached.
asherkin@3839
  1230
asherkin@3839
  1231
A malicious HTTP server could cause an infinite redirection loop, causing a
asherkin@3839
  1232
denial-of-service. This can be mitigated by using the CURLOPT_MAXREDIRS
asherkin@3839
  1233
option.
asherkin@3839
  1234
asherkin@3839
  1235
.IP "Arbitrary Headers"
asherkin@3839
  1236
User-supplied data must be sanitized when used in options like
asherkin@3839
  1237
CURLOPT_USERAGENT, CURLOPT_HTTPHEADER, CURLOPT_POSTFIELDS and others that
asherkin@3839
  1238
are used to generate structured data. Characters like embedded carriage
asherkin@3839
  1239
returns or ampersands could allow the user to create additional headers or
asherkin@3839
  1240
fields that could cause malicious transactions.
asherkin@3839
  1241
asherkin@3839
  1242
.IP "Server-supplied Names"
asherkin@3839
  1243
A server can supply data which the application may, in some cases, use as
asherkin@3839
  1244
a file name. The curl command-line tool does this with --remote-header-name,
asherkin@3839
  1245
using the Content-disposition: header to generate a file name.  An application
asherkin@3839
  1246
could also use CURLINFO_EFFECTIVE_URL to generate a file name from a
asherkin@3839
  1247
server-supplied redirect URL. Special care must be taken to sanitize such
asherkin@3839
  1248
names to avoid the possibility of a malicious server supplying one like
asherkin@3839
  1249
"/etc/passwd", "\autoexec.bat" or even ".bashrc".
asherkin@3839
  1250
asherkin@3839
  1251
.IP "Server Certificates"
asherkin@3839
  1252
A secure application should never use the CURLOPT_SSL_VERIFYPEER option to
asherkin@3839
  1253
disable certificate validation. There are numerous attacks that are enabled
asherkin@3839
  1254
by apps that fail to properly validate server TLS/SSL certificates,
asherkin@3839
  1255
thus enabling a malicious server to spoof a legitimate one. HTTPS without
asherkin@3839
  1256
validated certificates is potentially as insecure as a plain HTTP connection.
dvander@2518
  1257
dvander@2518
  1258
.IP "Showing What You Do"
dvander@2518
  1259
On a related issue, be aware that even in situations like when you have
dvander@2518
  1260
problems with libcurl and ask someone for help, everything you reveal in order
dvander@2518
  1261
to get best possible help might also impose certain security related
asherkin@3839
  1262
risks. Host names, user names, paths, operating system specifics, etc (not to
dvander@2518
  1263
mention passwords of course) may in fact be used by intruders to gain
dvander@2518
  1264
additional information of a potential target.
dvander@2518
  1265
dvander@2518
  1266
To avoid this problem, you must of course use your common sense. Often, you
dvander@2518
  1267
can just edit out the sensitive data or just search/replace your true
dvander@2518
  1268
information with faked data.
dvander@2518
  1269
dvander@2518
  1270
.SH "Multiple Transfers Using the multi Interface"
dvander@2518
  1271
dvander@2518
  1272
The easy interface as described in detail in this document is a synchronous
asherkin@3839
  1273
interface that transfers one file at a time and doesn't return until it is
dvander@2518
  1274
done.
dvander@2518
  1275
asherkin@3839
  1276
The multi interface, on the other hand, allows your program to transfer
dvander@2518
  1277
multiple files in both directions at the same time, without forcing you
dvander@2518
  1278
to use multiple threads.  The name might make it seem that the multi
dvander@2518
  1279
interface is for multi-threaded programs, but the truth is almost the
dvander@2518
  1280
reverse.  The multi interface can allow a single-threaded application
dvander@2518
  1281
to perform the same kinds of multiple, simultaneous transfers that
dvander@2518
  1282
multi-threaded programs can perform.  It allows many of the benefits
dvander@2518
  1283
of multi-threaded transfers without the complexity of managing and
dvander@2518
  1284
synchronizing many threads.
dvander@2518
  1285
dvander@2518
  1286
To use this interface, you are better off if you first understand the basics
dvander@2518
  1287
of how to use the easy interface. The multi interface is simply a way to make
asherkin@3839
  1288
multiple transfers at the same time by adding up multiple easy handles into
dvander@2518
  1289
a "multi stack".
dvander@2518
  1290
dvander@2518
  1291
You create the easy handles you want and you set all the options just like you
dvander@2518
  1292
have been told above, and then you create a multi handle with
dvander@2518
  1293
\fIcurl_multi_init(3)\fP and add all those easy handles to that multi handle
dvander@2518
  1294
with \fIcurl_multi_add_handle(3)\fP.
dvander@2518
  1295
dvander@2518
  1296
When you've added the handles you have for the moment (you can still add new
asherkin@3839
  1297
ones at any time), you start the transfers by calling
dvander@2518
  1298
\fIcurl_multi_perform(3)\fP.
dvander@2518
  1299
dvander@2518
  1300
\fIcurl_multi_perform(3)\fP is asynchronous. It will only execute as little as
dvander@2518
  1301
possible and then return back control to your program. It is designed to never
asherkin@3839
  1302
block.
dvander@2518
  1303
dvander@2518
  1304
The best usage of this interface is when you do a select() on all possible
dvander@2518
  1305
file descriptors or sockets to know when to call libcurl again. This also
dvander@2518
  1306
makes it easy for you to wait and respond to actions on your own application's
dvander@2518
  1307
sockets/handles. You figure out what to select() for by using
dvander@2518
  1308
\fIcurl_multi_fdset(3)\fP, that fills in a set of fd_set variables for you
dvander@2518
  1309
with the particular file descriptors libcurl uses for the moment.
dvander@2518
  1310
dvander@2518
  1311
When you then call select(), it'll return when one of the file handles signal
dvander@2518
  1312
action and you then call \fIcurl_multi_perform(3)\fP to allow libcurl to do
dvander@2518
  1313
what it wants to do. Take note that libcurl does also feature some time-out
asherkin@3839
  1314
code so we advise you to never use very long timeouts on select() before you
dvander@2518
  1315
call \fIcurl_multi_perform(3)\fP, which thus should be called unconditionally
dvander@2518
  1316
every now and then even if none of its file descriptors have signaled
dvander@2518
  1317
ready. Another precaution you should use: always call
dvander@2518
  1318
\fIcurl_multi_fdset(3)\fP immediately before the select() call since the
dvander@2518
  1319
current set of file descriptors may change when calling a curl function.
dvander@2518
  1320
dvander@2518
  1321
If you want to stop the transfer of one of the easy handles in the stack, you
dvander@2518
  1322
can use \fIcurl_multi_remove_handle(3)\fP to remove individual easy
dvander@2518
  1323
handles. Remember that easy handles should be \fIcurl_easy_cleanup(3)\fPed.
dvander@2518
  1324
dvander@2518
  1325
When a transfer within the multi stack has finished, the counter of running
dvander@2518
  1326
transfers (as filled in by \fIcurl_multi_perform(3)\fP) will decrease. When
dvander@2518
  1327
the number reaches zero, all transfers are done.
dvander@2518
  1328
dvander@2518
  1329
\fIcurl_multi_info_read(3)\fP can be used to get information about completed
dvander@2518
  1330
transfers. It then returns the CURLcode for each easy transfer, to allow you
dvander@2518
  1331
to figure out success on each individual transfer.
dvander@2518
  1332
dvander@2518
  1333
.SH "SSL, Certificates and Other Tricks"
dvander@2518
  1334
dvander@2518
  1335
 [ seeding, passwords, keys, certificates, ENGINE, ca certs ]
dvander@2518
  1336
dvander@2518
  1337
.SH "Sharing Data Between Easy Handles"
asherkin@3839
  1338
You can share some data between easy handles when the easy interface is used,
asherkin@3839
  1339
and some data is share automatically when you use the multi interface.
dvander@2518
  1340
asherkin@3839
  1341
When you add easy handles to a multi handle, these easy handles will
asherkin@3839
  1342
automatically share a lot of the data that otherwise would be kept on a
asherkin@3839
  1343
per-easy handle basis when the easy interface is used.
dvander@2518
  1344
asherkin@3839
  1345
The DNS cache is shared between handles within a multi handle, making
asherkin@3839
  1346
subsequent name resolvings faster and the connection pool that is kept to
asherkin@3839
  1347
better allow persistent connections and connection re-use is shared. If you're
asherkin@3839
  1348
using the easy interface, you can still share these between specific easy
asherkin@3839
  1349
handles by using the share interface, see \fIlibcurl-share(3)\fP.
asherkin@3839
  1350
asherkin@3839
  1351
Some things are never shared automatically, not within multi handles, like for
asherkin@3839
  1352
example cookies so the only way to share that is with the share interface.
dvander@2518
  1353
.SH "Footnotes"
dvander@2518
  1354
dvander@2518
  1355
.IP "[1]"
dvander@2518
  1356
libcurl 7.10.3 and later have the ability to switch over to chunked
asherkin@3839
  1357
Transfer-Encoding in cases where HTTP uploads are done with data of an unknown
dvander@2518
  1358
size.
dvander@2518
  1359
.IP "[2]"
dvander@2518
  1360
This happens on Windows machines when libcurl is built and used as a
dvander@2518
  1361
DLL. However, you can still do this on Windows if you link with a static
dvander@2518
  1362
library.
dvander@2518
  1363
.IP "[3]"
asherkin@3839
  1364
The curl-config tool is generated at build-time (on UNIX-like systems) and
dvander@2518
  1365
should be installed with the 'make install' or similar instruction that
dvander@2518
  1366
installs the library, header files, man pages etc.
asherkin@3839
  1367
.IP "[4]"
asherkin@3839
  1368
This behavior was different in versions before 7.17.0, where strings had to
asherkin@3839
  1369
remain valid past the end of the \fIcurl_easy_setopt(3)\fP call.