summaryrefslogtreecommitdiff
path: root/src/ne_session.h
blob: 58493bffc382bc006e956f6b1f21574927c515ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/* 
   HTTP session handling
   Copyright (C) 1999-2009, Joe Orton <joe@manyfish.co.uk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   MA 02111-1307, USA

*/

#ifndef NE_SESSION_H
#define NE_SESSION_H 1

#include <sys/types.h>

#include "ne_ssl.h"
#include "ne_uri.h" /* for ne_uri */
#include "ne_defs.h"
#include "ne_socket.h"

NE_BEGIN_DECLS

typedef struct ne_session_s ne_session;

/* Create a session to the given server, using the given scheme.  If
 * "https" is passed as the scheme, SSL will be used to connect to the
 * server. */
ne_session *ne_session_create(const char *scheme,
			      const char *hostname, unsigned int port);

/* Finish an HTTP session */
void ne_session_destroy(ne_session *sess);

/* Prematurely force the connection to be closed for the given
 * session. */
void ne_close_connection(ne_session *sess);

/* Configure an HTTP proxy server for the session.  This function will
 * override (remove) any proxy servers previously configured, and must
 * be called before any requests are created using this session. */
void ne_session_proxy(ne_session *sess,
		      const char *hostname, unsigned int port);

/* Configure a SOCKS proxy server which will be used for the session.
 * The SOCKS protocol version 'vers' will be used to contact the
 * proxy at given 'hostname' and 'port'.
 *
 * If SOCKSv4 or v4a are used, username must be non-NULL.  For v5,
 * username may be NULL, in which case, password is ignored.  If
 * username is non-NULL, password must also be non-NULL.
 *
 * This function will override (remove) any proxy servers previously
 * configured, and must be called before any requests are created
 * using this session. */
void ne_session_socks_proxy(ne_session *sess, enum ne_sock_sversion vers,
                            const char *hostname, unsigned int port,
                            const char *username, const char *password);

/* Configure use of proxy servers from any system-wide default sources
 * which are configured at build time.  This function will override
 * (remove) any proxy servers previously configured, and must be
 * called before any requests are created using this session.  The
 * 'flags' parameter must be zero.  */
void ne_session_system_proxy(ne_session *sess, unsigned int flags);

/* Defined session flags: */
typedef enum ne_session_flag_e {
    NE_SESSFLAG_PERSIST = 0, /* disable this flag to prevent use of
                              * persistent connections. */

    NE_SESSFLAG_ICYPROTO, /* enable this flag to enable support for
                           * non-HTTP ShoutCast-style "ICY" responses. */

    NE_SESSFLAG_SSLv2, /* disable this flag to disable support for
                        * SSLv2, if supported by the SSL library. */

    NE_SESSFLAG_RFC4918, /* enable this flag to enable support for
                          * RFC4918-only WebDAV features; losing
                          * backwards-compatibility with RFC2518
                          * servers. */

    NE_SESSFLAG_CONNAUTH, /* enable this flag if an awful, broken,
                           * RFC-violating, connection-based HTTP
                           * authentication scheme is in use. */

    NE_SESSFLAG_TLS_SNI, /* disable this flag to disable use of the
                          * TLS Server Name Indication extension. */

    NE_SESSFLAG_EXPECT100, /* enable this flag to enable the flag
                            * NE_REQFLAG_EXPECT100 for new requests. */

    NE_SESSFLAG_LAST /* enum sentinel value */
} ne_session_flag;

/* Set a new value for a particular session flag. */
void ne_set_session_flag(ne_session *sess, ne_session_flag flag, int value);

/* Return 0 if the given flag is not set, >0 it is set, or -1 if the
 * flag is not supported. */
int ne_get_session_flag(ne_session *sess, ne_session_flag flag);

/* Bypass the normal name resolution; force the use of specific set of
 * addresses for this session, addrs[0]...addrs[n-1].  The 'addrs'
 * array and pointed-to objects must remain valid until the session is
 * destroyed.  This function will override (remove) any proxy servers
 * previously configured, and must be called before any requests are
 * created using this session.  */
void ne_set_addrlist(ne_session *sess, const ne_inet_addr **addrs, size_t n);

/* Bypass the normal name resolution; force the use of specific set of
 * addresses for this session, addrs[0]...addrs[n-1].  The 'addrs'
 * array and pointed-to objects must remain valid until the session is
 * destroyed.  This function will override (remove) any proxy servers
 * previously configured, and must be called before any requests are
 * created using this session.  Port number 'port' will be used
 * instead of the "real" session port, to connect to the proxy. */
void ne_set_addrlist2(ne_session *sess, unsigned int port, 
                      const ne_inet_addr **addrs, size_t n);

