GNU libmicrohttpd  1.0.1
basicauth.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2010, 2011, 2012 Daniel Pittman and Christian Grothoff
4  Copyright (C) 2014-2023 Evgeny Grin (Karlson2k)
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
27 #include "basicauth.h"
28 #include "gen_auth.h"
29 #include "platform.h"
30 #include "mhd_limits.h"
31 #include "internal.h"
32 #include "mhd_compat.h"
33 #include "mhd_str.h"
34 
35 
50 {
51  const struct MHD_RqBAuth *params;
52  size_t decoded_max_len;
53  struct MHD_BasicAuthInfo *ret;
54 
55  params = MHD_get_rq_bauth_params_ (connection);
56 
57  if (NULL == params)
58  return NULL;
59 
60  if ((NULL == params->token68.str) || (0 == params->token68.len))
61  return NULL;
62 
63  decoded_max_len = MHD_base64_max_dec_size_ (params->token68.len);
64  ret = (struct MHD_BasicAuthInfo *) malloc (sizeof(struct MHD_BasicAuthInfo)
65  + decoded_max_len + 1);
66  if (NULL != ret)
67  {
68  size_t decoded_len;
69  char *decoded;
70 
71  decoded = (char *) (ret + 1);
72  decoded_len = MHD_base64_to_bin_n (params->token68.str, params->token68.len,
73  decoded, decoded_max_len);
74  mhd_assert (decoded_max_len >= decoded_len);
75  if (0 != decoded_len)
76  {
77  size_t username_len;
78  char *colon;
79 
80  colon = memchr (decoded, ':', decoded_len);
81  if (NULL != colon)
82  {
83  size_t password_pos;
84  size_t password_len;
85 
86  username_len = (size_t) (colon - decoded);
87  password_pos = username_len + 1;
88  password_len = decoded_len - password_pos;
89  ret->password = decoded + password_pos;
90  ret->password[password_len] = 0; /* Zero-terminate the string */
92  }
93  else
94  {
95  username_len = decoded_len;
96  ret->password = NULL;
97  ret->password_len = 0;
98  }
99  ret->username = decoded;
100  ret->username[username_len] = 0; /* Zero-terminate the string */
101  ret->username_len = username_len;
102 
103  return ret; /* Success exit point */
104  }
105 #ifdef HAVE_MESSAGES
106  else
107  MHD_DLOG (connection->daemon,
108  _ ("Error decoding Basic Authorization authentication.\n"));
109 #endif /* HAVE_MESSAGES */
110 
111  free (ret);
112  }
113 #ifdef HAVE_MESSAGES
114  else
115  {
116  MHD_DLOG (connection->daemon,
117  _ ("Failed to allocate memory to process " \
118  "Basic Authorization authentication.\n"));
119  }
120 #endif /* HAVE_MESSAGES */
121 
122  return NULL; /* Failure exit point */
123 }
124 
125 
136 _MHD_EXTERN char *
138  char **password)
139 {
140  struct MHD_BasicAuthInfo *info;
141 
142  info = MHD_basic_auth_get_username_password3 (connection);
143  if (NULL == info)
144  return NULL;
145 
146  /* For backward compatibility this function must return NULL if
147  * no password is provided */
148  if (NULL != info->password)
149  {
150  char *username;
151 
152  username = malloc (info->username_len + 1);
153  if (NULL != username)
154  {
155  memcpy (username, info->username, info->username_len + 1);
156  mhd_assert (0 == username[info->username_len]);
157  if (NULL != password)
158  {
159  *password = malloc (info->password_len + 1);
160  if (NULL != *password)
161  {
162  memcpy (*password, info->password, info->password_len + 1);
163  mhd_assert (0 == (*password)[info->password_len]);
164 
165  free (info);
166  return username; /* Success exit point */
167  }
168 #ifdef HAVE_MESSAGES
169  else
170  MHD_DLOG (connection->daemon,
171  _ ("Failed to allocate memory.\n"));
172 #endif /* HAVE_MESSAGES */
173  }
174  else
175  {
176  free (info);
177  return username; /* Success exit point */
178  }
179 
180  free (username);
181  }
182 #ifdef HAVE_MESSAGES
183  else
184  MHD_DLOG (connection->daemon,
185  _ ("Failed to allocate memory.\n"));
186 #endif /* HAVE_MESSAGES */
187 
188  }
189  free (info);
190  if (NULL != password)
191  *password = NULL;
192  return NULL; /* Failure exit point */
193 }
194 
195 
224  const char *realm,
225  int prefer_utf8,
226  struct MHD_Response *response)
227 {
228  static const char prefix[] = "Basic realm=\"";
229  static const char suff_charset[] = "\", charset=\"UTF-8\"";
230  static const size_t prefix_len = MHD_STATICSTR_LEN_ (prefix);
231  static const size_t suff_simple_len = MHD_STATICSTR_LEN_ ("\"");
232  static const size_t suff_charset_len =
233  MHD_STATICSTR_LEN_ (suff_charset);
234  enum MHD_Result ret;
235  char *h_str;
236  size_t h_maxlen;
237  size_t suffix_len;
238  size_t realm_len;
239  size_t realm_quoted_len;
240  size_t pos;
241 
242  if (NULL == response)
243  return MHD_NO;
244 
245  suffix_len = (0 == prefer_utf8) ? suff_simple_len : suff_charset_len;
246  realm_len = strlen (realm);
247  h_maxlen = prefix_len + realm_len * 2 + suffix_len;
248 
249  h_str = (char *) malloc (h_maxlen + 1);
250  if (NULL == h_str)
251  {
252 #ifdef HAVE_MESSAGES
253  MHD_DLOG (connection->daemon,
254  "Failed to allocate memory for Basic Authentication header.\n");
255 #endif /* HAVE_MESSAGES */
256  return MHD_NO;
257  }
258  memcpy (h_str, prefix, prefix_len);
259  pos = prefix_len;
260  realm_quoted_len = MHD_str_quote (realm, realm_len, h_str + pos,
261  h_maxlen - prefix_len - suffix_len);
262  pos += realm_quoted_len;
263  mhd_assert (pos + suffix_len <= h_maxlen);
264  if (0 == prefer_utf8)
265  {
266  h_str[pos++] = '\"';
267  h_str[pos++] = 0; /* Zero terminate the result */
268  mhd_assert (pos <= h_maxlen + 1);
269  }
270  else
271  {
272  /* Copy with the final zero-termination */
273  mhd_assert (pos + suff_charset_len <= h_maxlen);
274  memcpy (h_str + pos, suff_charset, suff_charset_len + 1);
275  mhd_assert (0 == h_str[pos + suff_charset_len]);
276  }
277 
278  ret = MHD_add_response_header (response,
280  h_str);
281  free (h_str);
282  if (MHD_NO != ret)
283  {
284  ret = MHD_queue_response (connection,
286  response);
287  }
288  else
289  {
290 #ifdef HAVE_MESSAGES
291  MHD_DLOG (connection->daemon,
292  _ ("Failed to add Basic Authentication header.\n"));
293 #endif /* HAVE_MESSAGES */
294  }
295  return ret;
296 }
297 
298 
314  const char *realm,
315  struct MHD_Response *response)
316 {
317  return MHD_queue_basic_auth_required_response3 (connection, realm, MHD_NO,
318  response);
319 }
320 
321 
322 /* end of basicauth.c */
Declarations for HTTP authorisation general functions.
_MHD_EXTERN enum MHD_Result MHD_queue_basic_auth_fail_response(struct MHD_Connection *connection, const char *realm, struct MHD_Response *response)
Definition: basicauth.c:313
_MHD_EXTERN enum MHD_Result MHD_queue_basic_auth_required_response3(struct MHD_Connection *connection, const char *realm, int prefer_utf8, struct MHD_Response *response)
Definition: basicauth.c:223
_MHD_EXTERN char * MHD_basic_auth_get_username_password(struct MHD_Connection *connection, char **password)
Definition: basicauth.c:137
_MHD_EXTERN struct MHD_BasicAuthInfo * MHD_basic_auth_get_username_password3(struct MHD_Connection *connection)
Definition: basicauth.c:49
#define MHD_HTTP_HEADER_WWW_AUTHENTICATE
Definition: microhttpd.h:658
#define MHD_HTTP_UNAUTHORIZED
Definition: microhttpd.h:387
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:7850
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:620
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
#define NULL
Definition: reason_phrase.c:30
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:53
MHD internal shared structures.
Header for platform missing functions.
limits values definitions
Header for string manipulating helpers.
MHD_Result
Definition: microhttpd.h:158
@ MHD_NO
Definition: microhttpd.h:162
platform-specific includes for libmicrohttpd
struct MHD_Daemon * daemon
Definition: internal.h:675
struct _MHD_str_w_len token68
Definition: basicauth.h:40
const char * str
Definition: mhd_str_types.h:50