Exemplo n.º 1
0
static void execute_method(xmlrpc_value **result, char *method, xmlrpc_value *params) {
    xmlrpc_server_info *serverInfo;

    serverInfo = xmlrpc_server_info_new(&env, server);
    *result = xmlrpc_client_call_server_params(&env, serverInfo, method, params);
    check_fault();
}
int 
wpNewPost(char *username, char *password, wppost_t *post) {
	int retval = 0;
	char *postid = NULL;
	xmlrpc_env env;
	xmlrpc_client *clientP;
	xmlrpc_server_info * serverInfoP;
	xmlrpc_value *paramArrayP = NULL;
	char *methodName = "metaWeblog.newPost";
	xmlrpc_value *resultP;

	wp_env_init(&env, &clientP);
	retval = wpCreatePostStruct(&env, username, password, post, &paramArrayP, 0);
	if (retval != 0) {
		fprintf(stderr, "Error creating post structure, exiting\n");
		goto out;
	}
	serverInfoP = xmlrpc_server_info_new(&env, post->url);
	xmlrpc_client_call2(&env, clientP, serverInfoP, methodName, paramArrayP, &resultP);
	xmlrpc_read_string(&env, resultP,(const char **) &postid);
	post->postid = postid;
	xmlrpc_DECREF(resultP);	
out:
	xmlrpc_DECREF(paramArrayP);
	wp_env_clean(&env, &clientP);
	return retval;
}
Exemplo n.º 3
0
static void
testServerInfo(void) {

    xmlrpc_env env;
    xmlrpc_server_info * serverInfoP;
    xmlrpc_server_info * serverInfo2P;

    printf("  Running serverInfo tests...\n");

    xmlrpc_env_init(&env);

    serverInfoP = xmlrpc_server_info_new(&env, "testurl");
    TEST_NO_FAULT(&env);

    serverInfo2P = xmlrpc_server_info_copy(&env, serverInfoP);
    TEST_NO_FAULT(&env);

    xmlrpc_server_info_free(serverInfo2P);

    /* Fails because we haven't set user/password yet: */
    xmlrpc_server_info_allow_auth_basic(&env, serverInfoP);
    TEST_FAULT(&env, XMLRPC_INTERNAL_ERROR);
    
    xmlrpc_server_info_set_basic_auth(&env, serverInfoP,
                                      "username", "password");
    TEST_NO_FAULT(&env);

    xmlrpc_server_info_set_user(&env, serverInfoP, "username", "password");
    TEST_NO_FAULT(&env);

    xmlrpc_server_info_allow_auth_basic(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_disallow_auth_basic(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_allow_auth_digest(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_disallow_auth_digest(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_allow_auth_negotiate(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_disallow_auth_negotiate(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_allow_auth_ntlm(&env, serverInfoP);
    TEST_NO_FAULT(&env);
    
    xmlrpc_server_info_disallow_auth_ntlm(&env, serverInfoP);
    TEST_NO_FAULT(&env);

    xmlrpc_server_info_free(serverInfoP);
    
    xmlrpc_env_clean(&env);
}
Exemplo n.º 4
0
void abrt_xmlrpc_conn::new_xmlrpc_client(const char* url, bool ssl_verify)
{
    m_pClient = NULL;
    m_pServer_info = NULL;

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    /* This should be done at program startup, once. We do it in main */
    /* xmlrpc_client_setup_global_const(&env); */

    /* URL - bugzilla.redhat.com/show_bug.cgi?id=666893 Unable to make sense of
     * XML-RPC response from server
     *
     * By default, XML data from the network may be no larger than 512K.
     * XMLRPC_XML_SIZE_LIMIT_DEFAULT is #defined to (512*1024) in xmlrpc-c/base.h
     *
     * Users reported trouble with 733402 byte long responses, hope raising the
     * limit to 2*512k is enough
     */
    xmlrpc_limit_set(XMLRPC_XML_SIZE_LIMIT_ID, 2 * XMLRPC_XML_SIZE_LIMIT_DEFAULT);

    struct xmlrpc_curl_xportparms curlParms;
    memset(&curlParms, 0, sizeof(curlParms));
    /* curlParms.network_interface = NULL; - done by memset */
    curlParms.no_ssl_verifypeer = !ssl_verify;
    curlParms.no_ssl_verifyhost = !ssl_verify;
#ifdef VERSION
    curlParms.user_agent        = PACKAGE_NAME"/"VERSION;
#else
    curlParms.user_agent        = "abrt";
#endif

    struct xmlrpc_clientparms clientParms;
    memset(&clientParms, 0, sizeof(clientParms));
    clientParms.transport          = "curl";
    clientParms.transportparmsP    = &curlParms;
    clientParms.transportparm_size = XMLRPC_CXPSIZE(user_agent);

    xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS,
                        PACKAGE_NAME, VERSION,
                        &clientParms, XMLRPC_CPSIZE(transportparm_size),
                        &m_pClient);
    if (env.fault_occurred)
        throw_xml_fault(&env);

    m_pServer_info = xmlrpc_server_info_new(&env, url);
    if (env.fault_occurred)
    {
        xmlrpc_client_destroy(m_pClient);
        m_pClient = NULL;
        throw_xml_fault(&env);
    }
}
Exemplo n.º 5
0
int 
main(int           const argc, 
     const char ** const argv) {

    xmlrpc_env env;
    xmlrpc_server_info * serverP;
    xmlrpc_value * resultP;
    xmlrpc_int sum;
    
    if (argc-1 > 0) {
        fprintf(stderr, "There are no arguments.  You specified %d", argc-1);
        exit(1);
    }

    /* Start up our XML-RPC client library. */
    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);
    xmlrpc_env_init(&env);

    /* Make a new object to represent our XML-RPC server. */
    serverP = xmlrpc_server_info_new(&env, SERVER_URL);
    die_if_fault_occurred(&env);

    /* Set up our authentication information. */
    xmlrpc_server_info_set_basic_auth(&env, serverP, "jrandom", "secret");
    die_if_fault_occurred(&env);

    resultP = 
        xmlrpc_client_call_server(
            &env, serverP, "sample.add", "(ii)", 
            (xmlrpc_int32) 5, (xmlrpc_int32) 7);
    die_if_fault_occurred(&env);

    /* Dispose of our server object. */
    xmlrpc_server_info_free(serverP);
    
    /* Get the result of the RPC and print it out. */
    xmlrpc_read_int(&env, resultP, &sum);
    die_if_fault_occurred(&env);
    printf("The sum is %d\n", sum);
    
    /* Dispose of our result value. */
    xmlrpc_DECREF(resultP);

    /* Shut down our XML-RPC client library. */
    xmlrpc_env_clean(&env);
    xmlrpc_client_cleanup();

    return 0;
}
Exemplo n.º 6
0
static void
createServerInfo(xmlrpc_env *          const envP,
                 const char *          const serverUrl,
                 const char *          const userName,
                 const char *          const password,
                 xmlrpc_server_info ** const serverInfoPP) {

    xmlrpc_server_info * serverInfoP;

    serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
    if (!envP->fault_occurred) {
        if (userName) {
            xmlrpc_server_info_set_basic_auth(
                envP, serverInfoP, userName, password);
        }
    }
    *serverInfoPP = serverInfoP;
}
Exemplo n.º 7
0
static void
testSynchCall(void) {

    xmlrpc_env env;
    xmlrpc_client * clientP;
    xmlrpc_value * resultP;
    xmlrpc_value * emptyArrayP;
    xmlrpc_server_info * noSuchServerInfoP;

    xmlrpc_env_init(&env);

    emptyArrayP = xmlrpc_array_new(&env);
    TEST_NO_FAULT(&env);

    xmlrpc_client_setup_global_const(&env);
    TEST_NO_FAULT(&env);

    xmlrpc_client_create(&env, 0, "testprog", "1.0", NULL, 0, &clientP);
    TEST_NO_FAULT(&env);

    noSuchServerInfoP = xmlrpc_server_info_new(&env, "nosuchserver");
    TEST_NO_FAULT(&env);

    xmlrpc_client_call2(&env, clientP, noSuchServerInfoP, "nosuchmethod",
                        emptyArrayP, &resultP);
    TEST_FAULT(&env, XMLRPC_NETWORK_ERROR);  /* No such server */

    xmlrpc_client_call2f(&env, clientP, "nosuchserver", "nosuchmethod",
                          &resultP, "(i)", 7);
    TEST_FAULT(&env, XMLRPC_NETWORK_ERROR);  /* No such server */

    xmlrpc_server_info_free(noSuchServerInfoP);

    xmlrpc_client_destroy(clientP);

    xmlrpc_DECREF(emptyArrayP);
    
    xmlrpc_client_teardown_global_const();

    xmlrpc_env_clean(&env);
}
Exemplo n.º 8
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int xmlrpc_instantiate(CONF_SECTION * conf, void **instance)
{
	rlm_xmlrpc_t *data;
	rlm_xmlrpc_client_t *first_client;
	rlm_xmlrpc_client_t *client;

	xmlrpc_env env;

	struct xmlrpc_clientparms clientParms;
	struct xmlrpc_curl_xportparms curlParms;

	int i, error;
	void (*do_auth) ();

	/*
	 *      Set up a storage area for instance data
	 */
	data = rad_malloc(sizeof(*data));
	if (!data) {
		return -1;
	}
	memset(data, 0, sizeof(*data));

	/*
	 *      If the configuration parameters can't be parsed, then
	 *      fail.
	 */
	if (cf_section_parse(conf, data, module_config) < 0) {
		free(data);
		return -1;
	}

	*instance = data;

#ifdef HAVE_PTHREAD_H
	pthread_mutex_init(&data->client_mutex, NULL);
#endif

	/*
	 * network_interface parameter cannot be omitted because the
	 * XMLRPC_CXPSIZE macro calcs the size from the first parameter
	 * to the last modified.
	 * Unfortunately is this the order. 
	 */
	curlParms.network_interface = data->interface;
	curlParms.no_ssl_verifypeer = data->no_ssl_verify_peer;
	curlParms.no_ssl_verifyhost = data->no_ssl_verify_host;

	clientParms.transport = "curl";
	clientParms.transportparmsP = &curlParms;
	clientParms.transportparm_size = XMLRPC_CXPSIZE(no_ssl_verifyhost);

	/*
	 * Choosing method authentication
	 */
	if (strcmp(data->auth_type, "auth_basic") == 0) {
		do_auth = xmlrpc_server_info_allow_auth_basic;
	} else if (strcmp(data->auth_type, "auth_digest") == 0) {
		do_auth = xmlrpc_server_info_allow_auth_digest;
	} else if (strcmp(data->auth_type, "auth_negotiate") == 0) {
		do_auth = xmlrpc_server_info_allow_auth_negotiate;
	} else if (strcmp(data->auth_type, "auth_ntlm") == 0) {
		do_auth = xmlrpc_server_info_allow_auth_ntlm;
	}

	/*
	 * Clients are created into a circular linked list.
	 * Into this cycle we setup clients and server information objects.
	 * Server information contains a method to do html authentication. 
	 */
	for (i = 0; i < data->xmlrpc_num_socks; i++) {
		client = rad_malloc(sizeof(*client));
		if (!client) {
			return -1;
		}
		memset(client, 0, sizeof(*client));

		env = client->env;
		xmlrpc_env_init(&env);

		if (i == 0) {
			data->client = client;
			first_client = client;

			xmlrpc_client_setup_global_const(&env);
		} else {
			data->client->next = client;
			data->client = data->client->next;
		}

		xmlrpc_client_create(&env, XMLRPC_CLIENT_NO_FLAGS, NAME,
				     VERSION, &clientParms,
				     XMLRPC_CPSIZE(transportparm_size), &client->clientP);

		error = check_error_and_free(data);
		if (error != RLM_MODULE_OK)
			return error;

		client->serverInfoP = xmlrpc_server_info_new(&env, data->url);
		error = check_error_and_free(data);
		if (error != RLM_MODULE_OK)
			return error;

		if (strcmp(data->auth_type, "none") != 0) {
			xmlrpc_server_info_set_user(&env, client->serverInfoP,
						    data->user, data->password);
			error = check_error_and_free(data);
			if (error != RLM_MODULE_OK)
				return error;

			do_auth(&env, client->serverInfoP);
			error = check_error_and_free(data);
			if (error != RLM_MODULE_OK)
				return error;

			radlog(L_INFO, "\trlm_xmlrpc: client #%d logged in as %s", i, data->user);
		}

		radlog(L_INFO, "\trlm_xmlrpc: client #%d initialized", i);

	}

	/*
	 * closing the circular linked list. data->client helds a pointer
	 * to the last client used by a thread.
	 */

	data->client->next = first_client;
	data->client = data->client->next;

	return 0;
}
Exemplo n.º 9
0
static int
unenroll_host(const char *server, const char *hostname, const char *ktname, int quiet)
{
    int rval = 0;
    int ret;
    char *ipaserver = NULL;
    char *host = NULL;
    struct utsname uinfo;
    char *principal = NULL;
    char *realm = NULL;

    krb5_context krbctx = NULL;
    krb5_keytab keytab = NULL;
    krb5_ccache ccache = NULL;
    krb5_principal princ = NULL;
    krb5_error_code krberr;
    krb5_creds creds;
    krb5_get_init_creds_opt gicopts;
    char tgs[LINE_MAX];

    xmlrpc_env env;
    xmlrpc_value * argArrayP = NULL;
    xmlrpc_value * paramArrayP = NULL;
    xmlrpc_value * paramP = NULL;
    xmlrpc_value * resultP = NULL;
    xmlrpc_server_info * serverInfoP = NULL;
    xmlrpc_value *princP = NULL;
    char * url = NULL;
    char * user_agent = NULL;

    if (server) {
        ipaserver = strdup(server);
    } else {
        char * conf_data = read_config_file(IPA_CONFIG);
        if ((ipaserver = getIPAserver(conf_data)) == NULL) {
            if (!quiet)
                fprintf(stderr, _("Unable to determine IPA server from %s\n"),
                        IPA_CONFIG);
            exit(1);
        }
        free(conf_data);
    }

    if (NULL == hostname) {
        uname(&uinfo);
        host = strdup(uinfo.nodename);
    } else {
        host = strdup(hostname);
    }

    if (NULL == strstr(host, ".")) {
        if (!quiet)
            fprintf(stderr, _("The hostname must be fully-qualified: %s\n"),
                    host);
        rval = 16;
        goto cleanup;
    }

    krberr = krb5_init_context(&krbctx);
    if (krberr) {
        if (!quiet)
            fprintf(stderr, _("Unable to join host: "
                              "Kerberos context initialization failed\n"));
        rval = 1;
        goto cleanup;
    }
    krberr = krb5_kt_resolve(krbctx, ktname, &keytab);
    if (krberr != 0) {
        if (!quiet)
            fprintf(stderr, _("Error resolving keytab: %s.\n"),
                error_message(krberr));
        rval = 7;
        goto cleanup;
    }

    krberr = krb5_get_default_realm(krbctx, &realm);
    if (krberr != 0) {
        if (!quiet)
            fprintf(stderr, _("Error getting default Kerberos realm: %s.\n"),
                error_message(krberr));
        rval = 21;
        goto cleanup;
    }

    ret = asprintf(&principal, "host/%s@%s", host,  realm);
    if (ret == -1)
    {
        if (!quiet)
            fprintf(stderr, _("Out of memory!\n"));
        rval = 3;
        goto cleanup;
    }

    krberr = krb5_parse_name(krbctx, principal, &princ);
    if (krberr != 0) {
        if (!quiet)
            fprintf(stderr, _("Error parsing \"%1$s\": %2$s.\n"),
                            principal, error_message(krberr));
        return krberr;
    }
    strcpy(tgs, KRB5_TGS_NAME);
    snprintf(tgs + strlen(tgs), sizeof(tgs) - strlen(tgs), "/%.*s",
             (krb5_princ_realm(krbctx, princ))->length,
             (krb5_princ_realm(krbctx, princ))->data);
    snprintf(tgs + strlen(tgs), sizeof(tgs) - strlen(tgs), "@%.*s",
             (krb5_princ_realm(krbctx, princ))->length,
             (krb5_princ_realm(krbctx, princ))->data);
    memset(&creds, 0, sizeof(creds));
    krb5_get_init_creds_opt_init(&gicopts);
    krb5_get_init_creds_opt_set_forwardable(&gicopts, 1);
    krberr = krb5_get_init_creds_keytab(krbctx, &creds, princ, keytab,
                                      0, tgs, &gicopts);
    if (krberr != 0) {
        if (!quiet)
            fprintf(stderr, _("Error obtaining initial credentials: %s.\n"),
                    error_message(krberr));
        return krberr;
    }

    krberr = krb5_cc_resolve(krbctx, "MEMORY:ipa-join", &ccache);
    if (krberr == 0) {
        krberr = krb5_cc_initialize(krbctx, ccache, creds.client);
    } else {
        if (!quiet)
            fprintf(stderr,
                    _("Unable to generate Kerberos Credential Cache\n"));
        rval = 19;
        goto cleanup;
    }
    krberr = krb5_cc_store_cred(krbctx, ccache, &creds);
    if (krberr != 0) {
        if (!quiet)
            fprintf(stderr,
                    _("Error storing creds in credential cache: %s.\n"),
                    error_message(krberr));
        return krberr;
    }
    krb5_cc_close(krbctx, ccache);
    ccache = NULL;
    putenv("KRB5CCNAME=MEMORY:ipa-join");

    /* Start up our XML-RPC client library. */
    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);

    xmlrpc_env_init(&env);

    xmlrpc_client_setup_global_const(&env);

#if 1
    ret = asprintf(&url, "https://%s:443/ipa/xml", ipaserver);
#else
    ret = asprintf(&url, "http://%s:8888/", ipaserver);
#endif
    if (ret == -1)
    {
        if (!quiet)
            fprintf(stderr, _("Out of memory!\n"));
        rval = 3;
        goto cleanup;
    }
    serverInfoP = xmlrpc_server_info_new(&env, url);

    argArrayP = xmlrpc_array_new(&env);
    paramArrayP = xmlrpc_array_new(&env);

    paramP = xmlrpc_string_new(&env, host);
    xmlrpc_array_append_item(&env, argArrayP, paramP);
    xmlrpc_array_append_item(&env, paramArrayP, argArrayP);
    xmlrpc_DECREF(paramP);

    if ((user_agent = set_user_agent(ipaserver)) == NULL) {
        rval = 3;
        goto cleanup;
    }
    callRPC(user_agent, &env, serverInfoP, "host_disable", paramArrayP, &resultP);
    if (handle_fault(&env)) {
        rval = 17;
        goto cleanup;
    }

    xmlrpc_struct_find_value(&env, resultP, "result", &princP);
    if (princP) {
        xmlrpc_bool result;

        xmlrpc_read_bool(&env, princP, &result);
        if (result == 1) {
            if (!quiet)
                fprintf(stderr, _("Unenrollment successful.\n"));
        } else {
            if (!quiet)
                fprintf(stderr, _("Unenrollment failed.\n"));
        }

        xmlrpc_DECREF(princP);
    } else {
        fprintf(stderr, _("result not found in XML-RPC response\n"));
        rval = 20;
        goto cleanup;
    }

cleanup:

    free(user_agent);
    if (keytab) krb5_kt_close(krbctx, keytab);
    free((char *)principal);
    free((char *)ipaserver);
    if (princ) krb5_free_principal(krbctx, princ);
    if (ccache) krb5_cc_close(krbctx, ccache);
    if (krbctx) krb5_free_context(krbctx);

    free(url);
    xmlrpc_env_clean(&env);
    xmlrpc_client_cleanup();

    return rval;
}
Exemplo n.º 10
0
static int
join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **princ, const char **subject, int force, int quiet) {
    xmlrpc_env env;
    xmlrpc_value * argArrayP = NULL;
    xmlrpc_value * paramArrayP = NULL;
    xmlrpc_value * paramP = NULL;
    xmlrpc_value * optionsP = NULL;
    xmlrpc_value * resultP = NULL;
    xmlrpc_value * structP = NULL;
    xmlrpc_server_info * serverInfoP = NULL;
    struct utsname uinfo;
    xmlrpc_value *princP = NULL;
    xmlrpc_value *krblastpwdchangeP = NULL;
    xmlrpc_value *subjectP = NULL;
    xmlrpc_value *hostdnP = NULL;
    const char *krblastpwdchange = NULL;
    char * url = NULL;
    char * user_agent = NULL;
    int rval = 0;
    int ret;

    *hostdn = NULL;
    *subject = NULL;
    *princ = NULL;

    /* Start up our XML-RPC client library. */
    xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION);

    uname(&uinfo);

    xmlrpc_env_init(&env);

    xmlrpc_client_setup_global_const(&env);

#if 1
    ret = asprintf(&url, "https://%s:443/ipa/xml", ipaserver);
#else
    ret = asprintf(&url, "http://%s:8888/", ipaserver);
#endif
    if (ret == -1)
    {
        if (!quiet)
            fprintf(stderr, _("Out of memory!\n"));
        rval = 3;
        goto cleanup;
    }

    serverInfoP = xmlrpc_server_info_new(&env, url);

    argArrayP = xmlrpc_array_new(&env);
    paramArrayP = xmlrpc_array_new(&env);

    if (hostname == NULL)
        paramP = xmlrpc_string_new(&env, uinfo.nodename);
    else
        paramP = xmlrpc_string_new(&env, hostname);
    xmlrpc_array_append_item(&env, argArrayP, paramP);
#ifdef REALM
    if (!quiet)
        printf("Joining %s to IPA realm %s\n", uinfo.nodename, iparealm);
#endif
    xmlrpc_array_append_item(&env, paramArrayP, argArrayP);
    xmlrpc_DECREF(paramP);

    optionsP = xmlrpc_build_value(&env, "{s:s,s:s}",
                                  "nsosversion", uinfo.release,
                                  "nshardwareplatform", uinfo.machine);
    xmlrpc_array_append_item(&env, paramArrayP, optionsP);
    xmlrpc_DECREF(optionsP);

    if ((user_agent = set_user_agent(ipaserver)) == NULL) {
        rval = 3;
        goto cleanup;
    }
    callRPC(user_agent, &env, serverInfoP, "join", paramArrayP, &resultP);
    if (handle_fault(&env)) {
        rval = 17;
        goto cleanup_xmlrpc;
    }

    /* Return value is the form of an array. The first value is the
     * DN, the second a struct of attribute values
     */
    xmlrpc_array_read_item(&env, resultP, 0, &hostdnP);
    xmlrpc_read_string(&env, hostdnP, (const char **)hostdn);
    xmlrpc_DECREF(hostdnP);
    xmlrpc_array_read_item(&env, resultP, 1, &structP);

    xmlrpc_struct_find_value(&env, structP, "krbprincipalname", &princP);
    if (princP) {
        xmlrpc_value * singleprincP = NULL;

        /* FIXME: all values are returned as lists currently. Once this is
         * fixed we can read the string directly.
         */
        xmlrpc_array_read_item(&env, princP, 0, &singleprincP);
        xmlrpc_read_string(&env, singleprincP, &*princ);
        xmlrpc_DECREF(princP);
        xmlrpc_DECREF(singleprincP);
    } else {
        if (!quiet)
            fprintf(stderr, _("principal not found in XML-RPC response\n"));
        rval = 12;
        goto cleanup;
    }
    xmlrpc_struct_find_value(&env, structP, "krblastpwdchange", &krblastpwdchangeP);
    if (krblastpwdchangeP && !force) {
        xmlrpc_value * singleprincP = NULL;

        /* FIXME: all values are returned as lists currently. Once this is
         * fixed we can read the string directly.
         */
        xmlrpc_array_read_item(&env, krblastpwdchangeP, 0, &singleprincP);
        xmlrpc_read_string(&env, singleprincP, &krblastpwdchange);
        xmlrpc_DECREF(krblastpwdchangeP);
        if (!quiet)
            fprintf(stderr, _("Host is already joined.\n"));
        rval = 13;
        goto cleanup;
    }

    xmlrpc_struct_find_value(&env, structP, "ipacertificatesubjectbase", &subjectP);
    if (subjectP) {
        xmlrpc_value * singleprincP = NULL;

        /* FIXME: all values are returned as lists currently. Once this is
         * fixed we can read the string directly.
         */
        xmlrpc_array_read_item(&env, subjectP, 0, &singleprincP);
        xmlrpc_read_string(&env, singleprincP, *&subject);
        xmlrpc_DECREF(subjectP);
    }

cleanup:
    if (argArrayP) xmlrpc_DECREF(argArrayP);
    if (paramArrayP) xmlrpc_DECREF(paramArrayP);
    if (resultP) xmlrpc_DECREF(resultP);

cleanup_xmlrpc:
    free(user_agent);
    free(url);
    free((char *)krblastpwdchange);
    xmlrpc_env_clean(&env);
    xmlrpc_client_cleanup();

    return rval;
}