From aefe1e49b515b55243096098f820367e53a58493 Mon Sep 17 00:00:00 2001 From: Roman Rakus Date: Fri, 7 Sep 2012 15:02:37 +0200 Subject: account: createAccount function implementation I decided to not follow the DMTF Standard strictly here. Rather than using embedded instance I use several parameters. Signed-off-by: Roman Rakus --- src/account/LMI_AccountManagementServiceProvider.c | 240 ++++++++++++++++++++- 1 file changed, 238 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/account/LMI_AccountManagementServiceProvider.c b/src/account/LMI_AccountManagementServiceProvider.c index 17a25a2..a33df80 100644 --- a/src/account/LMI_AccountManagementServiceProvider.c +++ b/src/account/LMI_AccountManagementServiceProvider.c @@ -1,9 +1,20 @@ #include #include "LMI_AccountManagementService.h" +#include "LMI_HostedAccountManagementService.h" +#include "CIM_ComputerSystem.h" +#include "LMI_Account.h" +#include "LMI_Identity.h" #include "macros.h" #include "globals.h" +#include "aux_lu.h" +#include +#include + +#include +#include + static const CMPIBroker* _cb = NULL; static void LMI_AccountManagementServiceInitialize() @@ -189,14 +200,239 @@ KUint32 LMI_AccountManagementService_CreateAccount( const CMPIContext* context, const LMI_AccountManagementServiceRef* self, const KRef* System, - const KString* AccountTemplate, + const KString* Name, + const KString* GECOS, + const KString* HomeDirectory, + const KBoolean* DontCreateHome, + const KString* Shell, + const KUint32* UID, + const KUint32* GID, + const KBoolean* SystemAccount, + const KString* Password, + const KBoolean* DontCreateGroup, KRef* Account, KRefA* Identities, CMPIStatus* status) { +/* TODO - Use embedded instance? */ +/* XXX - split to functions and/or macros */ + + char *errmsg = NULL; + +#define FAIL(MSG, ERROR, STATUS, RETVAL)\ + errmsg = malloc(256 * sizeof(char));\ + snprintf(errmsg, 256, (MSG), (ERROR));\ + KSetStatus2(cb, status, STATUS, errmsg);\ + KUint32_Set(&result, (RETVAL));\ + free(errmsg); + KUint32 result = KUINT32_INIT; + struct lu_context *luc = NULL; + struct lu_error *error = NULL; + struct lu_ent *lue = NULL, *lue_group = NULL; + + GValue val; + int create_group = 0; + gid_t gid = LU_VALUE_INVALID_ID, uid = LU_VALUE_INVALID_ID; + char *group_name = NULL, *home = NULL, *instanceid = NULL; + + const char *nameSpace = LMI_AccountManagementServiceRef_NameSpace(self); + const char *hostname = get_system_name(); + CMPIStatus st; + CMPIEnumeration *instances = NULL; + LMI_AccountRef Accountref; + LMI_IdentityRef Identityref; + CMPIObjectPath *AccountOP = NULL, *IdentityOP = NULL; + + KSetStatus(status, OK); + KUint32_Set(&result, 0); + + if (!(Name->exists && !Name->null) || !(System->exists && !System->null)) + { + FAIL("Required parameters not specified%s\n", "", ERR_FAILED, 2); + goto clean; + } + + luc = lu_start(NULL, lu_user, NULL, NULL, lu_prompt_console_quiet, NULL, + &error); + if (!luc) + { + FAIL("Error initializing: %s\n", lu_strerror(error), ERR_FAILED, 2); + goto clean; + } + + instances = cb->bft->associatorNames(cb, context, + LMI_AccountManagementServiceRef_ToObjectPath(self, NULL), + LMI_HostedAccountManagementService_ClassName, + NULL, NULL, NULL, &st); + if (!instances || + !instances->ft->hasNext(instances, NULL) || + !KMatch(System->value, + instances->ft->getNext(instances,NULL).value.ref)) + { /* This service is not linked with provided system */ + FAIL("Unable to create account on the System%s\n", "", ERR_FAILED, 2); + goto clean; + } + + lue = lu_ent_new(); + lu_user_default(luc, Name->chars, + SystemAccount->exists && !SystemAccount->null && SystemAccount->value, + lue); + + memset(&val, 0, sizeof(val)); + + /* UID */ + if (UID->exists && !UID->null) + { + lu_value_init_set_id(&val, UID->value); + lu_ent_clear(lue, LU_UIDNUMBER); + lu_ent_add(lue, LU_UIDNUMBER, &val); + g_value_unset(&val); + } + + /* GID */ + /* if specified GID, the group should exists and don't create it + * if unspecified GID, check dontcreategroup, dont create "users" group, + * create group with same name as user name + */ + lue_group = lu_ent_new(); + + if (GID->exists && !GID->null) + { /* Specified GID */ + gid = GID->value; + if (!lu_group_lookup_id(luc, gid, lue_group, &error)) + { + FAIL("Non existing group: %d\n", gid, ERR_FAILED, 2); + goto clean; + } + } + else + { /* Not specified GID */ + if (DontCreateGroup->exists && !DontCreateGroup->null && + DontCreateGroup->value) + { + /* add user to "users" group */ + group_name = malloc((strlen("users")+1) * sizeof(char)); + strcpy(group_name, "users"); + } + else + { + /* add user to the group with same name as user name */ + group_name = malloc((strlen(Name->chars)+1) * sizeof(char)); + strcpy(group_name, Name->chars); + } + if (lu_group_lookup_name(luc, group_name, lue_group, &error)) + { + gid = aux_lu_get_long(lue_group, LU_GIDNUMBER); + } + else + { + create_group = 1; + } + if (create_group) + { + lu_group_default(luc, group_name, 0, lue_group); + if (!lu_group_add(luc, lue_group, &error)) + { + FAIL("Error creating group: %s\n", lu_strerror(error), + ERR_FAILED, 2); + goto clean; + } + } + } + + + gid = aux_lu_get_long(lue_group, LU_GIDNUMBER); + + lu_value_init_set_id(&val, gid); + lu_ent_clear(lue, LU_GIDNUMBER); + lu_ent_add(lue, LU_GIDNUMBER, &val); + g_value_unset(&val); + + g_value_init(&val, G_TYPE_STRING); +#define PARAM(ATTR, VAR)\ + if ((VAR)->exists && !(VAR)->null){\ + g_value_set_string(&val, (VAR)->chars);\ + lu_ent_clear(lue, (ATTR));\ + lu_ent_add(lue, (ATTR), &val);\ + } + PARAM(LU_GECOS, GECOS); + PARAM(LU_HOMEDIRECTORY, HomeDirectory); + PARAM(LU_LOGINSHELL, Shell); +#undef PARAM + g_value_unset(&val); + + if (!lu_user_add(luc, lue, &error)) + { + FAIL("Account Creation failed: %s\n", lu_strerror(error), ERR_FAILED, + 2); + goto clean; + } + + /* Finally create home dir */ + if (!(DontCreateHome->exists && !DontCreateHome->null && + DontCreateHome->value) && !(SystemAccount->exists && + !SystemAccount->null && SystemAccount->value)) + { /* Yes, create home */ + uid = aux_lu_get_long(lue, LU_UIDNUMBER); + gid = aux_lu_get_long(lue, LU_GIDNUMBER); + home = aux_lu_get_str(lue, LU_HOMEDIRECTORY); + /* TODO - copy /etc/skel */ + /* XXX - libuser will add/export function in the future */ + if(mkdir(home, 0700) != 0) + { + FAIL("Error creating homedir: %s\n", strerror(errno), ERR_FAILED, + 3); + goto clean; + } + if (chown(home, uid, gid) != 0) + { + FAIL("Error setting ownership of homedir: %s\n", strerror(errno), + ERR_FAILED, 3); + goto clean; + errmsg = malloc(256 * sizeof(char)); + } + } + + /* Output created Account reference */ + LMI_AccountRef_Init(&Accountref, cb, nameSpace); + LMI_AccountRef_Set_Name(&Accountref, Name->chars); + LMI_AccountRef_Set_SystemName(&Accountref, hostname); + LMI_AccountRef_Set_SystemCreationClassName(&Accountref, + get_system_creation_class_name()); + LMI_AccountRef_Set_CreationClassName(&Accountref, LMI_Account_ClassName); + AccountOP = LMI_AccountRef_ToObjectPath(&Accountref, &st); + KRef_SetObjectPath(Account, AccountOP); + + /* Output created (or already existed) identities references + * it means reference to Identity of Account and Group + */ + KRefA_Init(Identities, cb, 2); + instanceid = malloc(256 * sizeof(char)); + + /* Identity of Account */ + LMI_IdentityRef_Init(&Identityref, cb, nameSpace); + snprintf(instanceid, 255, ORGID":UID:%ld", + aux_lu_get_long(lue, LU_UIDNUMBER)); + LMI_IdentityRef_Set_InstanceID(&Identityref, instanceid); + IdentityOP = LMI_IdentityRef_ToObjectPath(&Identityref, &st); + KRefA_Set(Identities, 0, IdentityOP); + + /* Identity of Group */ + snprintf(instanceid, 255, ORGID":GID:%ld", + aux_lu_get_long(lue, LU_GIDNUMBER)); + LMI_IdentityRef_Set_InstanceID(&Identityref, instanceid); + IdentityOP = LMI_IdentityRef_ToObjectPath(&Identityref, &st); + KRefA_Set(Identities, 1, IdentityOP); + +clean: +#undef FAIL + free(group_name); + free(instanceid); + if (lue) lu_ent_free(lue); + if (lue_group) lu_ent_free(lue_group); + if (luc) lu_end(luc); - KSetStatus(status, ERR_NOT_SUPPORTED); return result; } -- cgit