Check buffer size in send_authorization_request()
Fixes issue #85
diff --git a/src/server/shttpd/auth.c b/src/server/shttpd/auth.c
index 55fbe56..cf70d23 100644
--- a/src/server/shttpd/auth.c
+++ b/src/server/shttpd/auth.c
@@ -387,39 +387,66 @@
return (ret);
}
-void
+int
send_authorization_request(struct conn *c)
{
- char buf[512];
- int n = 0;
+#define BUFSIZE 512
+ char buf[BUFSIZE];
+ char *bufptr = buf;
+ int n;
+ size_t remaining = BUFSIZE;
int b = 0, d = 0;
struct llhead *lp;
struct uri_auth *auth;
- n = snprintf(buf, sizeof(buf), "Unauthorized\r\n");
+ n = snprintf(bufptr, remaining, "Unauthorized\r\n");
+ bufptr += n;
+ remaining -= n;
LL_FOREACH(&c->ctx->uri_auths, lp) {
auth = LL_ENTRY(lp, struct uri_auth, link);
if (auth->type == DIGEST_AUTH && d == 0) {
if (b) {
- n += snprintf(buf +n, sizeof(buf) - n, "\r\n");
+ n = snprintf(bufptr, remaining, "\r\n");
+ if (n >= remaining) {
+ return -1;
+ }
+ bufptr += n;
+ remaining -= n;
}
- n += snprintf(buf+n, sizeof(buf) - n,
+ n = snprintf(bufptr, remaining,
"WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\", "
"nonce=\"%lu\"", c->ctx->auth_realm, (unsigned long) current_time);
+ if (n >= remaining) {
+ return -1;
+ }
+ bufptr += n;
+ remaining -= n;
d = 1;
}
if (auth->type == BASIC_AUTH && b == 0) {
if (d) {
- n += snprintf(buf +n, sizeof(buf) - n, "\r\n");
+ n = snprintf(bufptr, remaining, "\r\n");
+ if (n >= remaining) {
+ return -1;
+ }
+ bufptr += n;
+ remaining -= n;
}
- n += snprintf(buf+n, sizeof(buf) - n,
+ n = snprintf(bufptr, remaining,
"WWW-Authenticate: Basic realm=\"%s\"", c->ctx->auth_realm);
+ if (n >= remaining) {
+ return -1;
+ }
+ bufptr += n;
+ remaining -= n;
b = 1;
}
}
send_server_error(c, 401, buf);
+#undef BUFSIZE
+ return 0;
}
/*
diff --git a/src/server/shttpd/shttpd.c b/src/server/shttpd/shttpd.c
index 2266ae2..4aedf62 100644
--- a/src/server/shttpd/shttpd.c
+++ b/src/server/shttpd/shttpd.c
@@ -488,11 +488,14 @@
}
#if !defined(NO_AUTH)
- rc = check_authorization(c, path);
- if(rc != 1)
- {
- if(rc != 2) /* 2 = multipass auth (GSS)*/
- send_authorization_request(c);
+ rc = check_authorization(c, path);
+ if (rc != 1) {
+ if (rc != 2) { /* 2 = multipass auth (GSS)*/
+ if (send_authorization_request(c)) {
+ fprintf(stderr, "Digest realm overflows buffer\n");
+ return;
+ }
+ }
} else
#endif /* NO_AUTH */
#ifdef EMBEDDED
@@ -507,7 +510,10 @@
#if !defined(NO_AUTH)
if ((c->method == METHOD_PUT || c->method == METHOD_DELETE) &&
(c->ctx->put_auth_file == NULL || !is_authorized_for_put(c))) {
- send_authorization_request(c);
+ if (send_authorization_request(c)) {
+ fprintf(stderr, "Digest realm overflows buffer\n");
+ return;
+ }
} else
#endif /* NO_AUTH */
if (c->method == METHOD_PUT) {
diff --git a/src/server/shttpd/shttpd_defs.h b/src/server/shttpd/shttpd_defs.h
index 8c88fea..edcc5fd 100644
--- a/src/server/shttpd/shttpd_defs.h
+++ b/src/server/shttpd/shttpd_defs.h
@@ -480,7 +480,7 @@
*/
extern int check_authorization(struct conn *c, const char *path);
extern int is_authorized_for_put(struct conn *c);
-extern void send_authorization_request(struct conn *c);
+extern int send_authorization_request(struct conn *c);
extern int edit_passwords(const char *fname, const char *domain,
const char *user, const char *pass);