You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
16 KiB
392 lines
16 KiB
/***************************************************************************
|
|
* 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 <cstdlib>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <pwd.h>
|
|
|
|
#include <tdeapplication.h>
|
|
#include <tdestartupinfo.h>
|
|
#include <tdecmdlineargs.h>
|
|
#include <kuniqueapplication.h>
|
|
#include <tdeaboutdata.h>
|
|
|
|
#include <ksimpleconfig.h>
|
|
|
|
#include <tqdatetime.h>
|
|
#include <tqfile.h>
|
|
|
|
#include <libtdeldap.h>
|
|
|
|
#ifndef KDE_CONFDIR
|
|
#define KDE_CONFDIR "/etc/trinity"
|
|
#endif
|
|
|
|
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 <username>", I18N_NOOP("Specifies the user name in the Kerberos realm (mandatory)"), 0 },
|
|
{ "uid <user id>", I18N_NOOP("Specifies the POSIX user ID in the Kerberos realm"), 0 },
|
|
{ "password <password>", I18N_NOOP("Sets the password for the specified account to the given value"), 0 },
|
|
{ "displayname <full name>", I18N_NOOP("Sets the display name (common name) of the specified account to the given value"), 0 },
|
|
{ "homedirectory <full path>", I18N_NOOP("Sets the home directory of the specified account to the given value"), 0 },
|
|
{ "givenname <first name>", I18N_NOOP("Sets the first name of the specified account to the given value"), 0 },
|
|
{ "surname <last name>", I18N_NOOP("Sets the last name of the specified account to the given value"), 0 },
|
|
{ "telephone <number>", I18N_NOOP("Sets the telephone number of the specified account to the given value"), 0 },
|
|
{ "website <url>", I18N_NOOP("Sets the website of the specified account to the given value"), 0 },
|
|
{ "email <url>", I18N_NOOP("Sets the Email address of the specified account to the given value"), 0 },
|
|
{ "group <groupname>", 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 },
|
|
{ "primarygroup <groupname>", I18N_NOOP("Sets membership of the specified account in the group listed on the command line, and sets that group as the user's primary group."), 0 },
|
|
{ "revokeallgroups", I18N_NOOP("Revokes membership of the specified account for all groups"), 0 },
|
|
{ "adminusername <username>", I18N_NOOP("Specifies the username of the administrative user with permissions to perform the requested task"), 0 },
|
|
{ "adminpasswordfile <password file>", I18N_NOOP("Specifies the location of a file which contains the password of the administrative user"), 0 },
|
|
{ "anonymous", I18N_NOOP("Do not use authentication when contacting the realm controller"), 0 },
|
|
{ "!+command", I18N_NOOP("The command to execute on the Kerberos realm. Valid commands are: adduser deluser listusers listgroups"), 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;
|
|
if (!args->isSet("anonymous")) {
|
|
if (args->isSet("adminusername") && args->isSet("adminpasswordfile")) {
|
|
TQString passFileName = args->getOption("adminpasswordfile");
|
|
TQFile passFile(passFileName);
|
|
if (!passFile.open(IO_ReadOnly)) {
|
|
printf("[ERROR] Unable to open specified password file '%s'\n", passFileName.ascii()); fflush(stdout);
|
|
return -1;
|
|
}
|
|
TQTextStream stream(&passFile);
|
|
credentials.username = args->getOption("adminusername");
|
|
credentials.password = stream.readLine();
|
|
passFile.close();
|
|
}
|
|
else {
|
|
credentials.use_gssapi = true;
|
|
}
|
|
}
|
|
credentials.realm = realm;
|
|
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[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
LDAPUserInfoList userInfoList = ldapmanager.users(&retcode, &errorString);
|
|
if (retcode != 0) {
|
|
printf("[ERROR] Unable to retrieve list of users from realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
LDAPGroupInfoList groupInfoList = ldapmanager.groups(&retcode, &errorString);
|
|
if (retcode != 0) {
|
|
printf("[ERROR] Unable to retrieve list of users from realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
// Find the next available, reasonable UID
|
|
if (args->isSet("uid")) {
|
|
uid_t uid = atoi(args->getOption("uid"));
|
|
LDAPUserInfoList::Iterator it;
|
|
for (it = userInfoList.begin(); it != userInfoList.end(); ++it) {
|
|
LDAPUserInfo user = *it;
|
|
if (user.uid == uid) {
|
|
printf("[ERROR] The specified POSIX user ID is already in use\n");
|
|
return -1;
|
|
}
|
|
}
|
|
user.uid = uid;
|
|
}
|
|
else {
|
|
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;
|
|
}
|
|
|
|
if (!args->isSet("username")) {
|
|
printf("[ERROR] You must specify a username when adding a user\n");
|
|
return -1;
|
|
}
|
|
if (!args->isSet("surname")) {
|
|
printf("[ERROR] You must specify a surname when adding a user\n");
|
|
return -1;
|
|
}
|
|
if (!args->isSet("primarygroup")) {
|
|
printf("[ERROR] You must specify a primary group when adding a user\n");
|
|
return -1;
|
|
}
|
|
|
|
// Get user data
|
|
user.name = args->getOption("username");
|
|
user.new_password = args->getOption("password");
|
|
user.givenName = args->getOption("givenname");
|
|
user.surName = args->getOption("surname");
|
|
if (args->isSet("displayname")) {
|
|
user.commonName = args->getOption("displayname");
|
|
}
|
|
else {
|
|
user.commonName = user.givenName + " " + user.surName;
|
|
}
|
|
if (args->isSet("homedirectory")) {
|
|
user.homedir = args->getOption("homedirectory");
|
|
}
|
|
else {
|
|
user.homedir = "/home/" + user.name;
|
|
}
|
|
if (args->isSet("telephone")) {
|
|
user.telephoneNumber = args->getOption("telephone");
|
|
}
|
|
if (args->isSet("website")) {
|
|
user.website = args->getOption("website");
|
|
}
|
|
if (args->isSet("email")) {
|
|
user.email = args->getOption("email");
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
bool primary_gid_found = false;
|
|
TQString primaryGroupName = args->getOption("primarygroup");
|
|
LDAPGroupInfoList::Iterator it;
|
|
for (it = groupInfoList.begin(); it != groupInfoList.end(); ++it) {
|
|
LDAPGroupInfo group = *it;
|
|
if (primaryGroupName == group.name) {
|
|
user.primary_gid = group.gid;
|
|
primary_gid_found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!primary_gid_found) {
|
|
printf("[ERROR] Invalid primary group specified\n");
|
|
return -1;
|
|
}
|
|
if (ldapmanager.addUserInfo(user, &errorString) == 0) {
|
|
// Modify group(s) as needed
|
|
bool revoke_all = args->isSet("revokeallgroups");
|
|
if ((groupList.count() > 0) || revoke_all) {
|
|
LDAPGroupInfoList groupInfoList = ldapmanager.groups(&retcode, &errorString);
|
|
if (retcode != 0) {
|
|
printf("[ERROR] Unable to retrieve list of groups from realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
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, &errorString);
|
|
}
|
|
}
|
|
else {
|
|
// Make sure that we are NOT in this group!
|
|
if (group.userlist.contains(user.distinguishedName)) {
|
|
group.userlist.remove(user.distinguishedName);
|
|
ldapmanager.updateGroupInfo(group, &errorString);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (user.new_password != "") {
|
|
// If a new password was set, use Kerberos to set it on the server
|
|
if (ldapmanager.setPasswordForUser(user, &errorString) != 0) {
|
|
printf("[ERROR] Unable to set password for user\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
printf("[ERROR] Unable to add user with distingushed name '%s'\n[ERROR] Detailed debugging information: %s\n", user.distinguishedName.ascii(), errorString.ascii());
|
|
}
|
|
}
|
|
else if (command == "deluser") {
|
|
LDAPUserInfo deluser;
|
|
|
|
TQString errorString;
|
|
if (ldapmanager.bind(&errorString) != 0) {
|
|
printf("[ERROR] Unable to bind to Kerberos realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
LDAPUserInfoList userInfoList = ldapmanager.users(&retcode, &errorString);
|
|
if (retcode != 0) {
|
|
printf("[ERROR] Unable to retrieve list of users from realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
if (!args->isSet("username")) {
|
|
printf("[ERROR] You must specify a username when deleting a user\n");
|
|
return -1;
|
|
}
|
|
|
|
TQString delUserName = args->getOption("username");
|
|
|
|
bool found = false;
|
|
LDAPUserInfoList::Iterator it;
|
|
for (it = userInfoList.begin(); it != userInfoList.end(); ++it) {
|
|
LDAPUserInfo user = *it;
|
|
if (user.name == delUserName) {
|
|
found = true;
|
|
deluser = user;
|
|
break;
|
|
}
|
|
}
|
|
if (found) {
|
|
ldapmanager.deleteUserInfo(deluser);
|
|
}
|
|
else {
|
|
printf("[ERROR] User not found\n");
|
|
return -1;
|
|
}
|
|
// FIXME
|
|
}
|
|
else if (command == "listusers") {
|
|
TQString errorString;
|
|
if (ldapmanager.bind(&errorString) != 0) {
|
|
printf("[ERROR] Unable to bind to Kerberos realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
LDAPUserInfoList userInfoList = ldapmanager.users(&retcode, &errorString);
|
|
if (retcode != 0) {
|
|
printf("[ERROR] Unable to retrieve list of users from realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
printf("=======================================================================================================================================\n");
|
|
printf("UID\tdisplay name\tcommon name\tgiven name\tinitials\tsurname\tdefault shell\thome directory\ttelephone number\twebsite\temail address\n");
|
|
printf("=======================================================================================================================================\n");
|
|
LDAPUserInfoList::Iterator it;
|
|
for (it = userInfoList.begin(); it != userInfoList.end(); ++it) {
|
|
LDAPUserInfo user = *it;
|
|
printf("%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", user.uid, user.name.ascii(), user.commonName.ascii(), user.givenName.ascii(), user.initials.ascii(), user.surName.ascii(), user.shell.ascii(), user.homedir.ascii(), user.telephoneNumber.ascii(), user.website.ascii(), user.email.ascii()); fflush(stdout);
|
|
}
|
|
printf("=======================================================================================================================================\n");
|
|
}
|
|
else if (command == "listgroups") {
|
|
TQString errorString;
|
|
if (ldapmanager.bind(&errorString) != 0) {
|
|
printf("[ERROR] Unable to bind to Kerberos realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
LDAPGroupInfoList groupInfoList = ldapmanager.groups(&retcode, &errorString);
|
|
if (retcode != 0) {
|
|
printf("[ERROR] Unable to retrieve list of groups from realm controller\n[ERROR] Detailed debugging information: %s\n", errorString.ascii());
|
|
return -1;
|
|
}
|
|
|
|
printf("=======================================================================================================================================\n");
|
|
printf("GID\tname\n");
|
|
printf("=======================================================================================================================================\n");
|
|
LDAPGroupInfoList::Iterator it;
|
|
for (it = groupInfoList.begin(); it != groupInfoList.end(); ++it) {
|
|
LDAPGroupInfo group = *it;
|
|
printf("%d\t%s\n", group.gid, group.name.ascii()); fflush(stdout);
|
|
}
|
|
printf("=======================================================================================================================================\n");
|
|
}
|
|
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;
|
|
}
|