httpkadmind: Fix error clobbering
This commit is contained in:
@@ -80,6 +80,41 @@
|
|||||||
#define heim_pconfig krb5_context
|
#define heim_pconfig krb5_context
|
||||||
#include <heimbase-svc.h>
|
#include <heimbase-svc.h>
|
||||||
|
|
||||||
|
#define BODYLEN_IS_STRLEN (~0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Libmicrohttpd is not the easiest API to use. It's got issues.
|
||||||
|
*
|
||||||
|
* One of the issues is how responses are handled, and the return value of the
|
||||||
|
* resource handler (MHD_NO -> close the connection, MHD_YES -> send response).
|
||||||
|
* Note that the handler could return MHD_YES without having set an HTTP
|
||||||
|
* response.
|
||||||
|
*
|
||||||
|
* There's memory management issues as well.
|
||||||
|
*
|
||||||
|
* Here we have to be careful about return values.
|
||||||
|
*
|
||||||
|
* Some of the functions defined here return just a krb5_error_code without
|
||||||
|
* having set an HTTP response on error.
|
||||||
|
* Others do set an HTTP response on error.
|
||||||
|
* The convention is to either set an HTTP response on error, or not at all,
|
||||||
|
* but not a mix of errors where for some the function will set a response and
|
||||||
|
* for others it won't.
|
||||||
|
*
|
||||||
|
* We do use some system error codes to stand in for errors here.
|
||||||
|
* Specifically:
|
||||||
|
*
|
||||||
|
* - EACCES -> authorization failed
|
||||||
|
* - EINVAL -> bad API usage
|
||||||
|
* - ENOSYS -> missing CSRF token but CSRF token required
|
||||||
|
*
|
||||||
|
* FIXME: We should rely only on krb5_set_error_message() and friends and make
|
||||||
|
* error responses only in route(), mapping krb5_error_code values to
|
||||||
|
* HTTP status codes. This would simplify the error handling convention
|
||||||
|
* here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Our request description structure */
|
||||||
typedef struct kadmin_request_desc {
|
typedef struct kadmin_request_desc {
|
||||||
HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
|
HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
|
||||||
|
|
||||||
@@ -129,6 +164,7 @@ typedef struct kadmin_request_desc {
|
|||||||
char *freeme1;
|
char *freeme1;
|
||||||
char *enctypes;
|
char *enctypes;
|
||||||
const char *method;
|
const char *method;
|
||||||
|
unsigned int response_set:1;
|
||||||
unsigned int materialize:1;
|
unsigned int materialize:1;
|
||||||
unsigned int rotate_now:1;
|
unsigned int rotate_now:1;
|
||||||
unsigned int rotate:1;
|
unsigned int rotate:1;
|
||||||
@@ -151,6 +187,8 @@ audit_trail(kadmin_request_desc r, krb5_error_code ret)
|
|||||||
*/
|
*/
|
||||||
#define CASE(x) case x : retname = #x; break
|
#define CASE(x) case x : retname = #x; break
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
|
case ENOSYS: retname = "ECSRFTOKENREQD"; break;
|
||||||
|
CASE(EINVAL);
|
||||||
CASE(ENOMEM);
|
CASE(ENOMEM);
|
||||||
CASE(EACCES);
|
CASE(EACCES);
|
||||||
CASE(HDB_ERR_NOT_FOUND_HERE);
|
CASE(HDB_ERR_NOT_FOUND_HERE);
|
||||||
@@ -284,6 +322,10 @@ static struct getarg_strings auth_types;
|
|||||||
conf.mask |= b; \
|
conf.mask |= b; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does NOT set an HTTP response, naturally, as it doesn't even have access to
|
||||||
|
* the connection.
|
||||||
|
*/
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
get_kadm_handle(krb5_context context,
|
get_kadm_handle(krb5_context context,
|
||||||
const char *want_realm,
|
const char *want_realm,
|
||||||
@@ -366,7 +408,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static krb5_error_code resp(kadmin_request_desc, int,
|
static krb5_error_code resp(kadmin_request_desc, int, krb5_error_code,
|
||||||
enum MHD_ResponseMemoryMode, const char *,
|
enum MHD_ResponseMemoryMode, const char *,
|
||||||
const void *, size_t, const char *, const char *);
|
const void *, size_t, const char *, const char *);
|
||||||
static krb5_error_code bad_req(kadmin_request_desc, krb5_error_code, int,
|
static krb5_error_code bad_req(kadmin_request_desc, krb5_error_code, int,
|
||||||
@@ -430,9 +472,13 @@ validate_token(kadmin_request_desc r)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return bad_403(r, ret, "Token validation failed");
|
return bad_403(r, ret, "Token validation failed");
|
||||||
if (r->cprinc == NULL)
|
if (r->cprinc == NULL)
|
||||||
return bad_403(r, ret, "Could not extract a principal name "
|
return bad_403(r, ret,
|
||||||
"from token");
|
"Could not extract a principal name from token");
|
||||||
return krb5_unparse_name(r->context, r->cprinc, &r->cname);
|
ret = krb5_unparse_name(r->context, r->cprinc, &r->cname);
|
||||||
|
if (ret)
|
||||||
|
return bad_503(r, ret,
|
||||||
|
"Could not extract a principal name from token");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -557,10 +603,19 @@ make_redirect_uri(kadmin_request_desc r, const char *base)
|
|||||||
* XXX Shouldn't be a body, but a status message. The body should be
|
* XXX Shouldn't be a body, but a status message. The body should be
|
||||||
* configurable to be from a file. MHD doesn't give us a way to set the
|
* configurable to be from a file. MHD doesn't give us a way to set the
|
||||||
* response status message though, just the body.
|
* response status message though, just the body.
|
||||||
|
*
|
||||||
|
* Calls audit_trail().
|
||||||
|
*
|
||||||
|
* Returns -1 if something terrible happened, which should ultimately cause
|
||||||
|
* route() to return MHD_NO, which should cause libmicrohttpd to close the
|
||||||
|
* connection to the user-agent.
|
||||||
|
*
|
||||||
|
* Returns 0 in all other cases.
|
||||||
*/
|
*/
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
resp(kadmin_request_desc r,
|
resp(kadmin_request_desc r,
|
||||||
int http_status_code,
|
int http_status_code,
|
||||||
|
krb5_error_code ret,
|
||||||
enum MHD_ResponseMemoryMode rmmode,
|
enum MHD_ResponseMemoryMode rmmode,
|
||||||
const char *content_type,
|
const char *content_type,
|
||||||
const void *body,
|
const void *body,
|
||||||
@@ -571,9 +626,17 @@ resp(kadmin_request_desc r,
|
|||||||
struct MHD_Response *response;
|
struct MHD_Response *response;
|
||||||
int mret = MHD_YES;
|
int mret = MHD_YES;
|
||||||
|
|
||||||
|
if (r->response_set) {
|
||||||
|
krb5_log_msg(r->context, logfac, 1, NULL,
|
||||||
|
"Internal error; attempted to set a second response");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
(void) gettimeofday(&r->tv_end, NULL);
|
(void) gettimeofday(&r->tv_end, NULL);
|
||||||
if (http_status_code == MHD_HTTP_OK)
|
audit_trail(r, ret);
|
||||||
audit_trail(r, 0);
|
|
||||||
|
if (body && bodylen == BODYLEN_IS_STRLEN)
|
||||||
|
bodylen = strlen(body);
|
||||||
|
|
||||||
response = MHD_create_response_from_buffer(bodylen, rk_UNCONST(body),
|
response = MHD_create_response_from_buffer(bodylen, rk_UNCONST(body),
|
||||||
rmmode);
|
rmmode);
|
||||||
@@ -615,6 +678,7 @@ resp(kadmin_request_desc r,
|
|||||||
if (mret != MHD_NO)
|
if (mret != MHD_NO)
|
||||||
mret = MHD_queue_response(r->connection, http_status_code, response);
|
mret = MHD_queue_response(r->connection, http_status_code, response);
|
||||||
MHD_destroy_response(response);
|
MHD_destroy_response(response);
|
||||||
|
r->response_set = 1;
|
||||||
return mret == MHD_NO ? -1 : 0;
|
return mret == MHD_NO ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,9 +705,8 @@ bad_reqv(kadmin_request_desc r,
|
|||||||
if (code == ENOMEM) {
|
if (code == ENOMEM) {
|
||||||
if (context)
|
if (context)
|
||||||
krb5_log_msg(context, logfac, 1, NULL, "Out of memory");
|
krb5_log_msg(context, logfac, 1, NULL, "Out of memory");
|
||||||
audit_trail(r, code);
|
return resp(r, http_status_code, code, MHD_RESPMEM_PERSISTENT,
|
||||||
return resp(r, http_status_code, MHD_RESPMEM_PERSISTENT,
|
NULL, fmt, BODYLEN_IS_STRLEN, NULL, NULL);
|
||||||
NULL, fmt, strlen(fmt), NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code) {
|
if (code) {
|
||||||
@@ -661,22 +724,20 @@ bad_reqv(kadmin_request_desc r,
|
|||||||
msg = formatted;
|
msg = formatted;
|
||||||
formatted = NULL;
|
formatted = NULL;
|
||||||
}
|
}
|
||||||
if (r && r->hcontext) {
|
if (r && r->hcontext)
|
||||||
heim_audit_addreason((heim_svc_req_desc)r, "%s", formatted);
|
heim_audit_addreason((heim_svc_req_desc)r, "%s", formatted);
|
||||||
audit_trail(r, code);
|
|
||||||
}
|
|
||||||
krb5_free_error_message(context, k5msg);
|
krb5_free_error_message(context, k5msg);
|
||||||
|
|
||||||
if (ret == -1 || msg == NULL) {
|
if (ret == -1 || msg == NULL) {
|
||||||
if (context)
|
if (context)
|
||||||
krb5_log_msg(context, logfac, 1, NULL, "Out of memory");
|
krb5_log_msg(context, logfac, 1, NULL, "Out of memory");
|
||||||
return resp(r, MHD_HTTP_SERVICE_UNAVAILABLE,
|
return resp(r, MHD_HTTP_SERVICE_UNAVAILABLE, ENOMEM,
|
||||||
MHD_RESPMEM_PERSISTENT, NULL,
|
MHD_RESPMEM_PERSISTENT, NULL,
|
||||||
"Out of memory", sizeof("Out of memory") - 1, NULL, NULL);
|
"Out of memory", BODYLEN_IS_STRLEN, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = resp(r, http_status_code, MHD_RESPMEM_MUST_COPY,
|
ret = resp(r, http_status_code, code, MHD_RESPMEM_MUST_COPY,
|
||||||
NULL, msg, strlen(msg), NULL, NULL);
|
NULL, msg, BODYLEN_IS_STRLEN, NULL, NULL);
|
||||||
free(formatted);
|
free(formatted);
|
||||||
free(msg);
|
free(msg);
|
||||||
return ret == -1 ? -1 : code;
|
return ret == -1 ? -1 : code;
|
||||||
@@ -781,7 +842,7 @@ good_ext_keytab(kadmin_request_desc r)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return bad_503(r, ret, "Could not recover keytab from temp file");
|
return bad_503(r, ret, "Could not recover keytab from temp file");
|
||||||
|
|
||||||
ret = resp(r, MHD_HTTP_OK, MHD_RESPMEM_MUST_COPY,
|
ret = resp(r, MHD_HTTP_OK, 0, MHD_RESPMEM_MUST_COPY,
|
||||||
"application/octet-stream", body, bodylen, NULL, NULL);
|
"application/octet-stream", body, bodylen, NULL, NULL);
|
||||||
free(body);
|
free(body);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -911,7 +972,7 @@ param_cb(void *d,
|
|||||||
ret = krb5_principal_set_realm(r->context, p,
|
ret = krb5_principal_set_realm(r->context, p,
|
||||||
r->realm ? r->realm : realm);
|
r->realm ? r->realm : realm);
|
||||||
if (ret == 0 && krb5_principal_get_num_comp(r->context, p) != 2)
|
if (ret == 0 && krb5_principal_get_num_comp(r->context, p) != 2)
|
||||||
ret = ENOTSUP;
|
ret = ENOTSUP;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = check_service_name(r,
|
ret = check_service_name(r,
|
||||||
krb5_principal_get_comp_string(r->context,
|
krb5_principal_get_comp_string(r->context,
|
||||||
@@ -1088,7 +1149,11 @@ make_kstuple(krb5_context context,
|
|||||||
return *kstuple ? 0 :krb5_enomem(context);
|
return *kstuple ? 0 :krb5_enomem(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get keys for one principal */
|
/*
|
||||||
|
* Get keys for one principal.
|
||||||
|
*
|
||||||
|
* Does NOT set an HTTP response.
|
||||||
|
*/
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
get_keys1(kadmin_request_desc r, const char *pname)
|
get_keys1(kadmin_request_desc r, const char *pname)
|
||||||
{
|
{
|
||||||
@@ -1261,6 +1326,11 @@ get_keys1(kadmin_request_desc r, const char *pname)
|
|||||||
|
|
||||||
static krb5_error_code check_csrf(kadmin_request_desc);
|
static krb5_error_code check_csrf(kadmin_request_desc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calls get_keys1() to extract each requested principal's keys.
|
||||||
|
*
|
||||||
|
* When this returns a response will have been set.
|
||||||
|
*/
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
get_keysN(kadmin_request_desc r, const char *method)
|
get_keysN(kadmin_request_desc r, const char *method)
|
||||||
{
|
{
|
||||||
@@ -1273,24 +1343,19 @@ get_keysN(kadmin_request_desc r, const char *method)
|
|||||||
/* Parses and validates the request, then checks authorization */
|
/* Parses and validates the request, then checks authorization */
|
||||||
ret = authorize_req(r);
|
ret = authorize_req(r);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret; /* authorize_req() calls bad_req() */
|
return ret; /* authorize_req() calls bad_req() on error */
|
||||||
|
|
||||||
ret = get_kadm_handle(r->context, r->realm ? r->realm : realm,
|
ret = get_kadm_handle(r->context, r->realm ? r->realm : realm,
|
||||||
0 /* want_write */, &r->kadm_handle);
|
0 /* want_write */, &r->kadm_handle);
|
||||||
|
|
||||||
if (strcmp(method, "POST") == 0 && (ret = check_csrf(r)))
|
if (strcmp(method, "POST") == 0 && (ret = check_csrf(r)))
|
||||||
return bad_403(r, ret,
|
return ret; /* check_csrf() calls bad_req() on error */
|
||||||
"CSRF token needed; copy the X-CSRF-Token: response "
|
|
||||||
"header to your next POST");
|
|
||||||
|
|
||||||
nhosts = heim_array_get_length(r->hostnames);
|
nhosts = heim_array_get_length(r->hostnames);
|
||||||
nsvcs = heim_array_get_length(r->service_names);
|
nsvcs = heim_array_get_length(r->service_names);
|
||||||
nspns = heim_array_get_length(r->spns);
|
nspns = heim_array_get_length(r->spns);
|
||||||
if (!nhosts && !nspns) {
|
if (!nhosts && !nspns)
|
||||||
krb5_set_error_message(r->context, ret = EINVAL,
|
return bad_403(r, EINVAL, "No service principals requested");
|
||||||
"No service principals requested");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nhosts && !nsvcs) {
|
if (nhosts && !nsvcs) {
|
||||||
heim_string_t s;
|
heim_string_t s;
|
||||||
@@ -1304,11 +1369,8 @@ get_keysN(kadmin_request_desc r, const char *method)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Make this configurable */
|
/* FIXME: Make this configurable */
|
||||||
if (nsvcs > 4) {
|
if (nspns + nsvcs * nhosts > 40)
|
||||||
krb5_set_error_message(r->context, ret = ERANGE,
|
return bad_403(r, EINVAL, "Requested keys for too many principals");
|
||||||
"Requested too many service names");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = make_keytab(r);
|
ret = make_keytab(r);
|
||||||
for (i = 0; ret == 0 && i < nsvcs; i++) {
|
for (i = 0; ret == 0 && i < nsvcs; i++) {
|
||||||
@@ -1339,7 +1401,34 @@ get_keysN(kadmin_request_desc r, const char *method)
|
|||||||
heim_string_get_utf8(heim_array_get_value(r->spns,
|
heim_string_get_utf8(heim_array_get_value(r->spns,
|
||||||
i)));
|
i)));
|
||||||
}
|
}
|
||||||
return ret;
|
switch (ret) {
|
||||||
|
case -1:
|
||||||
|
/* Can't happen */
|
||||||
|
krb5_log_msg(r->context, logfac, 1, NULL,
|
||||||
|
"Failed to extract keys for unknown reasons");
|
||||||
|
if (r->response_set)
|
||||||
|
return MHD_YES;
|
||||||
|
return bad_503(r, ret, "Could not get keys");
|
||||||
|
case ENOSYS:
|
||||||
|
/* Our convention */
|
||||||
|
return bad_method_want_POST(r);
|
||||||
|
case KADM5_READ_ONLY:
|
||||||
|
if (primary_server_URI) {
|
||||||
|
krb5_log_msg(r->context, logfac, 1, NULL,
|
||||||
|
"Redirect %s to primary server", r->cname);
|
||||||
|
return resp(r, MHD_HTTP_TEMPORARY_REDIRECT, KADM5_READ_ONLY,
|
||||||
|
MHD_RESPMEM_PERSISTENT, NULL, "", 0, NULL, NULL);
|
||||||
|
} else {
|
||||||
|
krb5_log_msg(r->context, logfac, 1, NULL, "HDB is read-only");
|
||||||
|
return bad_403(r, ret, "HDB is read-only");
|
||||||
|
}
|
||||||
|
case 0:
|
||||||
|
krb5_log_msg(r->context, logfac, 1, NULL, "Sent keytab to %s",
|
||||||
|
r->cname);
|
||||||
|
return good_ext_keytab(r);
|
||||||
|
default:
|
||||||
|
return bad_503(r, ret, "Could not get keys");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copied from kdc/connect.c */
|
/* Copied from kdc/connect.c */
|
||||||
@@ -1467,37 +1556,12 @@ get_keys(kadmin_request_desc r, const char *method)
|
|||||||
{
|
{
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
|
||||||
if ((ret = validate_token(r)))
|
if ((ret = validate_token(r)))
|
||||||
return ret; /* validate_token() calls bad_req() */
|
return ret; /* validate_token() calls bad_req() */
|
||||||
if (r->cname == NULL || r->cprinc == NULL)
|
if (r->cname == NULL || r->cprinc == NULL)
|
||||||
return bad_403(r, EINVAL,
|
return bad_403(r, EINVAL,
|
||||||
"Could not extract principal name from token");
|
"Could not extract principal name from token");
|
||||||
switch ((ret = get_keysN(r, method))) {
|
return get_keysN(r, method); /* Sets an HTTP response */
|
||||||
case -1: /* XXX */
|
|
||||||
return MHD_YES;
|
|
||||||
case ENOSYS: /* XXX */
|
|
||||||
return bad_method_want_POST(r);
|
|
||||||
case KADM5_READ_ONLY:
|
|
||||||
if (primary_server_URI) {
|
|
||||||
krb5_log_msg(r->context, logfac, 1, NULL,
|
|
||||||
"Redirect for %s to primary server to "
|
|
||||||
"materialize or rotate principal", r->cname);
|
|
||||||
return resp(r, MHD_HTTP_TEMPORARY_REDIRECT, MHD_RESPMEM_PERSISTENT,
|
|
||||||
NULL, "", 0, NULL, NULL);
|
|
||||||
} else {
|
|
||||||
krb5_log_msg(r->context, logfac, 1, NULL, "HDB is read-only here "
|
|
||||||
"and no primary URI configured");
|
|
||||||
return bad_403(r, ret, "HDB is read-only here "
|
|
||||||
"and no primary URI configured");
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
krb5_log_msg(r->context, logfac, 1, NULL,
|
|
||||||
"Issued service principal keys to %s", r->cname);
|
|
||||||
return good_ext_keytab(r);
|
|
||||||
default:
|
|
||||||
return bad_503(r, ret, "Could not get keys");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implements GETs of /get-config */
|
/* Implements GETs of /get-config */
|
||||||
@@ -1558,7 +1622,7 @@ get_config(kadmin_request_desc r)
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
krb5_log_msg(r->context, logfac, 1, NULL,
|
krb5_log_msg(r->context, logfac, 1, NULL,
|
||||||
"Returned krb5.conf contents to %s", r->cname);
|
"Returned krb5.conf contents to %s", r->cname);
|
||||||
ret = resp(r, MHD_HTTP_OK, MHD_RESPMEM_MUST_COPY,
|
ret = resp(r, MHD_HTTP_OK, 0, MHD_RESPMEM_MUST_COPY,
|
||||||
"application/text", body, bodylen, NULL, NULL);
|
"application/text", body, bodylen, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
ret = bad_503(r, ret, "Could not retrieve principal configuration");
|
ret = bad_503(r, ret, "Could not retrieve principal configuration");
|
||||||
@@ -1701,6 +1765,10 @@ make_csrf_token(kadmin_request_desc r,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns system or krb5_error_code on error, but also calls resp() or bad_*()
|
||||||
|
* on error.
|
||||||
|
*/
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
check_csrf(kadmin_request_desc r)
|
check_csrf(kadmin_request_desc r)
|
||||||
{
|
{
|
||||||
@@ -1714,13 +1782,17 @@ check_csrf(kadmin_request_desc r)
|
|||||||
"X-CSRF-Token");
|
"X-CSRF-Token");
|
||||||
ret = make_csrf_token(r, given, &expected, &age);
|
ret = make_csrf_token(r, given, &expected, &age);
|
||||||
if (ret)
|
if (ret)
|
||||||
bad_503(r, ret, "Could not create a CSRF token");
|
return bad_503(r, ret, "Could not create a CSRF token");
|
||||||
|
/*
|
||||||
|
* If CSRF token needed but missing, call resp() directly, bypassing
|
||||||
|
* bad_403(), to return a 403 with an expected CSRF token in the response.
|
||||||
|
*/
|
||||||
if (given == NULL) {
|
if (given == NULL) {
|
||||||
(void) resp(r, MHD_HTTP_FORBIDDEN, MHD_RESPMEM_PERSISTENT, NULL,
|
(void) resp(r, MHD_HTTP_FORBIDDEN, ENOSYS, MHD_RESPMEM_PERSISTENT,
|
||||||
"Request missing a CSRF token",
|
NULL, "CSRF token needed; copy the X-CSRF-Token: response "
|
||||||
sizeof("Request missing a CSRF token"), NULL,
|
"header to your next POST", BODYLEN_IS_STRLEN, NULL,
|
||||||
expected);
|
expected);
|
||||||
return -1;
|
return ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate the CSRF token for this request */
|
/* Validate the CSRF token for this request */
|
||||||
@@ -1740,14 +1812,13 @@ check_csrf(kadmin_request_desc r)
|
|||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
health(const char *method, kadmin_request_desc r)
|
health(const char *method, kadmin_request_desc r)
|
||||||
{
|
{
|
||||||
if (strcmp(method, "HEAD") == 0)
|
if (strcmp(method, "HEAD") == 0) {
|
||||||
return resp(r, MHD_HTTP_OK, MHD_RESPMEM_PERSISTENT, NULL, "", 0, NULL,
|
return resp(r, MHD_HTTP_OK, 0, MHD_RESPMEM_PERSISTENT, NULL, "", 0,
|
||||||
NULL);
|
NULL, NULL);
|
||||||
return resp(r, MHD_HTTP_OK, MHD_RESPMEM_PERSISTENT, NULL,
|
}
|
||||||
|
return resp(r, MHD_HTTP_OK, 0, MHD_RESPMEM_PERSISTENT, NULL,
|
||||||
"To determine the health of the service, use the /get-config "
|
"To determine the health of the service, use the /get-config "
|
||||||
"end-point.\n",
|
"end-point.\n", BODYLEN_IS_STRLEN, NULL, NULL);
|
||||||
sizeof("To determine the health of the service, use the "
|
|
||||||
"/get-config end-point.\n") - 1, NULL, NULL);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -585,6 +585,9 @@ cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
|
|||||||
test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 3 ||
|
test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 3 ||
|
||||||
{ echo "Wrong number of new keys!"; exit 1; }
|
{ echo "Wrong number of new keys!"; exit 1; }
|
||||||
|
|
||||||
|
grep 'Internal error' messages.log &&
|
||||||
|
{ echo "Internal errors in log"; exit 1; }
|
||||||
|
|
||||||
sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
|
sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
|
||||||
sh ${leaks_kill} kadmind $kadmindpid || ec=1
|
sh ${leaks_kill} kadmind $kadmindpid || ec=1
|
||||||
sh ${leaks_kill} kadmind $kadmind2pid || ec=1
|
sh ${leaks_kill} kadmind $kadmind2pid || ec=1
|
||||||
|
Reference in New Issue
Block a user