/* Bind connections to the specified local address.  If the address
 * determined for the remote host has a different family (type) to
 * 'addr', 'addr' will be ignored.  The 'addr' object must remain
 * valid until the session is destroyed. */
void ne_set_localaddr(ne_session *sess, const ne_inet_addr *addr);

/* DEPRECATED: Progress callback. */
typedef void (*ne_progress)(void *userdata, ne_off_t progress, ne_off_t total);

/* DEPRECATED API: Set a progress callback for the session; this is
 * deprecated in favour of ne_set_notifier().  The progress callback
 * is invoked for after each block of the request and response body to
 * indicate request and response progress (there is no way to
 * distinguish between the two using this interface alone).
 * If progress is NULL, any existing callback is deregistered and will
 * no longer be invoked.
 *
 * NOTE: Use of this interface is mutually exclusive with the use of
 * ne_set_notifier().  A call to ne_set_progress() removes the
 * notifier callback, and vice versa. */
void ne_set_progress(ne_session *sess, ne_progress progress, void *userdata);

/* Store an opaque context for the session, 'priv' is returned by a
 * call to ne_session_get_private with the same ID. */
void ne_set_session_private(ne_session *sess, const char *id, void *priv);
void *ne_get_session_private(ne_session *sess, const char *id);

/* Status event type.  NOTE: More event types may be added in
 * subsequent releases, so callers must ignore unknown status types
 * for forwards-compatibility.  */
typedef enum {
    ne_status_lookup = 0, /* looking up hostname */
    ne_status_connecting, /* connecting to host */
    ne_status_connected, /* connected to host */
    ne_status_sending, /* sending a request body */
    ne_status_recving, /* receiving a response body */
    ne_status_disconnected /* disconnected from host */
} ne_session_status;

/* Status event information union; the relevant structure within
 * corresponds to the event type.  WARNING: the size of this union is
 * not limited by ABI constraint; it may be extended with additional
 * members of different size, or existing members may be extended. */
typedef union ne_session_status_info_u {
    struct /* ne_status_lookup */ {
        /* The hostname which is being resolved: */
        const char *hostname;
    } lu;
    struct /* ne_status_connecting */ {
        /* The hostname and network address to which a connection
         * attempt is being made: */
        const char *hostname;
        const ne_inet_addr *address;
    } ci;
    struct /* ne_status_connected, ne_status_disconnected */ {
        /* The hostname to which a connection has just been
         * established or closed: */
        const char *hostname;
    } cd;
    struct /* ne_status_sending and ne_status_recving */ {
        /* Request/response body transfer progress; if total == -1,
         * the total size is unknown; otherwise, total gives the total
         * number of bytes which will be transferred.  progress gives
         * the number of bytes transferred so far. */
        ne_off_t progress, total;
    } sr;
} ne_session_status_info;

/* Callback invoked to notify a new session status event, given by the
 * 'status' argument.  On invocation, the contents of exactly one of
 * the structures in the info union will be valid, as indicated
 * above. */
typedef void (*ne_notify_status)(void *userdata, ne_session_status status,
                                 const ne_session_status_info *info);

/* Set a status notification callback for the session, to report
 * session status events.  Only one notification callback per session
 * can be registered; the most recent of successive calls to this
 * function takes effect.  If status is NULL, any existing callback
 * is deregistered and will no longer be invoked.
 *
 * NOTE: Use of this interface is mutually exclusive with the use of
 * ne_set_progress().  A call to ne_set_notifier() removes the
 * progress callback, and vice versa. */
void ne_set_notifier(ne_session *sess, ne_notify_status status, void *userdata);

/* Certificate verification failures. */

/* NE_SSL_NOTYETVALID: the certificate is not yet valid. */
#define NE_SSL_NOTYETVALID (0x01)

/* NE_SSL_EXPIRED: the certificate has expired. */
#define NE_SSL_EXPIRED (0x02)

/* NE_SSL_IDMISMATCH: the hostname for which the certificate was
 * issued does not match the hostname of the server; this could mean
 * that the connection is being intercepted. */
#define NE_SSL_IDMISMATCH (0x04)

/* NE_SSL_UNTRUSTED: the certificate authority which signed the server
 * certificate is not trusted: there is no indicatation the server is
 * who they claim to be: */
#define NE_SSL_UNTRUSTED (0x08)

/* NE_SSL_BADCHAIN: the certificate chain contained a certificate
 * other than the server cert which failed verification for a reason
 * other than lack of trust; for example, due to a CA cert being
 * outside its validity period. */
#define NE_SSL_BADCHAIN (0x10)

/* N.B.: 0x20 is reserved. */

/* NE_SSL_REVOKED: the server certificate has been revoked by the
 * issuing authority. */
#define NE_SSL_REVOKED (0x40)

