* limitations under the License.
*/
+#define _GNU_SOURCE
+#define _XOPEN_SOURCE 700
+#include <strings.h>
#include "uhttpd.h"
static LIST_HEAD(auth_realms);
struct auth_realm *new = NULL;
struct passwd *pwd;
const char *new_pass = NULL;
+ char *dest_path, *dest_user, *dest_pass;
#ifdef HAVE_SHADOW
struct spwd *spwd;
if (!new_pass || !new_pass[0])
return;
- new = calloc(1, sizeof(*new));
+ new = calloc_a(sizeof(*new),
+ &dest_path, strlen(path) + 1,
+ &dest_user, strlen(user) + 1,
+ &dest_pass, strlen(new_pass) + 1);
+
if (!new)
return;
- snprintf(new->path, sizeof(new->path), "%s", path);
- snprintf(new->user, sizeof(new->user), "%s", user);
- snprintf(new->pass, sizeof(new->user), "%s", new_pass);
+ new->path = strcpy(dest_path, path);
+ new->user = strcpy(dest_user, user);
+ new->pass = strcpy(dest_pass, new_pass);
list_add(&new->list, &auth_realms);
}
+
+bool uh_auth_check(struct client *cl, struct path_info *pi)
+{
+ struct http_request *req = &cl->request;
+ struct auth_realm *realm;
+ bool user_match = false;
+ char *user = NULL;
+ char *pass = NULL;
+ int plen;
+
+ if (pi->auth && !strncasecmp(pi->auth, "Basic ", 6)) {
+ const char *auth = pi->auth + 6;
+
+ uh_b64decode(uh_buf, sizeof(uh_buf), auth, strlen(auth));
+ pass = strchr(uh_buf, ':');
+ if (pass) {
+ user = uh_buf;
+ *pass++ = 0;
+ }
+ }
+
+ req->realm = NULL;
+ plen = strlen(pi->name);
+ list_for_each_entry(realm, &auth_realms, list) {
+ int rlen = strlen(realm->path);
+
+ if (plen < rlen)
+ continue;
+
+ if (strncasecmp(pi->name, realm->path, rlen) != 0)
+ continue;
+
+ req->realm = realm;
+ if (!user)
+ break;
+
+ if (strcmp(user, realm->user) != 0)
+ continue;
+
+ user_match = true;
+ break;
+ }
+
+ if (!req->realm)
+ return true;
+
+ if (user_match && !strcmp(crypt(pass, realm->pass), realm->pass))
+ return true;
+
+ uh_http_header(cl, 401, "Authorization Required");
+ ustream_printf(cl->us,
+ "WWW-Authenticate: Basic realm=\"%s\"\r\n"
+ "Content-Type: text/plain\r\n\r\n",
+ conf.realm);
+ uh_chunk_printf(cl, "Authorization Required\n");
+ uh_request_done(cl);
+
+ return false;
+}