mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ipa-join: buffer curl response before parsing json
CURLOPT_WRITEFUNCTION is not guaranteed to be called only once per request and receive all data at once. Use a dynamic buffer to cope with that case. Related: https://pagure.io/freeipa/issue/7966 Reviewed-By: Christian Heimes <cheimes@redhat.com> Reviewed-By: Rob Crittenden <rcritten@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
parent
c197918e8d
commit
c905f94f9b
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
int init_gettext(void);
|
int init_gettext(void);
|
||||||
|
|
||||||
struct json_results {
|
typedef struct {
|
||||||
char *hostdn;
|
char *payload;
|
||||||
char *krbprinc;
|
size_t size;
|
||||||
};
|
} curl_buffer;
|
||||||
|
@ -50,16 +50,12 @@
|
|||||||
|
|
||||||
#define IPA_CONFIG "/etc/ipa/default.conf"
|
#define IPA_CONFIG "/etc/ipa/default.conf"
|
||||||
|
|
||||||
#define BUFSIZE 1024
|
|
||||||
|
|
||||||
char * read_config_file(const char *filename);
|
char * read_config_file(const char *filename);
|
||||||
char * get_config_entry(char * data, const char *section, const char *key);
|
char * get_config_entry(char * data, const char *section, const char *key);
|
||||||
|
|
||||||
static int debug = 0;
|
static int debug = 0;
|
||||||
static int use_json = 0;
|
static int use_json = 0;
|
||||||
|
|
||||||
struct json_results *results = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Translate some IPA exceptions into specific errors in this context.
|
* Translate some IPA exceptions into specific errors in this context.
|
||||||
*/
|
*/
|
||||||
@ -649,52 +645,54 @@ curl_slist_append_log(struct curl_slist *list, char *string, int quiet) {
|
|||||||
|
|
||||||
size_t
|
size_t
|
||||||
jsonrpc_handle_response(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
jsonrpc_handle_response(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||||
struct json_object *jsonobj, *result, *krb5princ, *hostdn, *arr, *content;
|
size_t realsize = size * nmemb;
|
||||||
size_t arr_length;
|
curl_buffer *cb = (curl_buffer *) userdata;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (debug) {
|
char *buf = (char *) realloc(cb->payload, cb->size + realsize + 1);
|
||||||
fprintf(stdout, "JSONRPC CALL Respone:\n%s\n", ptr);
|
if (!buf) {
|
||||||
}
|
fprintf(stderr, _("Expanding buffer in jsonrpc_handle_response failed"));
|
||||||
|
free(cb->payload);
|
||||||
|
cb->payload = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cb->payload = buf;
|
||||||
|
memcpy(&(cb->payload[cb->size]), ptr, realsize);
|
||||||
|
|
||||||
jsonobj = json_tokener_parse(ptr);
|
cb->size += realsize;
|
||||||
json_object_object_get_ex(jsonobj, "result", &result);
|
cb->payload[cb->size] = 0;
|
||||||
|
|
||||||
arr_length = json_object_array_length(result);
|
return realsize;
|
||||||
|
|
||||||
if (arr_length == 2) {
|
|
||||||
results = (struct json_results *) malloc(sizeof(struct json_results));
|
|
||||||
|
|
||||||
hostdn = json_object_array_get_idx(result, 0);
|
|
||||||
ret = asprintf(&results->hostdn, "%s", json_object_get_string(hostdn));
|
|
||||||
|
|
||||||
arr = json_object_array_get_idx(result, 1);
|
|
||||||
json_object_object_get_ex(arr, "krbprincipalname", &content);
|
|
||||||
krb5princ = json_object_array_get_idx(content, 0);
|
|
||||||
ret = asprintf(&results->krbprinc, "%s", json_object_get_string(krb5princ));
|
|
||||||
}
|
|
||||||
|
|
||||||
json_object_put(jsonobj);
|
|
||||||
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const char **princ, int force, int quiet) {
|
join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const char **princ, int force, int quiet) {
|
||||||
CURL *curl = NULL;
|
CURL *curl = NULL;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
struct curl_slist *headers = NULL;
|
|
||||||
json_object *jsonobj = NULL;
|
|
||||||
json_object *array = NULL;
|
|
||||||
json_object *hostarr = NULL;
|
|
||||||
json_object *optsarr = NULL;
|
|
||||||
struct utsname uinfo;
|
struct utsname uinfo;
|
||||||
|
|
||||||
char *host = NULL;
|
char *host = NULL;
|
||||||
char *url = NULL;
|
char *url = NULL;
|
||||||
char *referer = NULL;
|
char *referer = NULL;
|
||||||
char *user_agent = NULL;
|
char *user_agent = NULL;
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
|
||||||
|
curl_buffer cb;
|
||||||
|
|
||||||
|
json_object *json_post = NULL;
|
||||||
|
json_object *array = NULL;
|
||||||
|
json_object *hostarr = NULL;
|
||||||
|
json_object *optsarr = NULL;
|
||||||
|
|
||||||
|
json_object *json_resp = NULL;
|
||||||
|
json_object *json_result = NULL;
|
||||||
|
json_object *json_krbprinc = NULL;
|
||||||
|
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
|
|
||||||
|
*hostdn = NULL;
|
||||||
|
*princ = NULL;
|
||||||
|
|
||||||
uname(&uinfo);
|
uname(&uinfo);
|
||||||
|
|
||||||
if (!hostname) {
|
if (!hostname) {
|
||||||
@ -728,6 +726,16 @@ join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const ch
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cb.payload = (char *) malloc(sizeof(cb.payload));
|
||||||
|
if (!cb.payload) {
|
||||||
|
if (!quiet)
|
||||||
|
fprintf(stderr, _("Out of memory!\n"));
|
||||||
|
|
||||||
|
rval = 3;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
cb.size = 0;
|
||||||
|
|
||||||
/* setting endpoint and custom headers */
|
/* setting endpoint and custom headers */
|
||||||
ASPRINTF(&url, "https://%s/ipa/json", ipaserver);
|
ASPRINTF(&url, "https://%s/ipa/json", ipaserver);
|
||||||
CURL_SETOPT(curl, CURLOPT_URL, url);
|
CURL_SETOPT(curl, CURLOPT_URL, url);
|
||||||
@ -760,7 +768,9 @@ join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const ch
|
|||||||
CURL_SETOPT(curl, CURLOPT_HTTPHEADER, headers);
|
CURL_SETOPT(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
CURL_SETOPT(curl, CURLOPT_CAINFO, DEFAULT_CA_CERT_FILE);
|
CURL_SETOPT(curl, CURLOPT_CAINFO, DEFAULT_CA_CERT_FILE);
|
||||||
|
|
||||||
CURL_SETOPT(curl, CURLOPT_WRITEFUNCTION, &jsonrpc_handle_response);
|
CURL_SETOPT(curl, CURLOPT_WRITEFUNCTION, &jsonrpc_handle_response);
|
||||||
|
CURL_SETOPT(curl, CURLOPT_WRITEDATA, &cb);
|
||||||
|
|
||||||
/* delegate authentication to GSSAPI */
|
/* delegate authentication to GSSAPI */
|
||||||
CURL_SETOPT(curl, CURLOPT_GSSAPI_DELEGATION, CURLGSSAPI_DELEGATION_FLAG);
|
CURL_SETOPT(curl, CURLOPT_GSSAPI_DELEGATION, CURLGSSAPI_DELEGATION_FLAG);
|
||||||
@ -771,9 +781,9 @@ join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const ch
|
|||||||
CURL_SETOPT(curl, CURLOPT_VERBOSE, 1L);
|
CURL_SETOPT(curl, CURLOPT_VERBOSE, 1L);
|
||||||
|
|
||||||
/* create the JSON-RPC payload */
|
/* create the JSON-RPC payload */
|
||||||
jsonobj = json_object_new_object();
|
json_post = json_object_new_object();
|
||||||
|
|
||||||
json_object_object_add(jsonobj, "method", json_object_new_string("join"));
|
json_object_object_add(json_post, "method", json_object_new_string("join"));
|
||||||
|
|
||||||
array = json_object_new_array();
|
array = json_object_new_array();
|
||||||
|
|
||||||
@ -786,11 +796,11 @@ join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const ch
|
|||||||
json_object_object_add(optsarr, "nshardwareplatform", json_object_new_string(uinfo.machine));
|
json_object_object_add(optsarr, "nshardwareplatform", json_object_new_string(uinfo.machine));
|
||||||
json_object_array_add(array, json_object_get(optsarr));
|
json_object_array_add(array, json_object_get(optsarr));
|
||||||
|
|
||||||
json_object_object_add(jsonobj, "params", json_object_get(array));
|
json_object_object_add(json_post, "params", json_object_get(array));
|
||||||
|
|
||||||
json_object_object_add(jsonobj, "id", json_object_new_int(0));
|
json_object_object_add(json_post, "id", json_object_new_int(0));
|
||||||
|
|
||||||
CURL_SETOPT(curl, CURLOPT_POSTFIELDS, json_object_to_json_string(jsonobj));
|
CURL_SETOPT(curl, CURLOPT_POSTFIELDS, json_object_to_json_string(json_post));
|
||||||
|
|
||||||
/* Perform the call and check for errors */
|
/* Perform the call and check for errors */
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
@ -803,11 +813,26 @@ join_krb5_jsonrpc(const char *ipaserver, char *hostname, char **hostdn, const ch
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cb.payload && debug) {
|
||||||
|
fprintf(stderr, "JSON-RPC call respone:\n%s\n", cb.payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_resp = json_tokener_parse(cb.payload);
|
||||||
|
json_object_object_get_ex(json_resp, "result", &json_result);
|
||||||
|
|
||||||
|
if (json_object_array_length(json_result) == 2) {
|
||||||
|
asprintf((char **)hostdn, "%s", json_object_get_string(json_object_array_get_idx(json_result, 0)));
|
||||||
|
|
||||||
|
json_object_object_get_ex(json_object_array_get_idx(json_result, 1), "krbprincipalname", &json_krbprinc);
|
||||||
|
asprintf((char **)princ, "%s", json_object_get_string(json_object_array_get_idx(json_krbprinc, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
json_object_put(optsarr);
|
json_object_put(optsarr);
|
||||||
json_object_put(hostarr);
|
json_object_put(hostarr);
|
||||||
json_object_put(array);
|
json_object_put(array);
|
||||||
json_object_put(jsonobj);
|
json_object_put(json_post);
|
||||||
|
json_object_put(json_resp);
|
||||||
|
|
||||||
curl_slist_free_all(headers);
|
curl_slist_free_all(headers);
|
||||||
|
|
||||||
@ -824,6 +849,9 @@ cleanup:
|
|||||||
if (user_agent)
|
if (user_agent)
|
||||||
free(user_agent);
|
free(user_agent);
|
||||||
|
|
||||||
|
if (cb.payload)
|
||||||
|
free(cb.payload);
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1159,12 +1187,12 @@ join(const char *server, const char *hostname, const char *bindpw, const char *b
|
|||||||
argv[arg++] = "-s";
|
argv[arg++] = "-s";
|
||||||
argv[arg++] = ipaserver;
|
argv[arg++] = ipaserver;
|
||||||
argv[arg++] = "-p";
|
argv[arg++] = "-p";
|
||||||
argv[arg++] = use_json == 0 ? (char *)princ : (char *)results->krbprinc;
|
argv[arg++] = (char *)princ;
|
||||||
argv[arg++] = "-k";
|
argv[arg++] = "-k";
|
||||||
argv[arg++] = (char *)keytab;
|
argv[arg++] = (char *)keytab;
|
||||||
if (bindpw) {
|
if (bindpw) {
|
||||||
argv[arg++] = "-D";
|
argv[arg++] = "-D";
|
||||||
argv[arg++] = use_json == 0 ? (char *)hostdn : (char *)results->hostdn;
|
argv[arg++] = (char *)hostdn;
|
||||||
argv[arg++] = "-w";
|
argv[arg++] = "-w";
|
||||||
argv[arg++] = (char *)bindpw;
|
argv[arg++] = (char *)bindpw;
|
||||||
}
|
}
|
||||||
@ -1210,12 +1238,6 @@ cleanup:
|
|||||||
if (ccache) krb5_cc_close(krbctx, ccache);
|
if (ccache) krb5_cc_close(krbctx, ccache);
|
||||||
if (krbctx) krb5_free_context(krbctx);
|
if (krbctx) krb5_free_context(krbctx);
|
||||||
|
|
||||||
if (results != NULL) {
|
|
||||||
free(results->hostdn);
|
|
||||||
free(results->krbprinc);
|
|
||||||
free(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user