1 /*
2 This file is part of libmicrohttpd
3 Copyright (C) 2010, 2011, 2012 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 /**
20 * @file basicauth.c
21 * @brief Implements HTTP basic authentication methods
22 * @author Amr Ali
23 * @author Matthieu Speder
24 */
25 #include "platform.h"
26 #include <limits.h>
27 #include "internal.h"
28 #include "base64.h"
29
30 /**
31 * Beginning string for any valid Basic authentication header.
32 */
33 #define _BASIC_BASE "Basic "
34
35
36 /**
37 * Get the username and password from the basic authorization header sent by the client
38 *
39 * @param connection The MHD connection structure
40 * @param password a pointer for the password
41 * @return NULL if no username could be found, a pointer
42 * to the username if found
43 * @ingroup authentication
44 */
45 char *
MHD_basic_auth_get_username_password(struct MHD_Connection * connection,char ** password)46 MHD_basic_auth_get_username_password (struct MHD_Connection *connection,
47 char** password)
48 {
49 const char *header;
50 char *decode;
51 const char *separator;
52 char *user;
53
54 if ( (NULL == (header = MHD_lookup_connection_value (connection,
55 MHD_HEADER_KIND,
56 MHD_HTTP_HEADER_AUTHORIZATION))) ||
57 (0 != strncmp (header, _BASIC_BASE, strlen(_BASIC_BASE))) )
58 return NULL;
59 header += strlen (_BASIC_BASE);
60 if (NULL == (decode = BASE64Decode (header)))
61 {
62 #if HAVE_MESSAGES
63 MHD_DLOG (connection->daemon,
64 "Error decoding basic authentication\n");
65 #endif
66 return NULL;
67 }
68 /* Find user:password pattern */
69 if (NULL == (separator = strchr (decode, ':')))
70 {
71 #if HAVE_MESSAGES
72 MHD_DLOG(connection->daemon,
73 "Basic authentication doesn't contain ':' separator\n");
74 #endif
75 free (decode);
76 return NULL;
77 }
78 if (NULL == (user = strdup (decode)))
79 {
80 free (decode);
81 return NULL;
82 }
83 user[separator - decode] = '\0'; /* cut off at ':' */
84 if (NULL != password)
85 {
86 *password = strdup (separator + 1);
87 if (NULL == *password)
88 {
89 #if HAVE_MESSAGES
90 MHD_DLOG(connection->daemon,
91 "Failed to allocate memory for password\n");
92 #endif
93 free (decode);
94 free (user);
95 return NULL;
96 }
97 }
98 free (decode);
99 return user;
100 }
101
102
103 /**
104 * Queues a response to request basic authentication from the client.
105 * The given response object is expected to include the payload for
106 * the response; the "WWW-Authenticate" header will be added and the
107 * response queued with the 'UNAUTHORIZED' status code.
108 *
109 * @param connection The MHD connection structure
110 * @param realm the realm presented to the client
111 * @param response response object to modify and queue
112 * @return #MHD_YES on success, #MHD_NO otherwise
113 * @ingroup authentication
114 */
115 int
MHD_queue_basic_auth_fail_response(struct MHD_Connection * connection,const char * realm,struct MHD_Response * response)116 MHD_queue_basic_auth_fail_response (struct MHD_Connection *connection,
117 const char *realm,
118 struct MHD_Response *response)
119 {
120 int ret;
121 size_t hlen = strlen(realm) + strlen("Basic realm=\"\"") + 1;
122 char *header;
123
124 header = (char*)malloc(hlen);
125 if (NULL == header)
126 {
127 #if HAVE_MESSAGES
128 MHD_DLOG(connection->daemon,
129 "Failed to allocate memory for auth header\n");
130 #endif /* HAVE_MESSAGES */
131 return MHD_NO;
132 }
133 MHD_snprintf_ (header,
134 hlen,
135 "Basic realm=\"%s\"",
136 realm);
137 ret = MHD_add_response_header (response,
138 MHD_HTTP_HEADER_WWW_AUTHENTICATE,
139 header);
140 free(header);
141 if (MHD_YES == ret)
142 ret = MHD_queue_response (connection,
143 MHD_HTTP_UNAUTHORIZED,
144 response);
145 return ret;
146 }
147
148 /* end of basicauth.c */
149