diff --git a/cmdline/Makefile.am b/cmdline/Makefile.am new file mode 100644 index 0000000..7f6bdc3 --- /dev/null +++ b/cmdline/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES= $(all_includes) $(KDE_INCLUDES)/tde + +bin_PROGRAMS = tdeldapmanager + +tdeldapmanager_SOURCES = main.cpp + +tdeldapmanager_METASOURCES = AUTO +tdeldapmanager_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -ltdetexteditor -ltdeldap + +KDE_OPTIONS = nofinal diff --git a/cmdline/main.cpp b/cmdline/main.cpp new file mode 100644 index 0000000..a42b8d7 --- /dev/null +++ b/cmdline/main.cpp @@ -0,0 +1,212 @@ +/*************************************************************************** + * Copyright (C) 2013 by Timothy Pearson * + * kb9vqf@pearsoncomputing.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +// FIXME +// Connect this to CMake/Automake +#define KDE_CONFDIR "/etc/trinity" + +static const char description[] = + I18N_NOOP("TDE utility for managing a Kerberos realm"); + +static const char version[] = "v0.0.1"; + +static const TDECmdLineOptions options[] = +{ + { "forcepwchangenextlogin", I18N_NOOP("Force the user to change password on next login"), 0 }, + { "username ", I18N_NOOP("Specifies the user name in the Kerberos realm"), 0 }, + { "password ", I18N_NOOP("Sets the password for the specified account to the given value"), 0 }, + { "givenname ", I18N_NOOP("Sets the first name of the specified account to the given value"), 0 }, + { "surname ", I18N_NOOP("Sets the last name of the specified account to the given value"), 0 }, + { "group ", I18N_NOOP("Sets membership of the specified account in the groups listed on the command line, and revokes membership in any groups not listed. This option may be used multiple times."), 0 }, + { "revokeallgroups", I18N_NOOP("Revokes membership of the specified account for all groups"), 0 }, + { "!+command", I18N_NOOP("The command to execute on the Kerberos realm. Valid commands are: adduser"), 0 }, + { "!+realm", I18N_NOOP("The Kerberos realm on which to execute the specified command. Example: MY.REALM"), 0 }, + { "", I18N_NOOP("This utility will use GSSAPI to connect to the realm controller. You must own an active, valid Kerberos ticket in order to use this utility!"), 0 }, + TDECmdLineLastOption // End of options. +}; + +int main(int argc, char *argv[]) +{ + TDEAboutData aboutData( "tdeldapmanager", I18N_NOOP("Kerberos Realm Manager"), + version, description, TDEAboutData::License_GPL, + "(c) 2013, Timothy Pearson"); + aboutData.addAuthor("Timothy Pearson",0, "kb9vqf@pearsoncomputing.net"); + TDECmdLineArgs::init(argc, argv, &aboutData); + TDECmdLineArgs::addCmdLineOptions(options); + KUniqueApplication::addCmdLineOptions(); + TDEApplication::disableAutoDcopRegistration(); + + TDEApplication app(false, false); + + TDEStartupInfo::appStarted(); + + KSimpleConfig systemconfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" )); + + //====================================================================================================================================================== + // + // Manager code follows + // + //====================================================================================================================================================== + + // FIXME + // forcepwchangenextlogin not implemented! + + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + if (args->count() > 1) { + int retcode; + + TQString command = TQString(args->arg(0)); + TQString realm = TQString(args->arg(1)); + + systemconfig.setGroup("LDAPRealm-" + realm); + TQString host = systemconfig.readEntry("admin_server"); + LDAPCredentials credentials; + credentials.use_gssapi = true; + LDAPManager ldapmanager(realm, host, &credentials); + + if (command == "adduser") { + LDAPUserInfo user; + + TQString errorString; + if (ldapmanager.bind(&errorString) != 0) { + printf("[ERROR] Unable to bind to Kerberos realm controller\n\r[ERROR] Detailed debugging information: %s\n\r", errorString.ascii()); + return -1; + } + + LDAPUserInfoList userInfoList = ldapmanager.users(&retcode); + if (retcode != 0) { + printf("[ERROR] Unable to retrieve list of users from realm controller\n\r"); + return -1; + } + LDAPGroupInfoList groupInfoList = ldapmanager.groups(&retcode); + if (retcode != 0) { + printf("[ERROR] Unable to retrieve list of users from realm controller\n\r"); + return -1; + } + + // Find the next available, reasonable UID + uid_t uid = 100; + LDAPUserInfoList::Iterator it; + for (it = userInfoList.begin(); it != userInfoList.end(); ++it) { + LDAPUserInfo user = *it; + if (user.uid >= uid) { + uid = user.uid + 1; + } + } + user.uid = uid; + + // Get user data + user.name = args->getOption("username"); + user.new_password = args->getOption("password"); + user.givenName = args->getOption("givenname"); + user.surName = args->getOption("surname"); + + // Get list of groups + QCStringList groupList = args->getOptionList("group"); + + // Try to find a reasonable place to stuff the new entry + // Do any users exist right now? + if (userInfoList.begin() != userInfoList.end()) { + user.distinguishedName = (*userInfoList.begin()).distinguishedName; + int eqpos = user.distinguishedName.find("=")+1; + int cmpos = user.distinguishedName.find(",", eqpos); + user.distinguishedName.remove(eqpos, cmpos-eqpos); + user.distinguishedName.insert(eqpos, user.name); + } + else { + user.distinguishedName = "uid=" + user.name + "," + ldapmanager.basedn(); + } + if (ldapmanager.addUserInfo(user) == 0) { + // Modify group(s) as needed + bool revoke_all = args->isSet("revokeallgroups"); + if ((groupList.count() > 0) || revoke_all) { + LDAPGroupInfoList groupInfoList = ldapmanager.groups(&retcode); + if (retcode != 0) { + printf("[ERROR] Unable to retrieve list of users from realm controller\n\r"); + return -1; + } + LDAPGroupInfoList::Iterator it; + for (it = groupInfoList.begin(); it != groupInfoList.end(); ++it) { + LDAPGroupInfo group = *it; + if ((!revoke_all) && (groupList.contains(group.name.ascii()))) { + // Make sure that we are in this group! + if (!group.userlist.contains(user.distinguishedName)) { + group.userlist.append(user.distinguishedName); + ldapmanager.updateGroupInfo(group); + } + } + else { + // Make sure that we are NOT in this group! + if (group.userlist.contains(user.distinguishedName)) { + group.userlist.remove(user.distinguishedName); + ldapmanager.updateGroupInfo(group); + } + } + } + } + + if (user.new_password != "") { + // If a new password was set, use Kerberos to set it on the server + errorString = TQString::null; + if (ldapmanager.setPasswordForUser(user, &errorString) != 0) { + printf("[ERROR] Unable to set password for user\n\r[ERROR] Detailed debugging information: %s\n\r", errorString.ascii()); + } + ldapmanager.unbind(true); // Using kadmin on admin users/groups can disrupt our LDAP connection (likely due to the ACL rewrite) + } + } + } + else { + TDECmdLineArgs::usage(i18n("An invalid command was specified")); + return -1; + } + } + else { + if (args->count() > 0) { + TDECmdLineArgs::usage(i18n("No Kerberos realm was specified")); + return -1; + } + else { + TDECmdLineArgs::usage(i18n("No command was specified")); + return -1; + } + } + + //====================================================================================================================================================== + + return 0; +} diff --git a/subdirs b/subdirs index 0e67810..4eb573f 100644 --- a/subdirs +++ b/subdirs @@ -1,3 +1,4 @@ doc po +cmdline src