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