/* * ==================== * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common Development * and Distribution License("CDDL") (the "License"). You may not use this file * except in compliance with the License. * * You can obtain a copy of the License at * http://opensource.org/licenses/cddl1.php * See the License for the specific language governing permissions and limitations * under the License. * * When distributing the Covered Code, include this CDDL Header Notice in each file * and include the License file at http://opensource.org/licenses/cddl1.php. * If applicable, add the following below this CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * ==================== */ package org.identityconnectors.solaris.operation; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.identityconnectors.common.CollectionUtil; import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.framework.common.objects.Attribute; import org.identityconnectors.framework.common.objects.AttributeUtil; import org.identityconnectors.framework.common.objects.OperationalAttributes; import org.identityconnectors.solaris.SolarisConnection; import org.identityconnectors.solaris.attr.NativeAttribute; import org.identityconnectors.solaris.operation.search.SolarisEntry; /** * Updates any {@link NativeAttribute}, except * {@link OperationalAttributes#PASSWORD_NAME}. * * @author David Adam * */ class UpdateNativeUser extends CommandSwitches { private static final Set<String> USERMOD_ERRORS = CollectionUtil.newSet("ERROR", "command not found", "not allowed to execute"); private final static Map<NativeAttribute, String> UPDATE_SWITCHES; static { UPDATE_SWITCHES = new HashMap<NativeAttribute, String>(CommandSwitches.COMMON_SWITCHES); UPDATE_SWITCHES.put(NativeAttribute.NAME, "-l"); // for new username // attribute } public static void updateUser(SolarisEntry entry, GuardedString password, SolarisConnection conn) { conn.doSudoStart(); try { conn.executeMutexAcquireScript(); // UPDATE OF ALL ATTRIBUTES EXCEPT PASSWORD String newName = null; try { newName = updateUserImpl(entry, conn); } finally { conn.executeMutexReleaseScript(); } // PASSWORD UPDATE if (password != null) { // the username could have changed in update, so we need to // change the password for the new username: final SolarisEntry entryWithNewName = (newName != null) ? new SolarisEntry.Builder(newName).addAllAttributesFrom( entry).build() : entry; PasswdCommand.configureUserPassword(entryWithNewName, password, conn); } PasswdCommand.configurePasswordProperties(entry, conn); } finally { conn.doSudoReset(); } } /** * preform the user update. * * @param entry * @param conn * @return the new username, null otherwise (if the username hasn't been * changed). */ private static String updateUserImpl(SolarisEntry entry, SolarisConnection conn) { Attribute nameAttr = entry.searchForAttribute(NativeAttribute.NAME); // newName is null, if the name hasn't changed. String newName = (nameAttr != null) ? AttributeUtil.getStringValue(nameAttr) : null; /* * UPDATE OF USER ATTRIBUTES (except password) {@see PasswdCommand} */ String commandSwitches = CommandSwitches.formatCommandSwitches(entry, conn, UPDATE_SWITCHES); // TODO evaluate: this is based on SRA#getUpdateNativeUserScript, line // 452. But it doesn't make sense to add attributes that are not already // present in the replaceattrs. // if (newName != null) { // String newUserNameParams = " -l \"" + newName + "\" -G \"\""; // commandSwitches += newUserNameParams; // } if (commandSwitches.length() == 0) { return newName; // no update switch found, nothing to process } if (newName != null) { // The secondary groups the target user belongs to must // be extracted, the rename operation will temporarily // remove them to keep /etc/group clean. String groupsScript = getSecondaryGroupsScript(entry, conn); conn.executeCommand(groupsScript); } String cmd = conn.getModeDriver().buildUpdateUserCommand(entry, commandSwitches); conn.executeCommand(cmd, USERMOD_ERRORS); // If this is a rename operation, check to see if the user's // home directory needs to be renamed as well. if (newName != null) { // This script will restore the secondary groups to the // renamed user. final String updateGroupsCmd = conn.buildCommand(true, "usermod", "-G \"$WSGROUPS\"", newName); conn.executeCommand(updateGroupsCmd, USERMOD_ERRORS); // Test to see if the user's home directory is to be renamed. // If a new home directory was specified as part of the rename // then skip this. if (!commandSwitches.contains("-d ")) { // Rename the home directory of the user to match the new // user name. This will only be done if the basename of // the home directory matches the old username. Also, if // the renamed home directory already exists, then the // rename of the home directory will not occur. final String renameDirScript = getRenameDirScript(entry, conn, newName); conn.executeCommand(renameDirScript, USERMOD_ERRORS); } } return newName; } private static String getRenameDirScript(SolarisEntry entry, SolarisConnection conn, String newName) { return conn.getModeDriver().getRenameDirScript(entry, newName); } private static String getSecondaryGroupsScript(SolarisEntry entry, SolarisConnection conn) { String getGroups = "n=1; " + "WSGROUPS=; " + "GROUPSWORK=`" + conn.buildCommand(true, "logins") + " -m -l " + entry.getName() + " | awk '{ print $1 }'`; " + "for i in $GROUPSWORK; " + "do " + "if [ $n -eq 1 ]; then\n" + "n=2; " + "else " + "if [ $n -eq 2 ]; then " + "WSGROUPS=$i; " + "n=3; " + "else\n" + "WSGROUPS=`echo \"$WSGROUPS,$i\"`; " + "fi; " + "fi; " + "done"; return getGroups; } }