Back to index

avfs  1.0.1
http_auth.h
Go to the documentation of this file.
00001 /* 
00002    HTTP authentication routines
00003    Copyright (C) 1999-2001, Joe Orton <joe@light.plus.com>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009    
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018    MA 02111-1307, USA
00019 
00020 */
00021 
00022 #ifndef HTTPAUTH_H
00023 #define HTTPAUTH_H
00024 
00025 #include <sys/types.h>
00026 
00027 #include "neon_md5.h"
00028 
00029 /* HTTP Authentication - a pretty complete client implementation of RFC2617.
00030  */
00031 
00032 /*
00033   To use:
00034  
00035  1. A session state variable (http_auth_session) is needed for each of
00036  server state and proxy state. These may be statically declared (use
00037  _init/_finish), or dynamically (use _create/_destroy).
00038  
00039  2. To begin a new session, call http_auth_init() or http_auth_create().
00040  Set up a callback function with http_auth_set_creds_cb() for
00041  supplying the username and password on demand. See below for details.
00042 
00043  3. Before sending a request, pass http_auth_new_request its details,
00044  on BOTH auth session variables if you are using a proxy server too.
00045  
00046  4. Call http_auth_request_header() and add your 'Authentication:'
00047  header to the request if returns non-NULL. Similarly for
00048  Proxy-Authentication.
00049  
00050  5. Send the request.
00051 
00052  6. Read the response:
00053   - Pass the value of the '(Proxy|WWW)-Authenticate' header to 
00054     http_auth_challenge.
00055   - If there is 'Authentication-Info', save its value for later.
00056   - Pass each block of the response entity-body to http_auth_response_body.
00057 
00058  7. After reading the complete response, if an Auth-Info header was
00059  received, pass its value to http_auth_verify_response to check
00060  whether the SERVER was authenticated okay, passing the saved value.
00061 
00062  8. If a 401 or a 407 response is received, retry once for each, by
00063  going back to step 3. Note that http_auth_new_request MUST be called
00064  again if the SAME request is being retried.
00065 
00066 */
00067 
00068 /* The authentication scheme we are using */
00069 typedef enum {
00070     http_auth_scheme_basic,
00071     http_auth_scheme_digest
00072 } http_auth_scheme;
00073 
00074 typedef enum { 
00075     http_auth_alg_md5,
00076     http_auth_alg_md5_sess,
00077     http_auth_alg_unknown
00078 } http_auth_algorithm;
00079 
00080 /* Selected method of qop which the client is using */
00081 typedef enum {
00082     http_auth_qop_none,
00083     http_auth_qop_auth,
00084     http_auth_qop_auth_int
00085 } http_auth_qop;
00086 
00087 /* The callback used to request the username and password in the given
00088  * realm. The username and password must be placed in malloc()-allocate
00089  * memory.
00090  * Must return:
00091  *   0 on success, 
00092  *  -1 to cancel.
00093  */
00094 typedef int (*http_auth_request_creds)(
00095     void *userdata, const char *realm,
00096     char **username, char **password);
00097 
00098 /* Authentication session state. */
00099 typedef struct {
00100     /* The scheme used for this authentication session */
00101     http_auth_scheme scheme;
00102     /* The callback used to request new username+password */
00103     http_auth_request_creds reqcreds;
00104     void *reqcreds_udata;
00105 
00106     /*** Session details ***/
00107 
00108     /* The username and password we are using to authenticate with */
00109     char *username;
00110     /* Whether we CAN supply authentication at the moment */
00111     unsigned int can_handle:1;
00112     /* This used for Basic auth */
00113     char *basic; 
00114     /* These all used for Digest auth */
00115     char *unq_realm;
00116     char *unq_nonce;
00117     char *unq_cnonce;
00118     char *opaque;
00119     /* A list of domain strings */
00120     unsigned int domain_count;
00121     char **domain;
00122     http_auth_qop qop;
00123     http_auth_algorithm alg;
00124     int nonce_count;
00125     /* The ASCII representation of the session's H(A1) value */
00126     char h_a1[33];
00127     /* Used for calculation of H(entity-body) of the response */
00128     struct md5_ctx response_body;
00129     /* Temporary store for half of the Request-Digest
00130      * (an optimisation - used in the response-digest calculation) */
00131     struct md5_ctx stored_rdig;
00132 
00133     /* Details of server... needed to reconstruct absoluteURI's when
00134      * necessary */
00135     const char *host;
00136     const char *uri_scheme;
00137     unsigned int port;
00138 
00139     /*** Details of current request ***/
00140 
00141     /* The method and URI we are using for the current request */
00142     const char *uri;
00143     const char *method;
00144     /* Whether we WILL supply authentication for this request or not */
00145     unsigned int will_handle:1;
00146     /* Whether we have a request body for the current request */
00147     unsigned int got_body:1;
00148     /* And what the body is - stream or buffer */
00149     FILE *body_stream;
00150     const char *body_buffer;
00151 
00152 } http_auth_session;
00153 
00154 /* Initializes the authentication state for the given session,
00155  * which will use the given username and password. */
00156 void http_auth_init(http_auth_session *sess);
00157 
00158 void http_auth_set_creds_cb(http_auth_session *sess,
00159                          http_auth_request_creds callback, void *userdata);
00160 
00161 /* Finishes off the given authentication session, freeing
00162  * any memory used. */
00163 void http_auth_finish(http_auth_session *sess);
00164 
00165 /* Creates a new authentication session.
00166  * Returns non-NULL on success */
00167 http_auth_session * http_auth_create(void);
00168 
00169 /* Destroys an authentication session, freeing the session state
00170  * itself too. */
00171 void http_auth_destroy(http_auth_session *sess); 
00172 
00173 /* Call this before sending a request.  Pass ONE OF body_buffer or
00174  * body_stream as non-NULL if the request will include an
00175  * entity-body. If body_buffer is non-NULL, it MUST be
00176  * \0-terminated. If body_stream is non-NULL, it may be read once
00177  * during http_auth_challenge, then rewound.  uri must identical to
00178  * Request-URI, EXCEPT for server auth state, where if the request is
00179  * passing through a proxy, then uri should be the same as abs_path.  */
00180 void http_auth_new_request(http_auth_session *sess,
00181                         const char *method, const char *uri,
00182                         const char *body_buffer, FILE *body_stream);
00183 
00184 /* Returns the value of the authentication field if one is to be sent,
00185  * else NULL. The return value will be taken from malloc()'ed memory,
00186  * so should be free()'ed after use. */
00187 char *http_auth_request_header(http_auth_session *sess);
00188 
00189 /* Pass this the value of the "(Proxy,WWW)-Authenticate: " header field.
00190  * Returns:
00191  *   0 if we can now authenticate ourselves with the server.
00192  *   non-zero if we can't
00193  */
00194 int http_auth_challenge(http_auth_session *sess, const char *value);
00195 
00196 /* As you receive sections of the response entity-body, pass them to 
00197  * this function. */
00198 void http_auth_response_body(http_auth_session *sess, 
00199                           const char *buffer, size_t buffer_len);
00200 
00201 /* If you receive a "(Proxy-)Authentication-Info:" header, pass its value to
00202  * this function. Returns zero if this successfully authenticates
00203  * the response as coming from the server, and false if it hasn't. */
00204 int http_auth_verify_response(http_auth_session *sess, const char *value);
00205 
00206 #endif /* HTTPAUTH_H */