1 /*
2    HTTP authentication routines
3    Copyright (C) 1999-2021, Joe Orton <joe@manyfish.co.uk>
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public
16    License along with this library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18    MA 02111-1307, USA
19 
20 */
21 
22 #ifndef NE_AUTH_H
23 #define NE_AUTH_H
24 
25 #include "ne_session.h" /* for ne_session */
26 
27 NE_BEGIN_DECLS
28 
29 /* Size of username/password buffers passed to ne_auth_creds
30  * callback. */
31 #define NE_ABUFSIZ (256)
32 
33 /* The callback used to request the username and password in the given
34  * realm. The username and password must be copied into the buffers
35  * which are both of size NE_ABUFSIZ.  The 'attempt' parameter is zero
36  * on the first call to the callback, and increases by one for each
37  * invocation of the callback during an attempt to authenticate.
38  *
39  * The callback must return zero to indicate that authentication
40  * should be attempted with the username/password, or non-zero to
41  * cancel the request. (if non-zero, username and password are
42  * ignored.)
43  *
44  * IMPORTANT NOTE: The callback will be invoked repeatedly until
45  * either it returns non-zero, or authentication is successful.
46  *
47  * Hint: if you just wish to attempt authentication just once (even if
48  * the user gets the username/password wrong), have the callback
49  * function use 'attempt' value as the function return value. */
50 typedef int (*ne_auth_creds)(void *userdata, const char *realm, int attempt,
51 			     char *username, char *password);
52 
53 /* Set callbacks to provide credentials for server and proxy
54  * authentication, using the default set of authentication protocols.
55  * userdata is passed as the first argument to the callback. */
56 void ne_set_server_auth(ne_session *sess, ne_auth_creds creds, void *userdata);
57 void ne_set_proxy_auth(ne_session *sess, ne_auth_creds creds, void *userdata);
58 
59 /* As an alternative to using ne_set_server_auth and
60  * ne_set_proxy_auth, the following interfaces may be used; these
61  * allow control over which authentication protocol is used. */
62 
63 /* NE_AUTH_BASIC: Basic authentication transmits the username and
64  * password unprotected over the channel; this allows a passive attack
65  * to steal the credentials if using an unsecured channel
66  * (i.e. non-SSL). */
67 #define NE_AUTH_BASIC (0x0001)
68 
69 /* NE_AUTH_DIGEST: Digest authentication uses a hash of the username,
70  * password, and certain aspects of the request, so prevents passive
71  * attackers from obtaining the credentials; active attackers can
72  * still modify most of the request/response if using an unsecured
73  * channel.  Supports algorithms from RFC 2617 and RFC 7616. */
74 #define NE_AUTH_DIGEST (0x0080)
75 
76 /* NE_AUTH_LEGACY_DIGEST: Using this flag together with NE_AUTH_DIGEST
77  * enables support for the weaker, legacy version of the Digest
78  * algorithm specified in RFC 2069 (obsoleted by RFC 2617, which was
79  * published in June 1999).  */
80 #define NE_AUTH_LEGACY_DIGEST (0x0002)
81 
82 /* NE_AUTH_NEGOTIATE: Negotiate uses GSSAPI/SSPI, or NTLM, to
83  * authenticate the user; an active attacker can modify any of the
84  * request/response at will, so this must not be used over an
85  * unsecured channel.  NE_AUTH_NEGOTIATE is currently equivalent to
86  * use of (NE_AUTH_GSSAPI | NE_AUTH_NTLM). */
87 #define NE_AUTH_NEGOTIATE (0x0004)
88 
89 /* NE_AUTH_GSSAPI: Use GSSAPI or SSPI to authenticate the user; an
90  * active attacker can modify any of the request/response at will, so
91  * this must not be used over an unsecured channel. NE_AUTH_GSSAPI
92  * is currently equivalent to (NE_AUTH_GSSAPI_ONLY | NE_AUTH_SSPI). */
93 #define NE_AUTH_GSSAPI (0x0008)
94 
95 /* NE_AUTH_NTLM: Use NTLM to authenticate the user; an active attacker
96  * can modify any of the request/response at will, so this must not be
97  * used over an unsecured channel. */
98 #define NE_AUTH_NTLM (0x0010)
99 
100 /* NE_AUTH_SSPI: Use SSPI to authenticate the user; an
101  * active attacker can modify any of the request/response at will, so
102  * this must not be used over an unsecured channel. */
103 #define NE_AUTH_SSPI (0x0020)
104 
105 /* NE_AUTH_GSSAPI_ONLY: Use GSSAPI to authenticate the user; an
106  * active attacker can modify any of the request/response at will, so
107  * this must not be used over an unsecured channel. */
108 #define NE_AUTH_GSSAPI_ONLY (0x0040)
109 
110 /* 0x0080: legacy definition of NE_AUTH_DIGEST in 0.31 and earlier */
111 
112 /* The default set of supported protocols, as deemed appropriate for
113  * the given session scheme.  The interpretation of this flag may
114  * change across versions, for example with older, less secure
115  * protocols being removed from the default set. */
116 #define NE_AUTH_DEFAULT (0x1000)
117 
118 /* All protocols supported by the library. The interpretation of this
119  * flag may change across versions. */
120 #define NE_AUTH_ALL (0x2000)
121 
122 /* If present in the protocol mask passed to ne_auth_provide,
123  * indicates that proxy authentication is requested. */
124 #define NE_AUTH_PROXY (0x4000)
125 
126 /* Add a callback to provide credentials for server and proxy
127  * authentication using a particular auth protocol or set of
128  * protocols.  The protocol is supplied as a bitmask of NE_AUTH_*
129  * values.  For NE_AUTH_NEGOTIATE, the creds and userdata arguments
130  * are ignored and may be NULL.
131  *
132  * These functions may be called multiple times per session to
133  * register callbacks for different protocols.  If the server presents
134  * more than one protocol in an auth challenge, the following
135  * algorithm will be used to determine which callback is used:
136  *
137  * - iterate over the registered callbacks in the order registered
138  * - for each each callback, iterate over the known set of protocols
139  *   in order of algorithm strength (strongest first).
140  * - if the protocol mask for that callback matches the protocol,
141  *   attempt authentication using this protocol.
142  *
143  * Therefore, if multiple calls to ne_add_server_auth or
144  * ne_add_proxy_auth are used for a given session, the caller must
145  * ensure that the order in which those calls are made reflects the
146  * precedence of protocols to be used. */
147 void ne_add_server_auth(ne_session *sess, unsigned protocol,
148                         ne_auth_creds creds, void *userdata);
149 void ne_add_proxy_auth(ne_session *sess, unsigned protocol,
150                        ne_auth_creds creds, void *userdata);
151 
152 /* Alternative credentials provider callback, invoked when credentials
153  * are required to authenticate the client to either a server or
154  * proxy.  'protocol' is the authentication protocol number
155  * (NE_AUTH_*) of the challenge, bitwise-ORed with NE_AUTH_PROXY when
156  * the auth challenge is made by an HTTP proxy.
157  *
158  * 'realm' is the realm name.  The 'attempt' counter reflects the
159  * number of attempts to provide credentials to the server
160  * (i.e. retried requests sent with a challenge response), NOT the
161  * number of times the callback is invoked, unlike the ne_auth_creds
162  * callback.
163  *
164  * The callback must return zero to indicate that authentication
165  * should be attempted with the username/password, or non-zero to
166  * cancel the request. (if non-zero, username and password are
167  * ignored.)
168  *
169  * The username and password buffers have length 'buflen', which is
170  * guaranteed to be >= NE_ABUFSIZ.  The username must be provided as a
171  * NUL-terminated UTF-8 encoding only.  The password must be provided
172  * as a NUL-terminated string.  Additional protocol-specific
173  * restrictions apply, e.g. username cannot contain a colon for Basic
174  * auth.
175  *
176  * IMPORTANT NOTE: The callback will be invoked repeatedly until
177  * either it returns non-zero, or authentication is successful.
178  *
179  * Hint: if you just wish to attempt authentication just once (even if
180  * the user gets the username/password wrong), have the callback
181  * function use 'attempt' value as the function return value. */
182 typedef int (*ne_auth_provide)(void *userdata, int attempt,
183                                unsigned protocol, const char *realm,
184                                char *username, char *password, size_t buflen);
185 
186 void ne_add_auth(ne_session *sess, unsigned protocol,
187                  ne_auth_provide creds, void *userdata);
188 
189 /* Clear any cached authentication credentials for the given
190  * session. */
191 void ne_forget_auth(ne_session *sess);
192 
193 NE_END_DECLS
194 
195 #endif /* NE_AUTH_H */
196