summaryrefslogtreecommitdiffstats
path: root/LMI_RealmdServiceProvider.c
diff options
context:
space:
mode:
authorJohn Dennis <jdennis@redhat.com>2013-03-28 15:19:45 -0400
committerJohn Dennis <jdennis@redhat.com>2013-03-28 15:19:45 -0400
commit97a213ae1c58fec62a27c47fa46b822032f3d504 (patch)
tree4c54eecc94867413579d14adeabebe45692533a3 /LMI_RealmdServiceProvider.c
parentb6e01f4262176376920a59038012a4ef273d0235 (diff)
downloadrealmd-cim-97a213ae1c58fec62a27c47fa46b822032f3d504.tar.gz
realmd-cim-97a213ae1c58fec62a27c47fa46b822032f3d504.tar.xz
realmd-cim-97a213ae1c58fec62a27c47fa46b822032f3d504.zip
Add support for leaving realm
* Implement DBus leave method * Implement LMI_RealmdKerberosRealm.Leave() method * Implement LMI_RealmdService JoinDomain() & LeaveDomain() methods * GedDBusProperties now takes CMPIStatus arg * Add LMI_REALMD_RESULT_* constants, replaced hardcoded numbers * Implement SetCMPIStatus() which replaces CMSetStatusWithChars, SetCMPIStatus() permits printf style string formatting * Move handle_g_error() from rdcp_util to rdcp_error
Diffstat (limited to 'LMI_RealmdServiceProvider.c')
-rw-r--r--LMI_RealmdServiceProvider.c286
1 files changed, 274 insertions, 12 deletions
diff --git a/LMI_RealmdServiceProvider.c b/LMI_RealmdServiceProvider.c
index 8a3c7c4..ba1a6d5 100644
--- a/LMI_RealmdServiceProvider.c
+++ b/LMI_RealmdServiceProvider.c
@@ -58,7 +58,7 @@ static CMPIStatus LMI_RealmdServiceEnumInstances(
LMI_InitRealmdServiceKeys(LMI_RealmdService, &lmi_realmd_service, name_space, host_name);
- GetDBusProperies(provider_props, REALM_DBUS_SERVICE_PATH, REALM_DBUS_PROVIDER_INTERFACE);
+ GetDBusProperies(provider_props, REALM_DBUS_SERVICE_PATH, REALM_DBUS_PROVIDER_INTERFACE, &status);
g_variant_lookup(provider_props, "Realms", "ao", &iter);
n_items = g_variant_iter_n_children(iter);
@@ -233,39 +233,39 @@ KUint32 LMI_RealmdService_Discover(
gint32 relevance = 0;
gchar **paths = NULL;
gchar *path, **pp;
- CMPICount i, n_items;
+ CMPICount i, n_paths;
- KUint32_Set(&result, 0);
+ KUint32_Set(&result, LMI_REALMD_RESULT_SUCCESS);
CMSetStatus(status, CMPI_RC_OK);
if (!rdcp_dbus_initialize(&g_error)) {
handle_g_error(&g_error, _cb, status, CMPI_RC_ERR_FAILED, "rdcp_dbus_initialize failed");
- KUint32_Set(&result, 1);
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
goto exit;
}
if (!build_g_variant_options_from_KStringA(OptionNames, OptionValues, &options, &g_error)) {
handle_g_error(&g_error, _cb, status, CMPI_RC_ERR_FAILED,
"failed to convert options to gvariant");
- KUint32_Set(&result, 1);
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
goto exit;
}
if (!dbus_discover_call(system_bus, Target->chars, options,
&relevance, &paths, &g_error)) {
handle_g_error(&g_error, _cb, status, CMPI_RC_ERR_FAILED, "dbus_discover_call() failed");
- KUint32_Set(&result, 1);
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
goto exit;
}
#ifdef RDCP_DEBUG
- print_paths(paths, "LMI_Realm_Discover: target=%s, paths:", Target->chars);
+ print_paths(paths, "%s: target=%s, paths:", __FUNCTION__, Target->chars);
#endif
- for (pp = paths, path = *pp++, n_items = 0; path; path = *pp++, n_items++);
+ for (pp = paths, path = *pp++, n_paths = 0; path; path = *pp++, n_paths++);
- if (!KRefA_Init(DiscoveredRealms, cb, n_items)) {
- KUint32_Set(&result, 1);
+ if (!KRefA_Init(DiscoveredRealms, cb, n_paths)) {
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
goto exit;
}
@@ -277,7 +277,7 @@ KUint32 LMI_RealmdService_Discover(
*status = LMI_RealmdRealmRef_InitFromDBusPath(&realmdrealm_ref, cb,
LMI_RealmdServiceRef_NameSpace((LMI_RealmdServiceRef*)self), path);
if (status->rc != CMPI_RC_OK) {
- KUint32_Set(&result, 1);
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
goto exit;
}
@@ -285,7 +285,7 @@ KUint32 LMI_RealmdService_Discover(
goto exit;
}
if (!KRefA_Set(DiscoveredRealms, i, realmdrealm_op)) {
- KUint32_Set(&result, 1);
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
goto exit;
}
}
@@ -295,13 +295,275 @@ KUint32 LMI_RealmdService_Discover(
if (options) {
g_variant_unref(options);
}
+ if (paths) {
+ g_strfreev(paths);
+ }
+
+ return result;
+}
+
+// FIXME
+static gboolean
+get_credential_supported_owner(GVariant *supported, const gchar *cred_type, const gchar **cred_owner_return)
+{
+ GVariantIter iter;
+ const gchar *type;
+ const gchar *owner;
+
+ g_variant_iter_init (&iter, supported);
+ while (g_variant_iter_loop (&iter, "(&s&s)", &type, &owner)) {
+ if (g_str_equal (cred_type, type)) {
+ *cred_owner_return = owner;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+is_credential_supported (GVariant *supported, const gchar *cred_type, const gchar *cred_owner)
+{
+ GVariantIter iter;
+ const gchar *type;
+ const gchar *owner;
+
+ g_variant_iter_init(&iter, supported);
+ while (g_variant_iter_loop (&iter, "(&s&s)", &type, &owner)) {
+ if (g_str_equal(cred_type, type) &&
+ g_str_equal(cred_owner, owner)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+KUint32 LMI_RealmdService_Join_Leave_Domain(
+ bool join,
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_RealmdServiceRef* self,
+ const KString* Domain,
+ const KString* User,
+ const KString* Password,
+ const KStringA* OptionNames,
+ const KStringA* OptionValues,
+ CMPIStatus* status)
+{
+ const gchar *method_name = NULL;
+ const gchar *supported_credentials_property = NULL;
+ GError *g_error = NULL;
+ KUint32 result = KUINT32_INIT;
+ gint32 relevance = 0;
+ gchar **paths = NULL;
+ gchar *dbus_path, **pp;
+ CMPICount n_paths;
+ const gchar *cred_type = NULL;
+ const gchar *cred_owner = NULL;
+ GVariant *supported_creds = NULL;
+ GVariant *realm_props = NULL;
+ GVariant *kerberos_membership_props = NULL;
+ GVariant *credentials = NULL;
+ GVariant *options = NULL;
+
+ KUint32_Set(&result, LMI_REALMD_RESULT_SUCCESS);
+ CMSetStatus(status, CMPI_RC_OK);
+
+ /* Assure we can communicate with DBus */
+ if (!rdcp_dbus_initialize(&g_error)) {
+ handle_g_error(&g_error, _cb, status, CMPI_RC_ERR_FAILED, "rdcp_dbus_initialize failed");
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ }
+
+ if (join) {
+ method_name = "Join";
+ supported_credentials_property = "SupportedJoinCredentials";
+ } else {
+ method_name = "Leave";
+ supported_credentials_property = "SupportedLeaveCredentials";
+ }
+
+ /* Call Discover to obtain list of DBus object paths for domain */
+ if (!build_g_variant_options_from_KStringA(OptionNames, OptionValues, &options, &g_error)) {
+ handle_g_error(&g_error, _cb, status, CMPI_RC_ERR_FAILED,
+ "failed to convert options to gvariant");
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ }
+
+ if (!dbus_discover_call(system_bus, Domain->chars, options,
+ &relevance, &paths, &g_error)) {
+ handle_g_error(&g_error, _cb, status, CMPI_RC_ERR_FAILED, "dbus_discover_call() failed");
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ }
+
+#ifdef RDCP_DEBUG
+ print_paths(paths, "%s: target=%s, paths:", __FUNCTION__, Domain->chars);
+#endif
+ for (pp = paths, dbus_path = *pp++, n_paths = 0; dbus_path; dbus_path = *pp++, n_paths++);
+
+ if (n_paths < 1) {
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_FAILED, "Domain (%s) does not exist", Domain->chars);
+ KUint32_Set(&result, LMI_REALMD_RESULT_NO_SUCH_DOMAIN);
+ goto exit;
+ }
+
+ dbus_path = paths[0];
+
+ /* Lookup the realm properties so we can determine the supported DBus interfaces */
+ GetDBusProperies(realm_props, dbus_path, REALM_DBUS_REALM_INTERFACE, status);
+ if (!SupportsDBusInterface(realm_props, REALM_DBUS_KERBEROS_MEMBERSHIP_INTERFACE)) {
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_FAILED, "Domain (%s) does not support joining or leaving",
+ Domain->chars);
+ KUint32_Set(&result, LMI_REALMD_RESULT_DOMAIN_DOES_NOT_SUPPORT_JOINING);
+ goto exit;
+ }
+
+ GetDBusProperies(kerberos_membership_props, dbus_path,
+ REALM_DBUS_KERBEROS_MEMBERSHIP_INTERFACE, status);
+
+ if (!g_variant_lookup(kerberos_membership_props, supported_credentials_property, "@a(ss)",
+ &supported_creds)) {
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_FAILED,
+ "Domain (%s) did not supply supported %s credentials",
+ Domain->chars, method_name);
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ }
+
+ if (!User->exists || User->null) {
+ /* No User */
+ if (!Password->exists || Password->null) {
+ /* No User, No Password: automatic */
+ cred_type = "automatic";
+ if (!get_credential_supported_owner(supported_creds, cred_type, &cred_owner)) {
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_FAILED,
+ "Domain (%s) does not support automatic %s credentials",
+ Domain->chars, method_name);
+ KUint32_Set(&result, LMI_REALMD_RESULT_DOMAIN_DOES_NOT_SUPPORT_PROVIDED_CREDENTIALS);
+ goto exit;
+ }
+
+ credentials = g_variant_new ("(ssv)", cred_type, cred_owner,
+ g_variant_new_string (""));
+
+ } else {
+ /* No User, Password: one time password using secret */
+ cred_type = "secret";
+ if (!get_credential_supported_owner(supported_creds, cred_type, &cred_owner)) {
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_FAILED,
+ "Domain (%s) does not support secret %s credentials",
+ Domain->chars, method_name);
+ KUint32_Set(&result, LMI_REALMD_RESULT_DOMAIN_DOES_NOT_SUPPORT_PROVIDED_CREDENTIALS);
+ goto exit;
+ }
+ credentials = g_variant_new("(ssv)", cred_type, cred_owner,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ Password->chars,
+ strlen(Password->chars), 1));
+ }
+ } else {
+ /* User */
+ if (!Password->exists || Password->null) {
+ /* User, No Password: invalid combination */
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_INVALID_PARAMETER,
+ "Must provide a password when User is provided");
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ } else {
+ /* User, Password: password auth */
+ cred_type = "password";
+ cred_owner = "administrator";
+ if (!is_credential_supported(supported_creds, cred_type, cred_owner)) {
+ SetCMPIStatus(cb, status, CMPI_RC_ERR_FAILED,
+ "Domain (%s) does not support password with administrator ownership credentials",
+ Domain->chars);
+ KUint32_Set(&result, LMI_REALMD_RESULT_DOMAIN_DOES_NOT_SUPPORT_PROVIDED_CREDENTIALS);
+ goto exit;
+ }
+ credentials = g_variant_new("(ssv)", cred_type, cred_owner,
+ g_variant_new("(ss)", User->chars, Password->chars));
+
+ }
+ }
+
+ if (join) {
+ if (!dbus_join_call(system_bus, dbus_path, credentials, options, &g_error)) {
+ handle_g_error(&g_error, cb, status, CMPI_RC_ERR_FAILED, "dbus_join_call() failed");
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ }
+ } else {
+ if (!dbus_leave_call(system_bus, dbus_path, credentials, options, &g_error)) {
+ handle_g_error(&g_error, cb, status, CMPI_RC_ERR_FAILED, "dbus_leave_call() failed");
+ KUint32_Set(&result, LMI_REALMD_RESULT_FAILED);
+ goto exit;
+ }
+ }
+
+
+ exit:
+
+ if (realm_props) {
+ g_variant_unref(realm_props);
+ }
+
+ if (kerberos_membership_props) {
+ g_variant_unref(kerberos_membership_props);
+ }
+
+ if (options) {
+ g_variant_unref(options);
+ }
if (paths) {
g_strfreev(paths);
}
+ if (credentials) {
+ g_variant_unref(credentials);
+ }
return result;
}
+KEXTERN KUint32 LMI_RealmdService_JoinDomain(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_RealmdServiceRef* self,
+ const KString* Domain,
+ const KString* User,
+ const KString* Password,
+ const KStringA* OptionNames,
+ const KStringA* OptionValues,
+ CMPIStatus* status)
+{
+ return LMI_RealmdService_Join_Leave_Domain(true, cb, mi, context, self,
+ Domain, User, Password,
+ OptionNames, OptionValues,
+ status);
+}
+
+KEXTERN KUint32 LMI_RealmdService_LeaveDomain(
+ const CMPIBroker* cb,
+ CMPIMethodMI* mi,
+ const CMPIContext* context,
+ const LMI_RealmdServiceRef* self,
+ const KString* Domain,
+ const KString* User,
+ const KString* Password,
+ const KStringA* OptionNames,
+ const KStringA* OptionValues,
+ CMPIStatus* status)
+{
+ return LMI_RealmdService_Join_Leave_Domain(false, cb, mi, context, self,
+ Domain, User, Password,
+ OptionNames, OptionValues,
+ status);
+}
KONKRET_REGISTRATION(
"root/cimv2",