aboutsummaryrefslogtreecommitdiff
path: root/doc/chapters/tlsauthentication.inc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/chapters/tlsauthentication.inc')
-rw-r--r--doc/chapters/tlsauthentication.inc172
1 files changed, 171 insertions, 1 deletions
diff --git a/doc/chapters/tlsauthentication.inc b/doc/chapters/tlsauthentication.inc
index 125d4eb6..4f9c4443 100644
--- a/doc/chapters/tlsauthentication.inc
+++ b/doc/chapters/tlsauthentication.inc
@@ -105,6 +105,7 @@ The rest consists of little new besides some additional memory cleanups.
105 105
106The rather unexciting file loader can be found in the complete example @code{tlsauthentication.c}. 106The rather unexciting file loader can be found in the complete example @code{tlsauthentication.c}.
107 107
108
108@heading Remarks 109@heading Remarks
109@itemize @bullet 110@itemize @bullet
110@item 111@item
@@ -126,5 +127,174 @@ hardcode certificates in embedded devices.
126The cryptographic facilities consume memory space and computing time. For this reason, websites usually consists 127The cryptographic facilities consume memory space and computing time. For this reason, websites usually consists
127both of uncritically @emph{HTTP} parts and secured @emph{HTTPS}. 128both of uncritically @emph{HTTP} parts and secured @emph{HTTPS}.
128 129
129
130@end itemize 130@end itemize
131
132
133@heading Client authentication
134
135You can also use MHD to authenticate the client via SSL/TLS certificates
136(as an alternative to using the password-based Basic or Digest authentication).
137To do this, you will need to link your application against @emph{gnutls}.
138For this, you first need to obtain the raw GnuTLS session handle from
139@emph{MHD} using @code{MHD_get_connection_info}.
140
141@verbatim
142#include <gnutls/gnutls.h>
143#include <gnutls/x509.h>
144
145gnutls_session_t tls_session;
146tls_session = MHD_get_connection_info (connection,
147 MHD_CONNECTION_INFO_GNUTLS_SESSION);
148@end verbatim
149
150You can then extract the client certificate:
151
152@verbatim
153/**
154 * Get the client's certificate
155 *
156 * @param tls_session the TLS session
157 * @return NULL if no valid client certificate could be found, a pointer
158 * to the certificate if found
159 */
160static gnutls_x509_crt_t
161get_client_certificate (gnutls_session_t tls_session)
162{
163 unsigned int listsize;
164 const gnutls_datum_t * pcert;
165 gnutls_certificate_status_t client_cert_status;
166 gnutls_x509_crt_t client_cert;
167
168 if (tls_session == NULL)
169 return NULL;
170 if (gnutls_certificate_verify_peers2(tls_session,
171 &client_cert_status))
172 return NULL;
173 pcert = gnutls_certificate_get_peers(tls_session,
174 &listsize);
175 if ( (pcert == NULL) ||
176 (listsize == 0))
177 {
178 fprintf (stderr,
179 "Failed to retrieve client certificate chain\n");
180 return NULL;
181 }
182 if (gnutls_x509_crt_init(&client_cert))
183 {
184 fprintf (stderr,
185 "Failed to initialize client certificate\n");
186 return NULL;
187 }
188 /* Note that by passing values between 0 and listsize here, you
189 can get access to the CA's certs */
190 if (gnutls_x509_crt_import(client_cert,
191 &pcert[0],
192 GNUTLS_X509_FMT_DER))
193 {
194 fprintf (stderr,
195 "Failed to import client certificate\n");
196 gnutls_x509_crt_deinit(client_cert);
197 return NULL;
198 }
199 return client_cert;
200}
201@end verbatim
202
203Using the client certificate, you can then get the client's distinguished name
204and alternative names:
205
206@verbatim
207/**
208 * Get the distinguished name from the client's certificate
209 *
210 * @param client_cert the client certificate
211 * @return NULL if no dn or certificate could be found, a pointer
212 * to the dn if found
213 */
214char *
215cert_auth_get_dn(gnutls_x509_crt_c client_cert)
216{
217 char* buf;
218 size_t lbuf;
219
220 lbuf = 0;
221 gnutls_x509_crt_get_dn(client_cert, NULL, &lbuf);
222 buf = malloc(lbuf);
223 if (buf == NULL)
224 {
225 fprintf (stderr,
226 "Failed to allocate memory for certificate dn\n");
227 return NULL;
228 }
229 gnutls_x509_crt_get_dn(client_cert, buf, &lbuf);
230 return buf;
231}
232
233
234/**
235 * Get the alternative name of specified type from the client's certificate
236 *
237 * @param client_cert the client certificate
238 * @param nametype The requested name type
239 * @param index The position of the alternative name if multiple names are
240 * matching the requested type, 0 for the first matching name
241 * @return NULL if no matching alternative name could be found, a pointer
242 * to the alternative name if found
243 */
244char *
245MHD_cert_auth_get_alt_name(gnutls_x509_crt_t client_cert,
246 int nametype,
247 unsigned int index)
248{
249 char* buf;
250 size_t lbuf;
251 unsigned int seq;
252 unsigned int subseq;
253 unsigned int type;
254 int result;
255
256 subseq = 0;
257 for (seq=0;;seq++)
258 {
259 lbuf = 0;
260 result = gnutls_x509_crt_get_subject_alt_name2(client_cert, seq, NULL, &lbuf,
261 &type, NULL);
262 if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
263 return NULL;
264 if (nametype != (int) type)
265 continue;
266 if (subseq == index)
267 break;
268 subseq++;
269 }
270 buf = malloc(lbuf);
271 if (buf == NULL)
272 {
273 fprintf (stderr,
274 "Failed to allocate memory for certificate alt name\n");
275 return NULL;
276 }
277 result = gnutls_x509_crt_get_subject_alt_name2(client_cert,
278 seq,
279 buf,
280 &lbuf,
281 NULL, NULL);
282 if (result != nametype)
283 {
284 fprintf (stderr,
285 "Unexpected return value from gnutls: %d\n",
286 result);
287 free (buf);
288 return NULL;
289 }
290 return buf;
291}
292@end verbatim
293
294Finally, you should release the memory associated with the client
295certificate:
296
297@verbatim
298gnutls_x509_crt_deinit (client_cert);
299@end verbatim
300