/* For purposes of forwards-compatibility, the bitmask of all
 * currently exposed failure bits is given as NE_SSL_FAILMASK.  If the
 * expression (failures & ~NE_SSL_FAILMASK) is non-zero a failure type
 * is present which the application does not recognize but must treat
 * as a verification failure nonetheless. */
#define NE_SSL_FAILMASK (0x5f)

/* A callback which is used when server certificate verification is
 * needed.  The reasons for verification failure are given in the
 * 'failures' parameter, which is a binary OR of one or more of the
 * above NE_SSL_* values. failures is guaranteed to be non-zero.  The
 * callback must return zero to accept the certificate: a non-zero
 * return value will fail the SSL negotiation. */
typedef int (*ne_ssl_verify_fn)(void *userdata, int failures,
				const ne_ssl_certificate *cert);

/* Install a callback to handle server certificate verification.  This
 * is required when the CA certificate is not known for the server
 * certificate, or the server cert has other verification problems. */
void ne_ssl_set_verify(ne_session *sess, ne_ssl_verify_fn fn, void *userdata);

/* Use the given client certificate for the session.  The client cert
 * MUST be in the decrypted state, otherwise behaviour is undefined.
 * The 'clicert' object is duplicated internally so can be destroyed
 * by the caller.  */
void ne_ssl_set_clicert(ne_session *sess, const ne_ssl_client_cert *clicert);

/* Indicate that the certificate 'cert' is trusted; the 'cert' object
 * is duplicated internally so can be destroyed by the caller.  This
 * function has no effect for non-SSL sessions. */
void ne_ssl_trust_cert(ne_session *sess, const ne_ssl_certificate *cert);

/* If the SSL library provided a default set of CA certificates, trust
 * this set of CAs. */
void ne_ssl_trust_default_ca(ne_session *sess);

/* Callback used to load a client certificate on demand.  If dncount
 * is > 0, the 'dnames' array dnames[0] through dnames[dncount-1]
 * gives the list of CA names which the server indicated were
 * acceptable.  The callback should load an appropriate client
 * certificate and then pass it to 'ne_ssl_set_clicert'. */
typedef void (*ne_ssl_provide_fn)(void *userdata, ne_session *sess,
				  const ne_ssl_dname *const *dnames,
                                  int dncount);

/* Register a function to be called when the server requests a client
 * certificate. */
void ne_ssl_provide_clicert(ne_session *sess, 
                            ne_ssl_provide_fn fn, void *userdata);

/* Set the timeout (in seconds) used when reading from a socket.  The
 * timeout value must be greater than zero. */
void ne_set_read_timeout(ne_session *sess, int timeout);

/* Set the timeout (in seconds) used when making a connection.  The
 * timeout value must be greater than zero. */
void ne_set_connect_timeout(ne_session *sess, int timeout);

/* Sets the user-agent string. neon/VERSION will be appended, to make
 * the full header "User-Agent: product neon/VERSION".
 * If this function is not called, the User-Agent header is not sent.
 * The product string must follow the RFC2616 format, i.e.
 *       product         = token ["/" product-version]
 *       product-version = token
 * where token is any alpha-numeric-y string [a-zA-Z0-9]* */
void ne_set_useragent(ne_session *sess, const char *product);

/* Returns non-zero if next-hop server does not claim compliance to
 * HTTP/1.1 or later. */
int ne_version_pre_http11(ne_session *sess);

/* Returns the 'hostport' URI segment for the end-server, e.g.
 * "my.server.com:8080". */
const char *ne_get_server_hostport(ne_session *sess);

/* Returns the URL scheme being used for the current session, omitting
 * the trailing ':'; e.g. "http" or "https". */
const char *ne_get_scheme(ne_session *sess);

/* Sets the host, scheme, and port fields of the given URI structure
 * to that of the configured server and scheme for the session; host
 * and scheme are malloc-allocated.  No other fields in the URI
 * structure are changed. */
void ne_fill_server_uri(ne_session *sess, ne_uri *uri);

/* If a proxy is configured, sets the host and port fields in the
 * given URI structure to that of the proxy.  If multiple proxies are
 * configured, the active is used if any, otherwise the first.  The
 * hostname is malloc-allocated.  No other fields in the URI structure
 * are changed; if no proxy is configured or a non-HTTP proxy is in
 * use, no fields are changed. */
void ne_fill_proxy_uri(ne_session *sess, ne_uri *uri);

/* Set the error string for the session; takes printf-like format
 * string. */
void ne_set_error(ne_session *sess, const char *format, ...)
    ne_attribute((format (printf, 2, 3)));

/* Retrieve the error string for the session */
const char *ne_get_error(ne_session *sess);

NE_END_DECLS

#endif /* NE_SESSION_H */