diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 37333bf25ad9a4c538250f5af2f9f1d666362883 (patch) | |
tree | c45e8df5b9efbffe07eb3d9340df7811c7e16943 /kuser | |
download | tdeadmin-37333bf25ad9a4c538250f5af2f9f1d666362883.tar.gz tdeadmin-37333bf25ad9a4c538250f5af2f9f1d666362883.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeadmin@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kuser')
82 files changed, 11031 insertions, 0 deletions
diff --git a/kuser/AUTHORS b/kuser/AUTHORS new file mode 100644 index 0000000..f3913c9 --- /dev/null +++ b/kuser/AUTHORS @@ -0,0 +1,2 @@ +Denis Perchine <dyp@perchine.com> +Szombathelyi Gyrgy <gyurco@freemail.hu>
\ No newline at end of file diff --git a/kuser/ChangeLog b/kuser/ChangeLog new file mode 100644 index 0000000..9457e68 --- /dev/null +++ b/kuser/ChangeLog @@ -0,0 +1,47 @@ +29/04/2000: Simplified quota.cpp(becames 2 times smaller). Please test it. +28/04/2000: Move KUser to actions. + User is shown in delete user message box. + Use operator[] for list item access. + Use & instead of pointers to objects (cosy for []). + Rename mainDlg to mainView. + Move all global objects out of mainView. +24/03/2000: Move quota ifdef code to kuqconf.h. + Error messages are without flags now. +12/07/1999: fgetpwent/getpwent/fgetgrent/getgrent issue fixed (FreeBSD have no + fxx funcs. Thanks to Hans Petter Bieker <zerium@traad.lavvu.no>. +24/04/1999: change _KU_FIRST_USER to KU_FIRST_USER, and put a define for it into + globals.h <duncan@kde.org> +24/04/1999: Bug 'Group properties did show nothing in 'Other Users' listbox.' + fixed, documentation in SGML created. +23/04/1999: User create and delete postpone logic implemented. +04/04/1999: Bug #1133 'new fixes dont create new user home directory anymore' +01/04/1999: Bug #895 'Kuser doesn't restore the permissions on /etc/shadow.' + +19990328: added #ifdef's to kuser.cpp and kgroup.cpp so that if + _KU_FIRST_USER is defined to be, say, 500, then UID's and GID's + for regular users start at 500. If _KU_FIRST_USER is not defined, + they start at 1001, the default, as before. _KU_FIRST_USER can + be defined in kdeadmin/config.h. (This is to make it easy to + compile kuser for compatibitlity with RedHat, where regular users + start at UID 500, and the User Private Group scheme is used for + GID's.) <duncan@kde.org> + + +22/12/98: RedHat awared issues added. + Private group mechanism implemented. Works both for + add and delete. + +12/10/98: Simple property dialog added + +04/10/98: Use layouts in Edit group dialog (QtArch is rulez!!!) + +04/10/98: Patch by Rudolf Weber <rw@weber.ravnet.de> incorporated in part + if NIS support. + NIS support. + It is possible to create homedir when adding user. + It is possible to create mailbox when adding user. + It is possible to remove homedir when removing user. + It is possible to remove processes when removing user. + It is possible to remove crontabs when removing user. + It is possible to remove mailbox when removing user. + Preferences dialog added. diff --git a/kuser/Makefile.am b/kuser/Makefile.am new file mode 100644 index 0000000..d431ec5 --- /dev/null +++ b/kuser/Makefile.am @@ -0,0 +1,60 @@ +INCLUDES = -I.. -I$(top_srcdir)/kuser $(all_includes) + +# May be -D_XU_QUOTA -D_XU_SHADOW +#AM_CXXFLAGS = $(KU_NIS) $(KU_QUOTA) $(QUOTACTL) -D_KU_DEBUG + +kuser_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kuser_LDADD = $(LIB_KDEUI) $(LIBCRYPT) $(LIBSHADOW) $(LIBGEN) $(LIB_KABC) -lkntlm + +####### Files + +kuser_SOURCES = \ + mainWidget.cpp editGroup.cpp kuservw.cpp \ + kgroupvw.cpp delUser.cpp \ + kuser.cpp kgroup.cpp main.cpp mainView.cpp \ + propdlg.cpp misc.cpp pwddlg.cpp \ + addUser.cpp editDefaults.cpp \ + kglobal.cpp sid.cpp\ + kuserfiles.cpp kgroupfiles.cpp kuserldap.cpp kgroupldap.cpp \ + kusersystem.cpp kgroupsystem.cpp selectconn.cpp\ + sha1.cpp kuserprefs.kcfgc \ + filessettings.ui generalsettings.ui ldapsettings.ui ldapsamba.ui passwordpolicy.ui + +kuser_METASOURCES = AUTO + +# the following are only useful, if you want to use "make dist" +noinst_HEADERS = \ + mainWidget.h editGroup.h kuservw.h \ + kuser.h mainView.h kgroup.h delUser.h \ + kgroupvw.h propdlg.h globals.h misc.h \ + pwddlg.h addUser.h \ + editDefaults.h selectconn.h sha1.h sid.h kglobal_.h \ + kusersystem.h kgroupsystem.h kuserfiles.h kgroupfiles.h kuserldap.h kgroupldap.h + +kde_kcfg_DATA = kuser.kcfg + +EDITABLE = $(noinst_HEADERS) $(kuser_SOURCES) Makefile.am + +EXTRA_DIST = README AUTHORS THANKS kuser.desktop + +rcdir = $(kde_datadir)/kuser +rc_DATA = kuserui.rc + +# the programs get installed in $(prefix)/bin +bin_PROGRAMS = kuser + +# the subdirs we have. Better would be to include pic here too +SUBDIRS = pic toolbar icon + +xdg_apps_DATA = kuser.desktop + +edit:: + xemacs -fn "-edict-fixed-medium-r-*-*-*-120-*-*-*-*-koi8-r" -geometry 142x41+0+0 $(EDITABLE)& + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kuser.pot + +pot:: + /usr/local/bin/xgettext -ki18n -o kuser.pot -p ../po -d kuser -C -n *.cpp + /usr/local/bin/msgmerge --strict -v -o $(podir)/kuser.pot + mv $(podir)/ru/kuser.po diff --git a/kuser/README b/kuser/README new file mode 100644 index 0000000..b163125 --- /dev/null +++ b/kuser/README @@ -0,0 +1,19 @@ +This version of KUser is based on the work of: +Denis Perchine <dyp@perchine.com> + +Original README: +---------------------- +KUser is rewritten XUser which was written in XForms. +It supports: +Solaris +Linux +Irix +FreeBSD +HPUX + +ATTENTION: BACKUP ALL OF YOUR DATA. THIS PROGRAM MAY DESTROY +IT. BE CAREFUL. +---------------------- + +If you found a bug please post a bug report to the KDE bug database: +http://bugs.kde.org diff --git a/kuser/THANKS b/kuser/THANKS new file mode 100644 index 0000000..12a1af7 --- /dev/null +++ b/kuser/THANKS @@ -0,0 +1,20 @@ +Great thanks to: + +Paul Kendall <paul@orion.co.nz> (for Irix quota support, + his beautiful ktablevw classes and some minor patches) +Bernhard Rosenkraenzer <bero@redhat.com> (for some glibc2 fixes) +Alex Zepeda <garbanzo@hooked.net> (for FreeBSD support) +Mario Weilguni <mweilguni@sime.com> (for some usefull comments and suggestions) +Michael Rodionov <marod@solo.iis.nsk.su> (for his icons) +Chia-liang Kao <clkao@tc.neto.net> (for some typo corrections) +Uwe Thiem <uwe@uwix.alt.na> (for some Aplha notes) +Bernd Johannes Wuebben <wuebben@math.cornell.edu> (for some defines corrections) +Christophe Prudhomme <Christophe.Prudhomme@asci.fr> (for HP-UX notes and usefull suggestions) +Joerg Bornschein <theodor@disorder.ruhr.de> (for transparent pixmaps) +Clemens Drews <clemens.drews@hamburg.snafu.de> (for small password fix) +Kevin Street <street@iname.com> (for big FreeBSD patch) +Rudolf Weber <rw@weber.ravnet.de> (for NIS-related patch and some other futures) +Duncan Haldane <f.d.m.haldane@cwix.com> (for RedHat specific issues and testing) +Hans Petter Bieker <zerium@traad.lavvu.no> (for FreeBSD fgetpwent/getpwent/fgetr +gent/getgrent fixes) +"Steven M. Schultz" <sms@TO.GD-ES.COM> (for BSDI support) diff --git a/kuser/TODO b/kuser/TODO new file mode 100644 index 0000000..9be5109 --- /dev/null +++ b/kuser/TODO @@ -0,0 +1,29 @@ +Must do soon (these are very easy): +- Implement UID->SID like in ldapsam (Requires introducing the algorithmic RID base). - Ready +- Newer samba schema support (new attributes in sambaSamAccount in Samba>=3.0.6). - Ready +- Support LDAP entries with more objectclasses than we handle (part of #95366). - Ready for users (lazy to do for groups) + +Other: +- Add Kerberos support - Native kerberos protocols or LDAP backed? + I prefer to add it to the LDAP backend, but first I need to find an + LDAP-backed KDC. I heard that Heimdal can do this. +- Filtering users and groups, and implement it in backends, so it would + be possible to use server-side filtering (mainly in LDAP) +- Find next available UID and RID using LDAP sorting control - need an + ldap server which implements this control. Also I don't know is this a + good idea or not. +- Proper cross-check between user and group SIDs. +- Issue a warning if Unix/Samba account settings are not consistent with + each other (e.g the group of primary group ID != group of primary group SID). +- Other consistency checks (unique user/group IDs, unique SIDs, etc...). +- Copy data between backends. +- Update docs + +And some TODOs from the past which are still unsolved: +- Add 'Help' button to user and group properties dialogs. +- Add right mouse popup +- Replace call of rm with own procedure. +- Use QFile for file operations. +- How about having group name(s) next to the Full name of a user in the upper + panel, and similarly user names for a group in the lower pannel -- in a + separate column? diff --git a/kuser/addUser.cpp b/kuser/addUser.cpp new file mode 100644 index 0000000..4bd957e --- /dev/null +++ b/kuser/addUser.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> + +#include <qdir.h> +#include <qgroupbox.h> + +#include <kdebug.h> + +#include "kglobal_.h" +#include "misc.h" + +#include "addUser.h" +#include <kmessagebox.h> + +addUser::addUser( KU::KUser *AUser, bool useprivategroup, + QWidget *parent, const char *name ) : + propdlg( AUser, useprivategroup, parent, name ) +{ + QGroupBox *group = new QGroupBox(frontpage); + group->setTitle(i18n("New Account Options")); + QVBoxLayout *groupLayout = new QVBoxLayout(group, marginHint(), spacingHint()); + groupLayout->addSpacing(group->fontMetrics().lineSpacing()); + groupLayout->setAutoAdd(true); + createhome = new QCheckBox(i18n("Create home folder"), group); + createhome->setChecked(true); + copyskel = new QCheckBox(i18n("Copy skeleton"), group); + connect(createhome, SIGNAL(toggled(bool)), copyskel, SLOT(setEnabled(bool))); + frontlayout->addMultiCellWidget(group, frontrow, frontrow, 0, 2); + + if ( useprivategroup ) pbprigr->setEnabled( false ); +} + +void addUser::slotOk() +{ + KU::KUser *user = mUsers.first(); + + if ( !check() ) return; + + mergeUser( user, user ); + + if ( ( user->getCaps() & KU::KUser::Cap_POSIX ) && + kug->getUsers().lookup( user->getUID() ) ) { + KMessageBox::sorry( 0, i18n("User with UID %1 already exists.").arg( user->getUID() ) ); + return; + } + + if ( ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) && + ( user->getCaps() & KU::KUser::Cap_Samba ) ) { + if ( kug->getUsers().lookup_sam( user->getSID().getRID() ) ) { + KMessageBox::sorry( 0, i18n("User with RID %1 already exists.").arg( user->getSID().getRID() ) ); + return; + } + } + + if (createhome->isChecked()) + { + user->setCreateHome(true); + user->setCreateMailBox(true); + } + if (copyskel->isChecked()) + { + user->setCopySkel(true); + } + + if (user->getCreateHome() && !checkHome()) + return; + + if (user->getCreateMailBox() && !checkMailBox()) + user->setCreateMailBox(false); + + saveg(); + accept(); +} + +bool addUser::checkHome() +{ + KU::KUser *user = mUsers.first(); + + struct stat s; + int r; + + QString h_dir = user->getHomeDir(); + r = stat( QFile::encodeName(h_dir), &s ); + + if ( (r == -1) && (errno == ENOENT) ) + return true; + + if (r == 0) { + if (S_ISDIR(s.st_mode)) { + if ( KMessageBox:: + warningContinueCancel ( 0, + i18n("Folder %1 already exists!\n%2 may become owner and permissions may change.\nDo you really want to use %3?"). + arg(h_dir).arg(user->getName()).arg(h_dir), QString::null, KStdGuiItem::cont() ) == KMessageBox::Cancel ) + + return false; + else + return true; + } else + KMessageBox::error( 0, i18n("%1 is not a folder.").arg(h_dir) ); + } else + KMessageBox::error( 0, i18n("stat() failed on %1.").arg(h_dir) ); + + return false; +} + +bool addUser::checkMailBox() +{ + QString mailboxpath; + KU::KUser *user = mUsers.first(); + + struct stat s; + int r; + + mailboxpath = QFile::decodeName(MAIL_SPOOL_DIR) + "/" + user->getName(); + r = stat(QFile::encodeName(mailboxpath), &s); + + if ((r == -1) && (errno == ENOENT)) + return true; + + if (r == 0) + if (S_ISREG(s.st_mode)) + KMessageBox::error( 0, i18n("Mailbox %1 already exists (uid=%2).") + .arg(mailboxpath) + .arg(s.st_uid) ); + else + KMessageBox::error( 0, i18n("%1 exists but is not a regular file.") + .arg(mailboxpath) ); + else + KMessageBox::error( 0, i18n("stat() failed on %1.").arg(mailboxpath) ); + + return false; +} +#include "addUser.moc" diff --git a/kuser/addUser.h b/kuser/addUser.h new file mode 100644 index 0000000..786bdea --- /dev/null +++ b/kuser/addUser.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_ADDUSER_H_ +#define _KU_ADDUSER_H_ + +#include <qcheckbox.h> +#include "propdlg.h" + +class addUser: public propdlg { + Q_OBJECT +public: + addUser(KU::KUser *AUser, bool useprivategroup, + QWidget *parent = 0, const char *name = 0 ); + + void setCreateHomeDir(bool b) + { createhome->setChecked(b); } + + void setCopySkel(bool b) + { copyskel->setChecked(b); } + +protected slots: + virtual void slotOk(); +protected: + bool checkHome(); + bool checkMailBox(); + + QCheckBox *createhome; + QCheckBox *copyskel; +}; + +#endif // _KU_ADDUSER_H + + diff --git a/kuser/configure.in.in b/kuser/configure.in.in new file mode 100644 index 0000000..353857b --- /dev/null +++ b/kuser/configure.in.in @@ -0,0 +1,64 @@ +dnl this is for kuser: + +AC_DEFUN([KUSER_CRYPT_TESTS], [ + AC_REQUIRE([KDE_MISC_TESTS]) dnl for LIBCRYPT + AC_REQUIRE([KDE_SHADOWPASSWD]) dnl for LIBSHADOW and LIBGEN +]) + +KUSER_CRYPT_TESTS + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS(crypt.h fcntl.h mntent.h linux/quota.h linux/unistd.h \ + paths.h sys/fs/ufs_quota.h sys/mntent.h sys/mnttab.h \ + sys/quota.h sys/time.h unistd.h sys/params.h sys/param.h \ + signal.h sys/mount.h sys/fcntl.h) + +case "$host" in +*irix*) AC_DEFINE(HAVE_IRIX, 1, [Irix]) + ;; +*linux*) AC_DEFINE(HAVE_LINUX, 1, [Linux]) + ;; +esac + +AC_ARG_WITH(hometemplate, [ --with-hometemplate use specified template for homedir [default=/home/%U] ], ku_hometemplate="$withval", ku_hometemplate="/home/%U") +AC_DEFINE_UNQUOTED(KU_HOMETEMPLATE, "$ku_hometemplate",[default template for homedir]) + +AC_ARG_WITH(first-uid, [ --with-first-uid first normal user ID [default=500] ], ku_firstuid="$withval", ku_firstuid="500") +AC_DEFINE_UNQUOTED(KU_FIRSTUID, $ku_firstuid, [first user ID]) +AC_SUBST(KU_FIRSTUID) + +AC_ARG_WITH(first-gid, [ --with-first-gid first normal group ID [default=500] ], ku_firstgid="$withval", ku_firstgid="500") +AC_DEFINE_UNQUOTED(KU_FIRSTGID, $ku_firstgid, [first group ID]) +AC_SUBST(KU_FIRSTGID) + +AC_ARG_WITH(private-groups, [ --with-private-groups user private groups [default=no] ], ku_userprivategroup="$withval", ku_userprivategroup="no") +if test "$ku_userprivategroup" = "yes"; then + ku_userprivategroup="true" +else + ku_userprivategroup="false" +fi +AC_DEFINE_UNQUOTED(KU_USERPRIVATEGROUP, $ku_userprivategroup, [private groups]) + +AC_ARG_WITH(home-perm, [ --with-home-perm home directory permissions [default=0700] ], ku_homedir_perm="$withval", ku_homedir_perm="0700") +AC_DEFINE_UNQUOTED(KU_HOMEDIR_PERM, $ku_homedir_perm, [home directory permissions]) +AC_SUBST(KU_HOMEDIR_PERM) + +AC_ARG_WITH(mailbox-perm, [ --with-mailbox-perm mailbox permissions [default=0660] ], ku_mailbox_perm="$withval", ku_mailbox_perm="0660") +AC_DEFINE_UNQUOTED(KU_MAILBOX_PERM, $ku_mailbox_perm, [mailbox permissions]) +AC_SUBST(KU_MAILBOX_PERM) + +AC_ARG_WITH(mailbox-gid, [ --with-mailbox-gid mailbox gid [default=0] ], ku_mailbox_gid="$withval", ku_mailbox_gid="0") +AC_DEFINE_UNQUOTED(KU_MAILBOX_GID, $ku_mailbox_gid, [mailbox gid]) +AC_SUBST(KU_MAILBOX_GID) + +KDE_CHECK_FUNC_EXT(fgetpwent, [#include <pwd.h>], [(void) fgetpwent(0)], [], FGETPWENT) +KDE_CHECK_FUNC_EXT(fgetgrent, [#include <grp.h>], [(void) fgetgrent(0)], [], FGETGRENT) +KDE_CHECK_FUNC_EXT(fgetspent, [#include <shadow.h>], [(void) fgetspent(0)], [], FGETSPENT) + +AC_LANG_SAVE +dnl AC_C_BIGENDIAN has a bug (one of its tests uses "main()" instead of +dnl "int main()") so C++ compilers would break. Thats why we switch languages +AC_C_BIGENDIAN +AC_LANG_RESTORE diff --git a/kuser/delUser.cpp b/kuser/delUser.cpp new file mode 100644 index 0000000..1d545bc --- /dev/null +++ b/kuser/delUser.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002 Waldo Bastian <bastian@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "delUser.h" + +#include <qlabel.h> +#include <qvbox.h> +#include <qfile.h> + +#include <klocale.h> + +delUser::delUser(KU::KUser *AUser, QWidget *parent, const char *name) + : KDialogBase( parent, name, true, i18n("Delete User"), + KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true ) +{ + QVBox *page = makeVBoxMainWidget(); + new QLabel( i18n("<p>Deleting user <b>%1</b>" + "<p>Also perform the following actions:").arg(AUser->getName()), + page); + m_deleteHomeDir = new QCheckBox(i18n("Delete &home folder: %1").arg(AUser->getHomeDir()), page); + QString mailboxpath = QFile::decodeName(MAIL_SPOOL_DIR) + "/" + AUser->getName(); + m_deleteMailBox = new QCheckBox(i18n("Delete &mailbox: %1").arg(mailboxpath), page); + setButtonGuiItem(KDialogBase::Ok, KStdGuiItem::del()); +} + +#include "delUser.moc" diff --git a/kuser/delUser.h b/kuser/delUser.h new file mode 100644 index 0000000..0317a9b --- /dev/null +++ b/kuser/delUser.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2002 Waldo Bastian <bastian@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + + +#ifndef _KU_DELUSER_H_ +#define _KU_DELUSER_H_ + +#include <kdialogbase.h> +#include <qcheckbox.h> + +#include "kuser.h" + +class delUser: public KDialogBase { + Q_OBJECT +public: + delUser(KU::KUser *AUser, QWidget *parent = 0, const char *name = 0); + + bool getDeleteHomeDir() + { return m_deleteHomeDir->isChecked(); } + bool getDeleteMailBox() + { return m_deleteMailBox->isChecked(); } + +private: + QCheckBox *m_deleteHomeDir; + QCheckBox *m_deleteMailBox; +}; + +#endif // _KU_DELUSER_H + + diff --git a/kuser/editDefaults.cpp b/kuser/editDefaults.cpp new file mode 100644 index 0000000..82aba32 --- /dev/null +++ b/kuser/editDefaults.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <kdebug.h> + +#include <ktabwidget.h> +#include <kcombobox.h> +#include <kmessagebox.h> +#include <klineedit.h> +#include <knuminput.h> +#include <kpushbutton.h> +#include <kabc/ldapconfigwidget.h> +#include <kabc/ldapurl.h> + +#include "editDefaults.h" +#include "generalsettings.h" +#include "filessettings.h" +#include "ldapsettings.h" +#include "ldapsamba.h" +#include "passwordpolicy.h" +#include "misc.h" + +editDefaults::editDefaults( KConfigSkeleton *config, QWidget *parent, const char *name ) : + KConfigDialog( parent, name, config, IconList, + Default|Ok|Apply|Cancel|Help, Ok, true ) +{ + KTabWidget *page1 = new KTabWidget( this ); + page1->setMargin( KDialog::marginHint() ); + + GeneralSettings *page1a = new GeneralSettings( this ); + page1a->kcfg_shell->insertItem( i18n("<Empty>" ) ); + page1a->kcfg_shell->insertStringList( readShells() ); + page1->addTab( page1a, i18n("Connection") ); + PasswordPolicy *page1b = new PasswordPolicy( this ); + page1->addTab( page1b, i18n("Password Policy") ); + addPage( page1, i18n("General"), "", i18n("General Settings") ); + + FilesSettings *page2 = new FilesSettings( this ); + addPage( page2, i18n("Files"), "", i18n("File Source Settings") ); + + KTabWidget *page3 = new KTabWidget( this ); + page3->setMargin( KDialog::marginHint() ); + ldconf = + new KABC::LdapConfigWidget( + KABC::LdapConfigWidget::W_USER | + KABC::LdapConfigWidget::W_PASS | + KABC::LdapConfigWidget::W_BINDDN | + KABC::LdapConfigWidget::W_REALM | + KABC::LdapConfigWidget::W_HOST | + KABC::LdapConfigWidget::W_PORT | + KABC::LdapConfigWidget::W_VER | + KABC::LdapConfigWidget::W_DN | + KABC::LdapConfigWidget::W_SECBOX | + KABC::LdapConfigWidget::W_AUTHBOX, + page3 ); + page3->addTab( ldconf, i18n("Connection") ); + + LdapSettings *page3b = new LdapSettings( this ); + page3->addTab( page3b, i18n("Settings") ); + + page3c = new LdapSamba( this ); + connect( page3c->domQuery, SIGNAL(clicked()), SLOT(slotQueryClicked()) ); + page3->addTab( page3c, i18n("Samba") ); + addPage( page3, i18n("LDAP"), "", i18n("LDAP Source Settings") ); +} + +void editDefaults::slotQueryClicked() +{ + KABC::LDAPUrl _url = ldconf->url(); + + mResult.clear(); + mCancelled = true; + mDomain.name = ""; + mDomain.sid = ""; + mDomain.ridbase = 1000; + + QStringList attrs; + QString filter = "(objectClass=sambaDomain)"; + QString dom = page3c->kcfg_samdomain->text(); + if ( !dom.isEmpty() ) filter = "(&(sambaDomainName=" + dom + ")"+filter+")"; + attrs.append("sambaDomainName"); + attrs.append("sambaSID"); + attrs.append("sambaAlgorithmicRidBase"); + _url.setAttributes( attrs ); + _url.setScope( KABC::LDAPUrl::One ); + _url.setExtension( "x-dir", "base" ); + _url.setFilter( filter ); + + kdDebug() << "sendQuery url: " << _url.prettyURL() << endl; + mLdif.startParsing(); + KIO::Job *job = KIO::get( _url, true, false ); +// job->addMetaData("no-auth-prompt","true"); + connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ), + this, SLOT( loadData( KIO::Job*, const QByteArray& ) ) ); + connect( job, SIGNAL( result( KIO::Job* ) ), + this, SLOT( loadResult( KIO::Job* ) ) ); + + mProg = new KProgressDialog( this, 0, i18n("LDAP Query"), _url.prettyURL(), true ); + mProg->progressBar()->setValue( 0 ); + mProg->progressBar()->setTotalSteps( 1 ); + mProg->exec(); + delete mProg; + if ( mCancelled ) { + kdDebug(5700) << "query cancelled!" << endl; + job->kill( true ); + } else { + if ( !mErrorMsg.isEmpty() ) + KMessageBox::error( this, mErrorMsg ); + else { + mDomain = mResult.first(); + if ( !mDomain.name.isEmpty() && !mDomain.sid.isEmpty() ) { + page3c->kcfg_samdomain->setText( mDomain.name ); + page3c->kcfg_samdomsid->setText( mDomain.sid ); + page3c->kcfg_samridbase->setValue( mDomain.ridbase ); + } + } + } + kdDebug() << "domQueryx" << endl; +} + +void editDefaults::loadData( KIO::Job*, const QByteArray& d ) +{ + KABC::LDIF::ParseVal ret; + + if ( d.size() ) { + mLdif.setLDIF( d ); + } else { + mLdif.endLDIF(); + } + do { + ret = mLdif.nextItem(); + switch ( ret ) { + case KABC::LDIF::Item: + if ( mLdif.attr() == "sambaDomainName" ) + mDomain.name = QString::fromUtf8( mLdif.val(), mLdif.val().size() ); + else if ( mLdif.attr() == "sambaSID" ) + mDomain.sid = QString::fromUtf8( mLdif.val(), mLdif.val().size() ); + else if ( mLdif.attr() == "sambaAlgorithmicRidBase" ) + mDomain.ridbase = QString::fromUtf8( mLdif.val(), mLdif.val().size() ).toUInt(); + break; + case KABC::LDIF::EndEntry: + mProg->progressBar()->advance( 1 ); + if ( !mDomain.name.isEmpty() && !mDomain.sid.isEmpty() ) + mResult.push_back( mDomain ); + mDomain.sid = ""; + mDomain.name = ""; + mDomain.ridbase = 1000; + break; + + } + } while ( ret != KABC::LDIF::MoreData ); +} + +void editDefaults::loadResult( KIO::Job* job) +{ + int error = job->error(); + if ( error && error != KIO::ERR_USER_CANCELED ) + mErrorMsg = job->errorString(); + else + mErrorMsg = ""; + + mCancelled = false; + mProg->close(); +} + +#include "editDefaults.moc" diff --git a/kuser/editDefaults.h b/kuser/editDefaults.h new file mode 100644 index 0000000..dbe9dd6 --- /dev/null +++ b/kuser/editDefaults.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_EDITDEFAULTS_H_ +#define _KU_EDITDEFAULTS_H_ + +#include <qmemarray.h> +#include <kconfigdialog.h> +#include <kprogress.h> +#include <kabc/ldif.h> +#include "ldapsamba.h" + +class LdapSamba; +namespace KABC { class LdapConfigWidget; } +namespace KIO { class Job; } + +typedef struct SambaDomain { + QString name; + QString sid; + uint ridbase; +}; + +class editDefaults : public KConfigDialog { + Q_OBJECT +public: + editDefaults( KConfigSkeleton *config, QWidget* parent, const char * name = 0 ); +private: + KProgressDialog *mProg; + LdapSamba *page3c; + KABC::LdapConfigWidget *ldconf; + KABC::LDIF mLdif; + bool mCancelled; + QString mErrorMsg; + QValueList<SambaDomain> mResult; + SambaDomain mDomain; +private slots: + void slotQueryClicked(); + void loadData( KIO::Job*, const QByteArray& d ); + void loadResult( KIO::Job* job); +}; + +#endif // _KU_EDITDEFAULTS_H_ diff --git a/kuser/editGroup.cpp b/kuser/editGroup.cpp new file mode 100644 index 0000000..1ef74d8 --- /dev/null +++ b/kuser/editGroup.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + + +#include <qlabel.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qvalidator.h> +#include <qwhatsthis.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kdebug.h> +#include <kmessagebox.h> + +#include "kglobal_.h" +#include "editGroup.h" + +editGroup::editGroup(KU::KGroup *akg, bool samba, bool add, + QWidget* parent, const char* name) + : KDialogBase(parent, name, true, i18n("Group Properties"), Ok | Cancel, Ok, true) +{ + kg = akg; + mAdd = add; + mSamba = samba; + mOldName = kg->getName(); + SID sid = kg->getSID(); + ro = kug->getGroups().getCaps() & KU::KGroups::Cap_ReadOnly; + + RID rid; + rid.rid = 512; rid.name = i18n("Domain Admins"); rid.desc = i18n("Admins"); mRids.append( rid ); + rid.rid = 513; rid.name = i18n("Domain Users"); rid.desc = i18n("Users"); mRids.append( rid ); + rid.rid = 514; rid.name = i18n("Domain Guests"); rid.desc = i18n("Guests"); mRids.append( rid ); + + QFrame *page = makeMainWidget(); + QGridLayout *layout = new QGridLayout( page, 10, 3, marginHint(), spacingHint() ); + QLabel *lb; + + lb = new QLabel( page ); + lb->setText(i18n("Group number:")); + legid = new KLineEdit(page); + // ensure it fits at least 20 characters + legid->setText( "XXXXXXXXXXXXXXXXXXX" ); + legid->setText( QString::number(kg->getGID()) ); + legid->setValidator( new QIntValidator(this) ); + legid->setEnabled( mAdd ); + legid->setReadOnly( ro ); + lb->setBuddy( legid ); + layout->addWidget( lb, 0, 0 ); + layout->addMultiCellWidget( legid, 0, 0, 1, 2 ); + + if ( mSamba ) { + lb = new QLabel( page ); + lb->setText(i18n("Group rid:")); + lerid = new KComboBox( page ); + lerid->setEditable( !ro ); + QValueList<RID>::Iterator it; + for ( it = mRids.begin(); it != mRids.end(); ++it ) { + lerid->insertItem( QString::number( (*it).rid ) + " - " + (*it).name ); + } + + lerid->setCurrentText( QString::number( sid.getRID() ) ); + lerid->setValidator (new QIntValidator(this) ); + lerid->setEnabled( mAdd ); + connect( lerid, SIGNAL(activated(int)), SLOT(ridSelected(int)) ); + lb->setBuddy( lerid ); + layout->addWidget( lb, 1, 0 ); + layout->addMultiCellWidget( lerid, 1, 1, 1, 2 ); + } + + lb = new QLabel( page ); + lb->setText(i18n("Group name:")); + + legrpname = new KLineEdit( page ); + // ensure it fits at least 20 characters + legrpname->setText( "XXXXXXXXXXXXXXXXXXX" ); + legrpname->setText( kg->getName() ); + legrpname->setReadOnly( ro ); + legrpname->setFocus(); + lb->setBuddy( legrpname ); + layout->addWidget( lb, 2, 0 ); + layout->addMultiCellWidget( legrpname, 2, 2, 1, 2 ); + + if ( mSamba ) { + lb = new QLabel( page ); + lb->setText(i18n("Description:")); + ledesc = new KLineEdit(page); + ledesc->setText( kg->getDesc() ); + ledesc->setReadOnly( ro ); + lb->setBuddy( ledesc ); + layout->addWidget( lb, 3, 0 ); + layout->addMultiCellWidget( ledesc, 3, 3, 1, 2 ); + + lb = new QLabel( page ); + lb->setText(i18n("Display name:")); + ledispname = new KLineEdit(page); + ledispname->setText( kg->getDisplayName() ); + ledispname->setReadOnly( ro ); + lb->setBuddy( ledispname ); + layout->addWidget( lb, 4, 0 ); + layout->addMultiCellWidget( ledispname, 4, 4, 1, 2 ); + + lb = new QLabel( page ); + lb->setText(i18n("Type:")); + letype = new KComboBox( page ); + letype->insertItem( i18n("Domain") ); + letype->insertItem( i18n("Local") ); + letype->insertItem( i18n("Builtin") ); + switch ( kg->getType() ) { + case 2: + letype->setCurrentItem( 0 ); + break; + case 4: + letype->setCurrentItem( 1 ); + break; + case 5: + letype->setCurrentItem( 2 ); + break; + } + lb->setBuddy( letype ); + layout->addWidget( lb, 5, 0 ); + layout->addMultiCellWidget( letype, 5, 5, 1, 2 ); + + lb = new QLabel( page ); + lb->setText(i18n("Domain SID:")); + ledomsid = new KLineEdit(page); + ledomsid->setText( sid.getDOM() ); + ledomsid->setReadOnly( ro ); + lb->setBuddy( ledomsid ); + layout->addWidget( lb, 6, 0 ); + layout->addMultiCellWidget( ledomsid, 6, 6, 1, 2 ); + + cbsamba = new QCheckBox( i18n("Disable Samba group information"), page ); + layout->addMultiCellWidget( cbsamba, 7, 7, 0, 2 ); + connect( cbsamba, SIGNAL(toggled(bool)), ledesc, SLOT(setDisabled(bool)) ); + connect( cbsamba, SIGNAL(toggled(bool)), ledispname, SLOT(setDisabled(bool)) ); + connect( cbsamba, SIGNAL(toggled(bool)), letype, SLOT(setDisabled(bool)) ); + connect( cbsamba, SIGNAL(toggled(bool)), ledomsid, SLOT(setDisabled(bool)) ); + if ( mAdd ) connect( cbsamba, SIGNAL(toggled(bool)), lerid, SLOT(setDisabled(bool)) ); + if ( !mAdd ) cbsamba->setChecked( !( kg->getCaps() & KU::KGroup::Cap_Samba ) ); + } + + m_list_in = new KListView(page); + m_list_in->setFullWidth(true); // Single column, full widget width. + m_list_in->addColumn(i18n("Users in Group")); + m_list_in->setSelectionMode( QListView::Extended ); + layout->addWidget( m_list_in, 8, 0 ); + + QVBox *vbox = new QVBox(page); + QPushButton *btadd = new QPushButton(i18n("Add <-"), vbox); + QPushButton *btdel = new QPushButton(i18n("Remove ->"), vbox); + layout->addWidget( vbox, 8, 1 ); + + m_list_notin = new KListView(page); + m_list_notin->setFullWidth(true); // Single column, full widget width. + m_list_notin->addColumn(i18n("Users NOT in Group")); + m_list_notin->setSelectionMode(QListView::Extended); + layout->addWidget( m_list_notin, 8, 2 ); +// QString whatstr = i18n("Select the users that should be in this kg->"); +// QWhatsThis::add(m_list, whatstr); +// connect(this,SIGNAL(okClicked(void)), + //this,SLOT(okClicked())); + + + for (unsigned int i = 0; i<kug->getUsers().count(); i++) { + KU::KUser *user; + user = kug->getUsers()[i]; + QString userName = user->getName(); + if ( kg->lookup_user(userName) || user->getGID() == kg->getGID() ) { + KListViewItem *item = new KListViewItem(m_list_in, userName); + if ( user->getGID() == kg->getGID() ) item->setSelectable( false ); + } else { + new KListViewItem(m_list_notin, userName); + } + } + + connect(btadd, SIGNAL(clicked()), SLOT(addClicked())); + connect(btdel, SIGNAL(clicked()), SLOT(delClicked())); + + if ( ro ) { + btadd->setEnabled( false ); + btdel->setEnabled( false ); + } +} + +editGroup::~editGroup() +{ +} + +void editGroup::ridSelected( int index ) +{ + lerid->setCurrentText( QString::number( mRids[ index ].rid ) ); + legrpname->setText( mRids[ index ].name ); + ledesc->setText( mRids[ index ].desc ); + ledispname->setText( mRids[ index ].name ); +} + +void editGroup::addClicked() +{ + QListViewItem *item, *next; + QString name; + + item = m_list_notin->firstChild(); + while ( item ) { + next = item->nextSibling(); + if ( item->isSelected() ) { + name = item->text( 0 ); + delete item; + item = new KListViewItem( m_list_in, name ); + } + item = next; + } +} + +void editGroup::delClicked() +{ + QListViewItem *item, *next; + QString name; + + item = m_list_in->firstChild(); + while ( item ) { + next = item->nextSibling(); + if ( item->isSelected() ) { + name = item->text( 0 ); + delete item; + item = new KListViewItem( m_list_notin, name ); + } + item = next; + } +} + +void editGroup::slotOk() +{ + if ( ro ) { + reject(); + return; + } + + SID sid; + kg->clear(); + QString s; + s = legid->text(); + + if ( mSamba && !cbsamba->isChecked() ) { + sid.setDOM( ledomsid->text() ); + sid.setRID( lerid->currentText() ); + } + + if ( legrpname->text().isEmpty() ) { + KMessageBox::sorry( 0, + i18n("You need to type a group name.") ); + return; + } + + if ( legrpname->text() != mOldName && + kug->getGroups().lookup( legrpname->text() ) ) { + + KMessageBox::sorry( 0, + i18n("Group with name %1 already exists.").arg(legrpname->text()) ); + return; + } + + if ( mAdd ) { + if ( mSamba && !cbsamba->isChecked() && kug->getGroups().lookup_sam( sid ) ) { + KMessageBox::sorry( 0, + i18n("Group with SID %1 already exists.").arg( sid.getSID() ) ); + return; + } + if (kug->getGroups().lookup(s.toInt())) { + KMessageBox::sorry( 0, + i18n("Group with gid %1 already exists.").arg(s.toInt()) ); + return; + } + } + + kg->setName(legrpname->text()); + kg->setGID(s.toInt()); + if ( mSamba && !cbsamba->isChecked() ) { + kg->setCaps ( KU::KGroup::Cap_Samba ); + kg->setSID( sid ); + switch ( letype->currentItem() ) { + case 0: + kg->setType( 2 ); + break; + case 1: + kg->setType( 4 ); + break; + case 2: + kg->setType( 5 ); + break; + } + kg->setDesc( ledesc->text() ); + kg->setDisplayName( ledispname->text() ); + } else { + kg->setCaps( 0 ); + kg->setSID( QString::null ); + kg->setDesc( QString::null ); + kg->setDisplayName( QString::null ); + kg->setType( 0 ); + } + + QListViewItem *item; + item = m_list_in->firstChild(); + while ( item ) { + kg->addUser( item->text( 0 ) ); + item = item->nextSibling(); + } + accept(); +} + +#include "editGroup.moc" diff --git a/kuser/editGroup.h b/kuser/editGroup.h new file mode 100644 index 0000000..3d6334b --- /dev/null +++ b/kuser/editGroup.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + + +#ifndef _KU_EDITGROUP_H_ +#define _KU_EDITGROUP_H_ + +#include <qcheckbox.h> +#include <kdialogbase.h> +#include <klistview.h> +#include <kcombobox.h> +#include <klineedit.h> + +#include "kgroup.h" + +class editGroup : public KDialogBase +{ + Q_OBJECT +public: + + editGroup(KU::KGroup *akg, bool samba, bool add, + QWidget* parent = NULL, const char* name = NULL); + + virtual ~editGroup(); + +protected slots: + virtual void slotOk(); + void addClicked(); + void delClicked(); + void ridSelected( int index ); + +private: + bool mSamba, mAdd; + bool ro; + KU::KGroup *kg; + KListView *m_list_in,*m_list_notin; + KLineEdit *legrpname; + KLineEdit *legid; + KComboBox *lerid; + KLineEdit *ledom; + KLineEdit *ledispname; + KLineEdit *ledesc; + KLineEdit *ledomsid; + KComboBox *letype; + QCheckBox *cbsamba; + QString mOldName; + typedef struct _RID { + uint rid; + QString name,desc; + } RID; + QValueList<RID> mRids; +}; +#endif // _KU_EDITGROUP_H_ diff --git a/kuser/filessettings.ui b/kuser/filessettings.ui new file mode 100644 index 0000000..078578d --- /dev/null +++ b/kuser/filessettings.ui @@ -0,0 +1,225 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>FilesSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>FilesSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>405</width> + <height>315</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Local User Database Files</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Group file:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_groupsrc</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Password file:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_passwdsrc</cstring> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_passwdsrc</cstring> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>kcfg_groupsrc</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Shadow password file:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_shadowsrc</cstring> + </property> + </widget> + <widget class="KLineEdit" row="2" column="2"> + <property name="name"> + <cstring>kcfg_shadowsrc</cstring> + </property> + </widget> + <widget class="KLineEdit" row="3" column="2"> + <property name="name"> + <cstring>kcfg_gshadowsrc</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>Shadow group file:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_gshadowsrc</cstring> + </property> + </widget> + <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_md5shadow</cstring> + </property> + <property name="text"> + <string>MD5 shadow passwords</string> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>NIS Settings</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="text"> + <string>NIS password source:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_nispasswdsrc</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel4_2</cstring> + </property> + <property name="text"> + <string>NIS group source:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_nisgroupsrc</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel5_2</cstring> + </property> + <property name="text"> + <string>NIS minimum UID:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_nisminuid</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel6_2</cstring> + </property> + <property name="text"> + <string>NIS minimum GID:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_nismingid</cstring> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_nispasswdsrc</cstring> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_nisgroupsrc</cstring> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>kcfg_nisminuid</cstring> + </property> + </widget> + <widget class="KLineEdit" row="3" column="1"> + <property name="name"> + <cstring>kcfg_nismingid</cstring> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kuser/generalsettings.ui b/kuser/generalsettings.ui new file mode 100644 index 0000000..d486db7 --- /dev/null +++ b/kuser/generalsettings.ui @@ -0,0 +1,240 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>GeneralSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>GeneralSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>311</width> + <height>237</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Source of user/group database:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_source</cstring> + </property> + </widget> + <widget class="KComboBox"> + <item> + <property name="text"> + <string>Files</string> + </property> + </item> + <item> + <property name="text"> + <string>LDAP</string> + </property> + </item> + <item> + <property name="text"> + <string>System</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_source</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_homepath</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>First normal GID:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_firstGID</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Home path template:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_homepath</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Shell:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_shell</cstring> + </property> + </widget> + <widget class="KComboBox" row="0" column="1"> + <property name="name"> + <cstring>kcfg_shell</cstring> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1_3_2</cstring> + </property> + <property name="text"> + <string>First normal UID:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_firstUID</cstring> + </property> + </widget> + <widget class="KLineEdit" row="3" column="1"> + <property name="name"> + <cstring>kcfg_firstGID</cstring> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>kcfg_firstUID</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_createHomeDir</cstring> + </property> + <property name="text"> + <string>Create home folder</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_copySkel</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Copy skeleton to home folder</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_userPrivateGroup</cstring> + </property> + <property name="text"> + <string>User private groups</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>Default group:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_defaultgroup</cstring> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>kcfg_defaultgroup</cstring> + </property> + <property name="maxValue"> + <number>65536</number> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>kcfg_userPrivateGroup</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_defaultgroup</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_createHomeDir</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_copySkel</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_source</tabstop> + <tabstop>kcfg_shell</tabstop> + <tabstop>kcfg_homepath</tabstop> + <tabstop>kcfg_firstUID</tabstop> + <tabstop>kcfg_firstGID</tabstop> + <tabstop>kcfg_createHomeDir</tabstop> + <tabstop>kcfg_copySkel</tabstop> + <tabstop>kcfg_userPrivateGroup</tabstop> +</tabstops> +<slots> + <slot>kcfg_createHomeDir_toggled( bool )</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kuser/globals.h b/kuser/globals.h new file mode 100644 index 0000000..dde58a5 --- /dev/null +++ b/kuser/globals.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GLOBALS_H_ +#define _KU_GLOBALS_H_ + +#define _KU_VERSION "2.1" + +#include <config.h> +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif +#include <kconfig.h> +#include "kuserprefs.h" + +#define KU_BACKUP_EXT ".bak" +#define KU_CREATE_EXT ".new" + +#ifdef HAVE_PATHS_H + #define SHELL_FILE _PATH_SHELLS + #define MAIL_SPOOL_DIR _PATH_MAILDIR +#else + #define SHELL_FILE "/etc/shells" + #define MAIL_SPOOL_DIR "/var/spool/mail" +#endif + +#if defined(__FreeBSD__) || defined(__bsdi__) + #undef HAVE_SHADOW + #include <pwd.h> + #define PASSWORD_FILE _PATH_MASTERPASSWD + #define PASSWORD_FILE_MASK S_IRUSR | S_IWUSR + #define PWMKDB _PATH_PWD_MKDB" -p "PASSWORD_FILE + #define SKELDIR "/usr/share/skel" + #define SKEL_FILE_PREFIX "dot" + #define CRONTAB_DIR "/var/cron/tabs" +#else + #define PASSWORD_FILE "/etc/passwd" + #define PASSWORD_FILE_MASK S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH + #define PWMKDB "cd /var/yp; make 2>&1 >> /var/log/kuser" + #define GRMKDB "cd /var/yp; make 2>&1 >> /var/log/kuser" + #define SKELDIR "/etc/skel" + #define SKEL_FILE_PREFIX "" + #define CRONTAB_DIR "/var/spool/cron" +#endif + +#define GROUP_FILE "/etc/group" +#define GROUP_FILE_MASK S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH + +#endif // _KU_GLOBALS_H_ diff --git a/kuser/icon/Makefile.am b/kuser/icon/Makefile.am new file mode 100644 index 0000000..9f07108 --- /dev/null +++ b/kuser/icon/Makefile.am @@ -0,0 +1,3 @@ + +KDE_ICON = kuser + diff --git a/kuser/icon/hi128-app-kuser.png b/kuser/icon/hi128-app-kuser.png Binary files differnew file mode 100644 index 0000000..f28f704 --- /dev/null +++ b/kuser/icon/hi128-app-kuser.png diff --git a/kuser/icon/hi16-app-kuser.png b/kuser/icon/hi16-app-kuser.png Binary files differnew file mode 100644 index 0000000..8f69e2b --- /dev/null +++ b/kuser/icon/hi16-app-kuser.png diff --git a/kuser/icon/hi22-app-kuser.png b/kuser/icon/hi22-app-kuser.png Binary files differnew file mode 100644 index 0000000..396b19a --- /dev/null +++ b/kuser/icon/hi22-app-kuser.png diff --git a/kuser/icon/hi32-app-kuser.png b/kuser/icon/hi32-app-kuser.png Binary files differnew file mode 100644 index 0000000..a5cbf22 --- /dev/null +++ b/kuser/icon/hi32-app-kuser.png diff --git a/kuser/icon/hi48-app-kuser.png b/kuser/icon/hi48-app-kuser.png Binary files differnew file mode 100644 index 0000000..d8b241c --- /dev/null +++ b/kuser/icon/hi48-app-kuser.png diff --git a/kuser/icon/hi64-app-kuser.png b/kuser/icon/hi64-app-kuser.png Binary files differnew file mode 100644 index 0000000..57c5726 --- /dev/null +++ b/kuser/icon/hi64-app-kuser.png diff --git a/kuser/kglobal.cpp b/kuser/kglobal.cpp new file mode 100644 index 0000000..93a7cce --- /dev/null +++ b/kuser/kglobal.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <kapplication.h> + +#include "kglobal_.h" +#include "kuserfiles.h" +#include "kgroupfiles.h" +#include "kuserldap.h" +#include "kgroupldap.h" +#include "kusersystem.h" +#include "kgroupsystem.h" + +KUserGlobals::KUserGlobals() +{ + cfg = 0; + + users = 0; + groups = 0; +} + +void KUserGlobals::initCfg( const QString &connection ) +{ + if ( cfg ) { + cfg->writeConfig(); + delete cfg; + } + cfg = new KUserPrefsBase( kapp->sharedConfig(), connection ); + cfg->readConfig(); +} + +void KUserGlobals::init() +{ + if ( users ) delete users; + if ( groups ) delete groups; + SID::setAlgRidBase( cfg->samridbase() ); + kdDebug() << "Algorithmic RID base: " << SID::getAlgRidBase() << endl; + switch ( cfg->source() ) { + case KUserPrefsBase::EnumSource::Files: + users = new KUserFiles( cfg ); + groups = new KGroupFiles( cfg ); + break; + case KUserPrefsBase::EnumSource::LDAP: + users = new KUserLDAP( cfg ); + groups = new KGroupLDAP( cfg ); + break; + case KUserPrefsBase::EnumSource::System: + users = new KUserSystem( cfg ); + groups = new KGroupSystem( cfg ); + break; + } +} + +KUserGlobals::~KUserGlobals() +{ + delete users; + delete groups; + delete cfg; +} + +KU::KUsers &KUserGlobals::getUsers() +{ + return (*users); +} + +KU::KGroups &KUserGlobals::getGroups() +{ + return (*groups); +} diff --git a/kuser/kglobal_.h b/kuser/kglobal_.h new file mode 100644 index 0000000..2cf8dbe --- /dev/null +++ b/kuser/kglobal_.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GLOBAL_H_ +#define _KU_GLOBAL_H_ + +#include "kuser.h" +#include "kgroup.h" + +class KUserGlobals { +public: + KUserGlobals(); + ~KUserGlobals(); + void init(); + void initCfg( const QString &connection ); + + KUserPrefsBase *kcfg() { return cfg; } + KU::KUsers &getUsers(); + KU::KGroups &getGroups(); + +private: + + KU::KUsers *users; + KU::KGroups *groups; + + KUserPrefsBase *cfg; +}; + +extern KUserGlobals *kug; + +#endif //_KU_GLOBAL_H_ diff --git a/kuser/kgroup.cpp b/kuser/kgroup.cpp new file mode 100644 index 0000000..44fc31c --- /dev/null +++ b/kuser/kgroup.cpp @@ -0,0 +1,328 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qstring.h> + +#include <kdebug.h> + +#include "kglobal_.h" +#include "kgroup.h" +#include "misc.h" + +KU::KGroup::KGroup() +{ + pwd = QString::fromLatin1("*"); + gid = 0; + type = 2; + caps = 0; +} + +KU::KGroup::KGroup(KU::KGroup *group) +{ + copy( group ); +} + +KU::KGroup::~KGroup() +{ +} + +void KU::KGroup::copy( const KU::KGroup *group ) +{ + if ( group != this ) { + caps = group->caps; + name = group->name; + pwd = group->pwd; + gid = group->gid; + sid = group->sid; + type = group->type; + displayname = group->displayname; + desc = group->desc; + u = group->u; + } +} + +void KU::KGroup::setCaps( int data ) +{ + caps = data; +} + +int KU::KGroup::getCaps() +{ + return caps; +} + +const QString &KU::KGroup::getName() const +{ + return name; +} + +const QString &KU::KGroup::getPwd() const +{ + return pwd; +} + +gid_t KU::KGroup::getGID() const +{ + return gid; +} + +const SID &KU::KGroup::getSID() const +{ + return sid; +} + +int KU::KGroup::getType() const +{ + return type; +} + +const QString &KU::KGroup::getDisplayName() const +{ + return displayname; +} + +const QString &KU::KGroup::getDesc() const +{ + return desc; +} + +void KU::KGroup::setName(const QString &data) +{ + name = data; +} + +void KU::KGroup::setPwd(const QString &data) +{ + pwd = data; +} + +void KU::KGroup::setGID(gid_t data) +{ + gid = data; +} + +void KU::KGroup::setSID(const SID &data) +{ + sid = data; +} + +void KU::KGroup::setType(int data) +{ + type = data; +} + +void KU::KGroup::setDisplayName(const QString &data) +{ + displayname = data; +} + +void KU::KGroup::setDesc(const QString &data) +{ + desc = data; +} + +bool KU::KGroup::lookup_user(const QString &name) +{ + return (u.find(name) != u.end()); +} + +bool KU::KGroup::addUser(const QString &name) +{ + if (!lookup_user(name)) { + u.append(name); + return true; + } else + return false; +} + +bool KU::KGroup::removeUser(const QString &name) +{ + return ( u.remove(name) > 0 ); +} + +uint KU::KGroup::count() const +{ + return u.count(); +} + +QString KU::KGroup::user(uint i) +{ + return u[i]; +} + +void KU::KGroup::clear() +{ + u.clear(); +} + +KU::KGroups::KGroups(KUserPrefsBase *cfg) +{ + mGroups.setAutoDelete(TRUE); + mCfg = cfg; +} + +KU::KGroup *KU::KGroups::lookup(const QString &name) +{ + KU::KGroup *group; + QPtrListIterator<KU::KGroup> it( mGroups ); + + while ( (group = it.current()) != 0 && group->getName() != name ) ++it; + return group; +} + +KU::KGroup *KU::KGroups::lookup(gid_t gid) +{ + KU::KGroup *group; + QPtrListIterator<KU::KGroup> it( mGroups ); + + while ( (group = it.current()) != 0 && group->getGID() != gid ) ++it; + return group; +} + +KU::KGroup *KU::KGroups::lookup_sam( const SID &sid ) +{ + KU::KGroup *group; + QPtrListIterator<KU::KGroup> it( mGroups ); + + while ( (group = it.current()) != 0 && group->getSID() != sid ) ++it; + return group; +} + +KU::KGroup *KU::KGroups::lookup_sam( const QString &sid ) +{ + KU::KGroup *group; + QPtrListIterator<KU::KGroup> it( mGroups ); + + while ( (group = it.current()) != 0 && group->getSID().getSID() != sid ) ++it; + return group; +} + +KU::KGroup *KU::KGroups::lookup_sam( uint rid ) +{ + KU::KGroup *group; + QPtrListIterator<KU::KGroup> it( mGroups ); + + while ( (group = it.current()) != 0 && group->getSID().getRID() != rid ) ++it; + return group; +} + +gid_t KU::KGroups::first_free() +{ + gid_t t; + + for (t = mCfg->firstGID(); t<65534; t++) + if (lookup(t) == NULL) + return t; + + return NO_FREE; +} + +uint KU::KGroups::first_free_sam() +{ + uint t; + + for (t = 30000; t<65534; t++) + if (lookup_sam(t) == NULL) + return t; + + return 0; +} + +KU::KGroups::~KGroups() +{ + mGroups.clear(); +} + +KU::KGroup *KU::KGroups::operator[](uint num) +{ + return mGroups.at(num); +} + +KU::KGroup *KU::KGroups::first() +{ + return mGroups.first(); +} + +KU::KGroup *KU::KGroups::next() +{ + return mGroups.next(); +} + +uint KU::KGroups::count() const +{ + return mGroups.count(); +} + +const QString &KU::KGroups::getDOMSID() const +{ + return domsid; +} + +void KU::KGroups::add(KU::KGroup *group) +{ + kdDebug() << "adding group: " << group->getName() << " gid: " << group->getGID() << endl; + mAdd.append( group ); +} + +void KU::KGroups::del(KU::KGroup *group) +{ + kdDebug() << "deleting group: " << group->getName() << " gid: " << group->getGID() << endl; + mDel.append( group ); +} + +void KU::KGroups::mod(KU::KGroup *gold, const KU::KGroup &gnew) +{ + kdDebug() << "modify group " << gnew.getName() << " gid: " << gnew.getGID() << endl; + mMod.insert( gold, gnew ); +} + +void KU::KGroups::commit() +{ + kdDebug() << "KU::KGroups::commit()" << endl; + KU::KGroup *group; + DelIt dit( mDelSucc ); + AddIt ait( mAddSucc ); + ModIt mit = mModSucc.begin(); + + while ( mit != mModSucc.end() ) { + *(mit.key()) = mit.data(); + mit++; + } + while ( (group = dit.current()) != 0 ) { + ++dit; + mGroups.remove( group ); + } + while ( (group = ait.current()) != 0 ) { + ++ait; + mGroups.append( group ); + } + cancelMods(); +} + +void KU::KGroups::cancelMods() +{ + KU::KGroup *group; + while ( (group = mAdd.first()) ) { + delete group; + mAdd.remove(); + } + mDel.clear(); + mMod.clear(); +} diff --git a/kuser/kgroup.h b/kuser/kgroup.h new file mode 100644 index 0000000..c91f496 --- /dev/null +++ b/kuser/kgroup.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GROUP_H_ +#define _KU_GROUP_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qptrlist.h> + +#include "kuserprefs.h" +#include "sid.h" + +namespace KU { + +class KGroup { +public: + KGroup(); + KGroup(KGroup *group); + ~KGroup(); + + enum Cap { + Cap_Samba = 1 + }; + + void copy(const KGroup *group); + void setCaps( int data ); + int getCaps(); + + const QString &getName() const; + const QString &getPwd() const; + gid_t getGID() const; + const SID &getSID() const; + int getType() const; + const QString &getDisplayName() const; + const QString &getDesc() const; + + void setName(const QString &data); + void setPwd(const QString &data); + void setGID(gid_t data); + void setSID(const SID &data); + void setType(int data); + void setDisplayName(const QString &data); + void setDesc(const QString &data); + + bool addUser(const QString &name); + bool removeUser(const QString &name); + bool lookup_user(const QString &name); + uint count() const; + QString user(uint i); + void clear(); + +protected: + QString + name, + pwd; + gid_t gid; + +//samba attributes + SID sid; + int type; + int caps; + QString displayname; + QString desc; + + QStringList u; +}; + +class KGroups { +public: + enum Cap { + Cap_ReadOnly = 1, + Cap_Passwd = 2, + Cap_Shadow = 4, + Cap_Samba = 8 + }; + + typedef QPtrListIterator<KGroup> DelIt; + typedef QPtrListIterator<KGroup> AddIt; + typedef QMapIterator<KGroup*, KGroup> ModIt; + + QPtrList<KGroup> mDelSucc; + QPtrList<KGroup> mAddSucc; + QMap<KGroup*, KGroup> mModSucc; + + KGroups( KUserPrefsBase *cfg ); + virtual ~KGroups(); + + int getCaps() const { return caps; } + const QString &getDOMSID() const; + + KGroup *lookup( const QString &name ); + KGroup *lookup( gid_t gid ); + KGroup *lookup_sam( const SID &sid ); + KGroup *lookup_sam( const QString &sid ); + KGroup *lookup_sam( uint rid ); + + KGroup *first(); + KGroup *next(); + KGroup *operator[](uint num); + uint count() const; + + void add(KGroup *group); + void del(KGroup *group); + void mod(KGroup *gold, const KGroup &gnew); + void commit(); + void cancelMods(); + + enum { + NO_FREE = (gid_t) -1 + }; + + virtual gid_t first_free(); + virtual uint first_free_sam(); + virtual bool reload() = 0; + virtual bool dbcommit() = 0; + +protected: + KUserPrefsBase *mCfg; + QPtrList<KGroup> mGroups; + + QPtrList<KGroup> mDel; + QPtrList<KGroup> mAdd; + QMap<KGroup*, KGroup> mMod; + int caps; + QString domsid; +}; + +} + +#endif // _KU_GROUP_H_ diff --git a/kuser/kgroupfiles.cpp b/kuser/kgroupfiles.cpp new file mode 100644 index 0000000..bab8841 --- /dev/null +++ b/kuser/kgroupfiles.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "globals.h" +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <grp.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <qstring.h> +#include <qdir.h> + +#include <kdebug.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> + +#include "kglobal_.h" +#include "kgroupfiles.h" +#include "misc.h" +#include "editDefaults.h" + +KGroupFiles::KGroupFiles( KUserPrefsBase *cfg ) : KGroups( cfg ) +{ + gs_backuped = FALSE; + gr_backuped = FALSE; + gn_backuped = FALSE; + + smode = 0400; + mode = 0644; + uid = 0; + gid = 0; + + caps = Cap_Passwd; + + reload(); +} + +KGroupFiles::~KGroupFiles() +{ + mGroups.clear(); +} + +bool KGroupFiles::reload() +{ + struct group *p; + KU::KGroup *tmpKG = 0; + struct stat st; + QString filename; + QString group_filename; + QString nisgroup_filename; + int rc = 0; + int group_errno = 0; + int nisgroup_errno = 0; + char processing_file = '\0'; + #define GROUP 0x01 + #define NISGROUP 0x02 + #define MAXFILES 2 + + // Prepare to read KUser configuration + + group_filename = mCfg->groupsrc(); + nisgroup_filename = mCfg->nisgroupsrc(); + if(!group_filename.isEmpty()) { + processing_file = processing_file | GROUP; + filename.append(group_filename); + } + + // Start reading group file(s) + + for(int k = 0; k < MAXFILES; k++) { + rc = stat(QFile::encodeName(filename), &st); + if(rc != 0) { + KMessageBox::error( 0, i18n("stat call on file %1 failed: %2\nCheck KUser settings."). + arg(filename).arg(QString::fromLatin1(strerror(errno))) ); + if( (processing_file & GROUP) != 0 ) { + group_errno = errno; + if(!nisgroup_filename.isEmpty()) { + processing_file = processing_file & ~GROUP; + processing_file = processing_file | NISGROUP; + filename.truncate(0); + filename.append(nisgroup_filename); + } + continue; + } + else{ + nisgroup_errno = errno; + break; + } + } + + mode = st.st_mode; + uid = st.st_uid; + gid = st.st_gid; + + // We are reading our configuration specified group file +#ifdef HAVE_FGETGRENT + FILE *fgrp = fopen(QFile::encodeName(filename), "r"); + QString tmp; + if (fgrp == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(filename) ); + return FALSE; + } + + while ((p = fgetgrent(fgrp)) != NULL) { +#else + setgrent(); + while ((p = getgrent()) != NULL) { +#endif + tmpKG = new KU::KGroup(); + tmpKG->setGID(p->gr_gid); + tmpKG->setName(QString::fromLocal8Bit(p->gr_name)); + tmpKG->setPwd(QString::fromLocal8Bit(p->gr_passwd)); + + char *u_name; + int i = 0; + while ((u_name = p->gr_mem[i])!=0) { + tmpKG->addUser(QString::fromLocal8Bit(u_name)); + i++; + } + + mGroups.append(tmpKG); + } + + // End reading filename + +#ifdef HAVE_FGETGRENT + fclose(fgrp); +#else + endgrent(); +#endif + if(!nisgroup_filename.isEmpty()) { + if(nisgroup_filename == group_filename) + break; + processing_file = processing_file & ~GROUP; + processing_file = processing_file | NISGROUP; + filename.truncate(0); + filename.append(nisgroup_filename); + } + else + break; + + } // end of processing files, for loop + + if( (group_errno == 0) && (nisgroup_errno == 0) ) + return(TRUE); + if( (group_errno != 0) && (nisgroup_errno != 0) ) + return(FALSE); + else + return(TRUE); +} + +bool KGroupFiles::save() +{ + kdDebug() << "KGroupFiles::save() " << endl; + FILE *group_fd = NULL; + FILE *gshadow_fd = NULL; + FILE *nisgroup_fd = NULL; + gid_t mingid = 0; + int nis_groups_written = 0; + gid_t tmp_gid = 0; + QString tmpGe, tmpSe, tmp2; + QString group_filename, new_group_filename; + QString gshadow_filename, new_gshadow_filename; + QString nisgroup_filename, new_nisgroup_filename; + + char errors_found = '\0'; + #define NOMINGID 0x01 + #define NONISGROUP 0x02 + + // read KUser configuration info + + group_filename = mCfg->groupsrc(); + new_group_filename = group_filename + QString::fromLatin1(KU_CREATE_EXT); +#ifdef HAVE_SHADOW + gshadow_filename = mCfg->gshadowsrc(); + if ( !KStandardDirs::exists( gshadow_filename ) ) + gshadow_filename = QString::null; + else + new_gshadow_filename = gshadow_filename + QString::fromLatin1(KU_CREATE_EXT); +#endif + nisgroup_filename = mCfg->nisgroupsrc(); + new_nisgroup_filename = nisgroup_filename + QString::fromLatin1(KU_CREATE_EXT); + if( nisgroup_filename != group_filename ) { + mingid = mCfg->nismingid(); + } + + // Backup file(s) + + if(!group_filename.isEmpty()) { + if (!gr_backuped) { + if ( !backup(group_filename) ) return false; + gr_backuped = TRUE; + } + } + if(!gshadow_filename.isEmpty()) { + if (!gs_backuped) { + if ( !backup(gshadow_filename) ) return false; + gs_backuped = TRUE; + } + } + if(!nisgroup_filename.isEmpty() && (nisgroup_filename != group_filename)) { + if (!gn_backuped) { + if ( !backup(nisgroup_filename) ) return false; + gn_backuped = TRUE; + } + } + + // Open file(s) + + if(!group_filename.isEmpty()) { + if((group_fd = fopen(QFile::encodeName(new_group_filename), "w")) == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_group_filename) ); + return false; + } + } + + if(!gshadow_filename.isEmpty()) { + if((gshadow_fd = fopen(QFile::encodeName(new_gshadow_filename), "w")) == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_gshadow_filename) ); + if ( group_fd ) fclose ( group_fd ); + return false; + } + } + + if(!nisgroup_filename.isEmpty() && (nisgroup_filename != group_filename)) { + if((nisgroup_fd = fopen(QFile::encodeName(new_nisgroup_filename), "w")) == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_nisgroup_filename) ); + if ( group_fd ) fclose ( group_fd ); + if ( gshadow_fd ) fclose ( gshadow_fd ); + return false; + } + } + + QPtrListIterator<KU::KGroup> it( mGroups ); + KU::KGroup *gr; + bool addok = false; + + gr = (*it); + + while (true) { + + if ( gr == 0 ) { + if ( addok ) break; + it = QPtrListIterator<KU::KGroup> ( mAdd ); + gr = (*it); + addok = true; + if ( gr == 0 ) break; + }; + + if ( mDel.containsRef( gr ) ) { + ++it; + gr = (*it); + continue; + } + if ( mMod.contains( gr ) ) gr = &( mMod[ gr ] ); + +#ifdef HAVE_SHADOW + if ( addok && !mCfg->gshadowsrc().isEmpty() ) + gr->setPwd("x"); +#endif + + tmpGe = gr->getName(); + tmpGe.replace( ',', "_" ); + tmpGe.replace( ':', "_" ); + gr->setName( tmpGe ); + + tmp_gid = gr->getGID(); + tmpGe += ":" + + gr->getPwd() + ":" + + QString::number( gr->getGID() ) + ":"; + tmpSe = gr->getName() + ":!::"; + for (uint j=0; j<gr->count(); j++) { + if (j != 0) { + tmpGe += ','; + tmpSe += ','; + } + gr->user( j ).replace( ',', "_" ); + gr->user( j ).replace( ':', "_" ); + tmpGe += gr->user( j) ; + tmpSe += gr->user( j ); + } + tmpGe += '\n'; tmpSe += '\n'; + + if( (nisgroup_fd != 0) && (mingid != 0) ) { + if(mingid <= tmp_gid) { + fputs(tmpGe.local8Bit(), nisgroup_fd); + nis_groups_written++; + ++it; + gr = (*it); + continue; + } + } + + if( (nisgroup_fd != 0) && (mingid == 0) ) { + errors_found = errors_found | NOMINGID; + } + + if( (nisgroup_fd == 0) && (mingid != 0) ) { + errors_found = errors_found | NONISGROUP; + } + + fputs( tmpGe.local8Bit(), group_fd ); + if ( gshadow_fd ) fputs( tmpSe.local8Bit(), gshadow_fd ); + ++it; + gr = (*it); + } + + if(group_fd) { + fclose(group_fd); + chmod(QFile::encodeName(new_group_filename), mode); + chown(QFile::encodeName(new_group_filename), uid, gid); + rename(QFile::encodeName(new_group_filename), + QFile::encodeName(group_filename)); + } + + if(gshadow_fd) { + fclose(gshadow_fd); + chmod(QFile::encodeName(new_gshadow_filename), mode); + chown(QFile::encodeName(new_gshadow_filename), uid, gid); + rename(QFile::encodeName(new_gshadow_filename), + QFile::encodeName(gshadow_filename)); + } + + if(nisgroup_fd) { + fclose(nisgroup_fd); + chmod(QFile::encodeName(nisgroup_filename), mode); + chown(QFile::encodeName(nisgroup_filename), uid, gid); + rename(QFile::encodeName(new_nisgroup_filename), + QFile::encodeName(nisgroup_filename)); + } + + if( (errors_found & NOMINGID) != 0 ) { + KMessageBox::error( 0, i18n("Unable to process NIS group file without a minimum GID specified.\nPlease update KUser settings (File Source Settings).") ); + } + + if( (errors_found & NONISGROUP) != 0 ) { + KMessageBox::error( 0, i18n("Specifying NIS minimum GID requires NIS file(s).\nPlease update KUser settings (File Source Settings).") ); + } + +#ifdef GRMKDB + if( (nis_groups_written > 0) || (nisgroup_filename == group_filename) ) { + if (system(GRMKDB) != 0) { + KMessageBox::error( 0, i18n("Unable to build NIS group databases.") ); + return FALSE; + } + } +#endif + + return TRUE; +} + +bool KGroupFiles::dbcommit() +{ + bool ret; + mode_t mode; + + kdDebug() << "KGroupFiles dbcommit" << endl; + mAddSucc.clear(); + mDelSucc.clear(); + mModSucc.clear(); + if ( mDel.isEmpty() && mAdd.isEmpty() && mMod.isEmpty() ) + return true; + + mode = umask(0077); + ret = save(); + umask( mode ); + if ( !ret ) return false; + + mDelSucc = mDel; + mAddSucc = mAdd; + mModSucc = mMod; + mDel.clear(); + mAdd.clear(); + mMod.clear(); + + return true; +} + diff --git a/kuser/kgroupfiles.h b/kuser/kgroupfiles.h new file mode 100644 index 0000000..b2725bc --- /dev/null +++ b/kuser/kgroupfiles.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GROUPFILES_H_ +#define _KU_GROUPFILES_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qptrlist.h> + +#include "kgroup.h" + +class KGroupFiles : public KU::KGroups { +public: + KGroupFiles( KUserPrefsBase *cfg ); + virtual ~KGroupFiles(); + + virtual bool reload(); + virtual bool dbcommit(); + +private: + int gr_backuped; + int gn_backuped; + int gs_backuped; + + int mode, smode; + uid_t uid; + gid_t gid; + + bool save(); +}; + +#endif // _KU_GROUPFILES_H_ + diff --git a/kuser/kgroupldap.cpp b/kuser/kgroupldap.cpp new file mode 100644 index 0000000..1a84148 --- /dev/null +++ b/kuser/kgroupldap.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qstring.h> +#include <qdir.h> + +#include <kdebug.h> +#include <kmessagebox.h> + +#include "kglobal_.h" +#include "kgroupldap.h" +#include "misc.h" +#include "editDefaults.h" + +#include "kgroupldap.moc" + +KGroupLDAP::KGroupLDAP( KUserPrefsBase *cfg ) : KU::KGroups( cfg ) +{ + mGroups.setAutoDelete(TRUE); + + if ( mCfg->ldapssl() ) + mUrl.setProtocol("ldaps"); + else + mUrl.setProtocol("ldap"); + + mUrl.setHost( mCfg->ldaphost() ); + mUrl.setPort( mCfg->ldapport() ); + mUrl.setDn( mCfg->ldapgroupbase() + "," + mCfg->ldapdn() ); + if ( !mCfg->ldapanon() ) { + mUrl.setUser( mCfg->ldapuser() ); + mUrl.setPass( mCfg->ldappassword() ); + } + mUrl.setFilter( mCfg->ldapgroupfilter() ); + + if ( mCfg->ldaptls() ) mUrl.setExtension("x-tls",""); + if ( mCfg->ldapsasl() ) { + mUrl.setExtension( "x-sasl", "" ); + mUrl.setExtension( "x-mech", mCfg->ldapsaslmech() ); + } + + mUrl.setScope(KABC::LDAPUrl::One); + mUrl.setExtension("x-dir","base"); + + caps = Cap_Passwd; + if ( mCfg->ldapsam() ) { + caps |= Cap_Samba; + domsid = mCfg->samdomsid(); + } + + reload(); +} + +KGroupLDAP::~KGroupLDAP() +{ + mGroups.clear(); +} + +QString KGroupLDAP::getRDN( KU::KGroup *group ) +{ + switch ( mCfg->ldapgrouprdn() ) { + case KUserPrefsBase::EnumLdapgrouprdn::cn: + return "cn=" + group->getName(); + case KUserPrefsBase::EnumLdapgrouprdn::gidNumber: + return "gidNumber=" + QString::number( group->getGID() ); + default: + return ""; + } +} + +void KGroupLDAP::result( KIO::Job *job ) +{ + delete mProg; + mCancel = false; + if ( job->error() ) { + QString errstr = job->errorString(); + if ( !errstr.isEmpty() ) { + if ( ldif.isEmpty() ) + KMessageBox::error( 0, errstr ); + else + KMessageBox::detailedError( 0, errstr, QString::fromUtf8( ldif, ldif.size()-1 ) ); + } + mOk = false; + } else { + mOk = true; + } +} + +void KGroupLDAP::data( KIO::Job*, const QByteArray& data ) +{ + if ( data.size() ) { + mParser.setLDIF( data ); + } else { + mParser.endLDIF(); + } + + KABC::LDIF::ParseVal ret; + QString name, val; + QByteArray value; + do { + ret = mParser.nextItem(); + switch ( ret ) { + case KABC::LDIF::Item: + name = mParser.attr().lower(); + value = mParser.val(); + val = QString::fromUtf8( value, value.size() ); + if ( name == "objectclass" ) { + if ( val.lower() == "sambagroupmapping" ) + mGroup->setCaps( KU::KGroup::Cap_Samba ); + } else if ( name == "gidnumber" ) + mGroup->setGID( val.toLong() ); + else if ( name == "cn" ) + mGroup->setName( val ); + else if ( name == "userpassword" ) + mGroup->setPwd( val ); + else if ( name == "memberuid" ) + mGroup->addUser( val ); + else if ( name == "sambasid" ) + mGroup->setSID( val ); + else if ( name == "sambagrouptype" ) + mGroup->setType( val.toInt() ); + else if ( name == "displayname" ) + mGroup->setDisplayName( val ); + else if ( name == "description" ) + mGroup->setDesc( val ); + break; + case KABC::LDIF::EndEntry: { + KU::KGroup newGroup; + mGroups.append( new KU::KGroup( mGroup ) ); + mGroup->copy( &newGroup ); + if ( ( mGroups.count() & 7 ) == 7 ) { + mProg->progressBar()->advance( mAdv ); + if ( mProg->progressBar()->progress() == 0 ) mAdv = 1; + if ( mProg->progressBar()->progress() == mProg->progressBar()->totalSteps()-1 ) mAdv = -1; + } + break; + } + default: + break; + } + } while ( ret != KABC::LDIF::MoreData ); +} + +bool KGroupLDAP::reload() +{ + kdDebug() << "KGroupLDAP::reload()" << endl; + mGroup = new KU::KGroup(); + mParser.startParsing(); + + mProg = new KProgressDialog( 0, "", "", i18n("Loading Groups From LDAP"), true ); + mProg->setAutoClose( false ); + mProg->progressBar()->setFormat( "" ); + mProg->progressBar()->setTotalSteps( 100 ); + mAdv = 1; + mCancel = true; + ldif = ""; + + KIO::Job *job = KIO::get( mUrl, true, false ); + connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ), + this, SLOT( data( KIO::Job*, const QByteArray& ) ) ); + connect( job, SIGNAL( result( KIO::Job* ) ), + this, SLOT( result( KIO::Job* ) ) ); + mProg->exec(); + if ( mCancel ) job->kill(); + + delete mGroup; + return( mOk ); +} + +bool KGroupLDAP::dbcommit() +{ + mAddSucc.clear(); + mDelSucc.clear(); + mModSucc.clear(); + mAdd.first(); + mDel.first(); + mAddGroup = 0; mDelGroup = 0; mGroup = 0; + ldif = ""; + + mProg = new KProgressDialog( 0, "", i18n("LDAP Operation"), "", true ); + KIO::Job *job = KIO::put( mUrl, -1, false, false, false ); + connect( job, SIGNAL( dataReq( KIO::Job*, QByteArray& ) ), + this, SLOT( putData( KIO::Job*, QByteArray& ) ) ); + connect( job, SIGNAL( result( KIO::Job* ) ), + this, SLOT( result( KIO::Job* ) ) ); + mProg->exec(); + return( mOk ); +} + +void KGroupLDAP::putData( KIO::Job*, QByteArray& data ) +{ + ModIt mit = mMod.begin(); + + if ( mAddGroup ) { + mAddSucc.append( mAddGroup ); + mAdd.remove(); + mAddGroup = 0; + } + if ( mDelGroup ) { + mDelSucc.append( mDelGroup ); + mDel.remove(); + mDelGroup = 0; + } + if ( mGroup ) { + mModSucc.insert( mGroup, mit.data() ); + mMod.remove( mit ); + mit = mMod.begin(); + mGroup = 0; + } + + if ( (mAddGroup = mAdd.current()) ) { + addData( mAddGroup ); + data = ldif; + } else if ( mit != mMod.end() ) { + mGroup = mit.key(); + modData( &(mit.data()) ); + data = ldif; + } else if ( (mDelGroup = mDel.current()) ) { + delData( mDelGroup ); + data = ldif; + } else + data.resize(0); +} + +void KGroupLDAP::addData( KU::KGroup *group ) +{ + ldif = "dn: " + getRDN( group ).utf8() + "," + + mUrl.dn().utf8() + "\n" + "objectclass: posixGroup\n"; + + ldif += + KABC::LDIF::assembleLine( "cn", group->getName() ) + "\n" + + KABC::LDIF::assembleLine( "gidnumber", QString::number(group->getGID()) ) + "\n" + + KABC::LDIF::assembleLine( "userpassword", group->getPwd() ) + "\n"; + for ( uint i=0; i < group->count(); i++ ) { + ldif += KABC::LDIF::assembleLine( "memberuid", group->user(i) ) + "\n"; + } + if ( ( getCaps() & Cap_Samba ) && ( group->getCaps() & KU::KGroup::Cap_Samba ) ) { + ldif += "objectclass: sambagroupmapping\n" + + KABC::LDIF::assembleLine( "sambasid", group->getSID().getSID() ) + "\n" + + KABC::LDIF::assembleLine( "displayname", group->getDisplayName() ) + "\n" + + KABC::LDIF::assembleLine( "description", group->getDesc() ) + "\n" + + KABC::LDIF::assembleLine( "sambagrouptype", QString::number( group->getType() ) ) + "\n"; + } + ldif += "\n\n"; + kdDebug() << "ldif: " << ldif << endl; +} + +void KGroupLDAP::delData( KU::KGroup *group ) +{ + ldif = "dn: " + getRDN( group ).utf8() + "," + + mUrl.dn().utf8() + "\n" + "changetype: delete\n\n"; + kdDebug() << "ldif: " << ldif << endl; +} + +void KGroupLDAP::modData( KU::KGroup *group ) +{ + QString oldrdn = getRDN( mGroup ); + QString newrdn = getRDN( group ); + + ldif = ""; + if ( oldrdn != newrdn ) { + ldif = "dn: " + oldrdn.utf8() + "," + mUrl.dn().utf8() + "\n" + + "changetype: modrdn\n" + + "newrdn: " + newrdn.utf8() + "\n" + + "deleteoldrdn: 1\n\n"; + } + + ldif += "dn: " + newrdn.utf8() + "," + mUrl.dn().utf8() + "\n" + + "changetype: modify\n" + + "replace: objectclass\n" + + "objectclass: posixgroup\n"; + if ( ( getCaps() & Cap_Samba ) && ( group->getCaps() & KU::KGroup::Cap_Samba ) ) { + ldif += "objectclass: sambagroupmapping\n"; + } + ldif += + "-\nreplace: cn\n" + + KABC::LDIF::assembleLine( "cn", group->getName() ) + + "\n-\nreplace: gidnumber\n" + + KABC::LDIF::assembleLine( "gidnumber", QString::number(group->getGID()) ) + + "\n-\nreplace: userpassword\n" + + KABC::LDIF::assembleLine( "userpassword", group->getPwd() ) + + "\n-\nreplace: memberuid\n"; + for ( uint i=0; i < group->count(); i++ ) { + ldif += KABC::LDIF::assembleLine( "memberuid", group->user(i)) + "\n"; + } + if ( getCaps() & Cap_Samba ) { + if ( group->getCaps() & KU::KGroup::Cap_Samba ) { + ldif += + "-\nreplace: sambasid\n" + + KABC::LDIF::assembleLine( "sambasid", group->getSID().getSID() ) + + "\n-\nreplace: displayname\n" + + KABC::LDIF::assembleLine( "displayname", group->getDisplayName() ) + + "\n-\nreplace: description\n" + + KABC::LDIF::assembleLine( "description", group->getDesc() ) + + "\n-\nreplace: sambagrouptype\n" + + KABC::LDIF::assembleLine( "sambagrouptype", QString::number( group->getType() ) ) + "\n"; + } else { + ldif += "-\nreplace: sambasid\n"; + ldif += "-\nreplace: displayname\n"; + ldif += "-\nreplace: description\n"; + ldif += "-\nreplace: sambagrouptype\n"; + ldif += "-\nreplace: sambasidlist\n"; + } + } + + ldif += "-\n\n"; + kdDebug() << "ldif: " << ldif << endl; +} diff --git a/kuser/kgroupldap.h b/kuser/kgroupldap.h new file mode 100644 index 0000000..ece0185 --- /dev/null +++ b/kuser/kgroupldap.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GROUPLDAP_H_ +#define _KU_GROUPLDAP_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qptrlist.h> + +#include <kprogress.h> +#include <kabc/ldapurl.h> +#include <kabc/ldif.h> +#include <kio/job.h> + +#include "kgroup.h" + +class KGroupLDAP : public QObject, public KU::KGroups { +Q_OBJECT +public: + KGroupLDAP( KUserPrefsBase *cfg ); + virtual ~KGroupLDAP(); + + virtual bool reload(); + virtual bool dbcommit(); + +private slots: + void data( KIO::Job*, const QByteArray& ); + void putData( KIO::Job *job, QByteArray& data ); + void result( KIO::Job* ); +private: + KABC::LDIF mParser; + KABC::LDAPUrl mUrl; + KProgressDialog *mProg; + + KU::KGroup *mGroup, *mDelGroup, *mAddGroup; + + bool first, mOk, mCancel; + int mAdv; + QCString ldif; + + QString getRDN( KU::KGroup *group ); + void addData( KU::KGroup *group ); + void delData( KU::KGroup *group ); + void modData( KU::KGroup *group ); +}; + +#endif // _KU_GROUPLDAP_H_ + diff --git a/kuser/kgroupsystem.cpp b/kuser/kgroupsystem.cpp new file mode 100644 index 0000000..1cb2f13 --- /dev/null +++ b/kuser/kgroupsystem.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "globals.h" +#include <errno.h> +#include <grp.h> + +#include <qstring.h> + +#include <kdebug.h> +#include <kmessagebox.h> + +#include "kglobal_.h" +#include "kgroupsystem.h" +#include "misc.h" + +KGroupSystem::KGroupSystem( KUserPrefsBase *cfg ) : KU::KGroups( cfg ) +{ + caps = Cap_ReadOnly | Cap_Passwd; + + reload(); +} + +KGroupSystem::~KGroupSystem() +{ + mGroups.clear(); +} + +bool KGroupSystem::reload() +{ + struct group *p; + KU::KGroup *tmpKG = 0; + + setgrent(); + while ((p = getgrent()) != NULL) { + tmpKG = new KU::KGroup(); + tmpKG->setGID(p->gr_gid); + tmpKG->setName(QString::fromLocal8Bit(p->gr_name)); + tmpKG->setPwd(QString::fromLocal8Bit(p->gr_passwd)); + + char *u_name; + int i = 0; + while ((u_name = p->gr_mem[i])!=0) { + tmpKG->addUser(QString::fromLocal8Bit(u_name)); + i++; + } + + mGroups.append(tmpKG); + } + + endgrent(); + return true; +} diff --git a/kuser/kgroupsystem.h b/kuser/kgroupsystem.h new file mode 100644 index 0000000..b26dea8 --- /dev/null +++ b/kuser/kgroupsystem.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GROUPSYSTEM_H_ +#define _KU_GROUPSYSTEM_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qptrlist.h> + +#include "kgroup.h" + +class KGroupSystem : public KU::KGroups { +public: + KGroupSystem( KUserPrefsBase *cfg ); + virtual ~KGroupSystem(); + + virtual bool reload(); + virtual bool dbcommit() { return true; } +}; + +#endif // _KU_GROUPSYSTEM_H_ + diff --git a/kuser/kgroupvw.cpp b/kuser/kgroupvw.cpp new file mode 100644 index 0000000..2641554 --- /dev/null +++ b/kuser/kgroupvw.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kglobal_.h" +#include "misc.h" + +#include "kgroupvw.h" + + +KGroupViewItem::KGroupViewItem(KListView *parent, KU::KGroup *aku) + : KListViewItem(parent), mGroup(aku) +{ +} + +int KGroupViewItem::compare( QListViewItem *i, int col, bool ascending ) const +{ + switch ( col ) { + case 0: { + gid_t gid1, gid2; + + gid1 = mGroup->getGID(); + gid2 = ((KGroupViewItem*) i)->mGroup->getGID(); + + if ( gid1 == gid2 ) return 0; + return ( gid1 < gid2) ? -1: 1; + } + case 2: { + uint rid1,rid2; + rid1 = mGroup->getSID().getRID(); + rid2 = ((KGroupViewItem*) i)->mGroup->getSID().getRID(); + if ( rid1 == rid2 ) return 0; + return ( rid1 < rid2) ? -1: 1; + } + default: + return QListViewItem::compare( i, col, ascending ); + } +} + +QString KGroupViewItem::text(int num) const +{ + switch(num) + { + case 0: return QString::number(mGroup->getGID()); + case 1: return mGroup->getName(); + case 2: return ( mGroup->getCaps() & KU::KGroup::Cap_Samba ) ? + mGroup->getSID().getDOM() : QString::null; + case 3: return ( mGroup->getCaps() & KU::KGroup::Cap_Samba ) ? + QString::number( mGroup->getSID().getRID() ) : QString::null; + case 4: { + if ( mGroup->getCaps() & KU::KGroup::Cap_Samba ) { + switch ( mGroup->getType() ) { + case 2: return i18n("Domain"); + case 4: return i18n("Local"); + case 5: return i18n("Builtin"); + default: return i18n("Unknown"); + } + } else { + return QString::null; + } + } + case 5: return mGroup->getDisplayName(); + case 6: return mGroup->getDesc(); + } + return QString::null; +} + + +KGroupView::KGroupView(QWidget *parent, const char *name) + : KListView( parent, name ) +{ + setSelectionMode( QListView::Extended ); +} + +KGroupView::~KGroupView() +{ +} + +void KGroupView::insertItem(KU::KGroup *aku) +{ + KGroupViewItem *groupItem = new KGroupViewItem(this, aku); + KListView::insertItem(groupItem); +} + +void KGroupView::removeItem(KU::KGroup *aku) +{ + KGroupViewItem *groupItem = (KGroupViewItem *)firstChild(); + + while(groupItem) + { + if (groupItem->group() == aku) + { + delete groupItem; + return; + } + groupItem = (KGroupViewItem*) groupItem->nextSibling(); + } +} + +void KGroupView::init() +{ + while ( columns() > 2 ) { + removeColumn( 2 ); + } + setAllColumnsShowFocus(true); + + if ( columns() < 2 ) { + addColumn(i18n("GID")); + setColumnAlignment(0, AlignRight); + addColumn(i18n("Group Name")); + } + if ( kug->getGroups().getCaps() & KU::KGroups::Cap_Samba ) { + addColumn(i18n("Domain SID")); + addColumn(i18n("RID")); + addColumn(i18n("Type")); + addColumn(i18n("Display Name")); + addColumn(i18n("Description")); + } +} + +KU::KGroup *KGroupView::getCurrentGroup() +{ + KGroupViewItem *groupItem = (KGroupViewItem *)currentItem(); + if (!groupItem) return 0; + + return groupItem->group(); +} + +#include "kgroupvw.moc" diff --git a/kuser/kgroupvw.h b/kuser/kgroupvw.h new file mode 100644 index 0000000..4667f8c --- /dev/null +++ b/kuser/kgroupvw.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_GROUPVW_H_ +#define _KU_GROUPVW_H_ + +#include <qwidget.h> + +#include <klistview.h> + +#include "kgroup.h" + +class KGroupViewItem : public KListViewItem +{ +public: + KGroupViewItem(KListView *parent, KU::KGroup *aku); + KU::KGroup *group() { return mGroup; } +private: + virtual QString text ( int ) const; + virtual int compare( QListViewItem *i, int col, bool ascending ) const; + + KU::KGroup *mGroup; +}; + +class KGroupView : public KListView +{ + Q_OBJECT + +public: + KGroupView( QWidget* parent = 0, const char* name = 0 ); + + virtual ~KGroupView(); + + void insertItem(KU::KGroup *aku); + void removeItem(KU::KGroup *aku); + KU::KGroup *getCurrentGroup(); + void init(); +}; + +#endif // _KGROUPVW_H_ diff --git a/kuser/kuser.cpp b/kuser/kuser.cpp new file mode 100644 index 0000000..2fd9ff1 --- /dev/null +++ b/kuser/kuser.cpp @@ -0,0 +1,1053 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "globals.h" + +#include <errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include <fcntl.h> +#include <qstring.h> +#include <qdir.h> + +#include "kglobal_.h" +#include "kuser.h" +#include "misc.h" +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kprocess.h> +#include <kdebug.h> +#include <kio/netaccess.h> +#include <kurl.h> + +// class KUser + +KU::KUser::KUser() +{ + p_change = 0; + p_expire = -1; + p_uid = 0; + p_gid = 100; + + s_min = 0; + s_max = 99999; + s_warn = 7; + s_inact = -1; +// s_flag = 0; + caps = 0; + isCreateHome = false; + isCreateMailBox = false; + isCopySkel = false; + isDeleteHome = false; + isDeleteMailBox = false; + + isDisabled = true; +} + +KU::KUser::KUser(const KU::KUser *user) +{ + copy(user); +} + +void KU::KUser::copy(const KU::KUser *user) +{ + if ( user != this ) { + caps = user->caps; + p_name = user->p_name; + p_surname = user->p_surname; + p_email = user->p_email; + p_pwd = user->p_pwd; + p_dir = user->p_dir; + p_shell = user->p_shell; + p_fname = user->p_fname; + p_office = user->p_office; + p_ophone = user->p_ophone; + p_hphone = user->p_hphone; + p_class = user->p_class; + p_change = user->p_change; + p_expire = user->p_expire; + p_office1 = user->p_office1; + p_office2 = user->p_office2; + p_address = user->p_address; + + p_uid = user->p_uid; + p_gid = user->p_gid; + + s_pwd = user->s_pwd; + s_min = user->s_min; + s_max = user->s_max; + s_warn = user->s_warn; + s_inact = user->s_inact; + s_flag = user->s_flag; + + sam_lmpwd = user->sam_lmpwd; + sam_ntpwd = user->sam_ntpwd; + sam_loginscript = user->sam_loginscript; + sam_profile = user->sam_profile; + sam_homedrive = user->sam_homedrive; + sam_homepath = user->sam_homepath; + sam_workstations = user->sam_workstations; + sam_domain = user->sam_domain; + sid = user->sid; + pgroup_sid = user->pgroup_sid; + + isCreateHome = user->isCreateHome; + isCreateMailBox = user->isCreateMailBox; + isDeleteHome = user->isDeleteHome; + isDeleteMailBox = user->isDeleteMailBox; + isCopySkel = user->isCopySkel; + isDisabled = user->isDisabled; + } +} + +KU::KUser::~KUser() +{ +} + +void KU::KUser::setCaps( int data ) +{ + caps = data; +} + +int KU::KUser::getCaps() +{ + return caps; +} + +bool KU::KUser::getDeleteHome() +{ + return isDeleteHome; +} + +bool KU::KUser::getDeleteMailBox() +{ + return isDeleteMailBox; +} + +bool KU::KUser::getCreateHome() +{ + return isCreateHome; +} + +bool KU::KUser::getCreateMailBox() +{ + return isCreateMailBox; +} + +bool KU::KUser::getCopySkel() +{ + return isCopySkel; +} + +const QString &KU::KUser::getName() const +{ + return p_name; +} + +const QString &KU::KUser::getSurname() const +{ + return p_surname; +} + +const QString &KU::KUser::getEmail() const +{ + return p_email; +} + +const QString &KU::KUser::getPwd() const +{ + return p_pwd; +} + +const QString &KU::KUser::getHomeDir() const +{ + return p_dir; +} + +const QString &KU::KUser::getShell() const +{ + return p_shell; +} + +const QString &KU::KUser::getFullName() const +{ + return p_fname; +} + +bool KU::KUser::getDisabled() const +{ + return isDisabled; +} + +// FreeBSD apparently uses the GECOS fields differently than other Unices. +// Create some better named functions to make the FreeBSD code clear +const QString &KU::KUser::getOffice() const +{ + return p_office; +} + +const QString &KU::KUser::getWorkPhone() const +{ + return p_ophone; +} + +const QString &KU::KUser::getHomePhone() const +{ + return p_hphone; +} + +// New fields needed for the FreeBSD /etc/master.passwd file +const QString &KU::KUser::getClass() const +{ + return p_class; +} + +const QString &KU::KUser::getOffice1() const +{ + return p_office1; +} + +const QString &KU::KUser::getOffice2() const +{ + return p_office2; +} + +const QString &KU::KUser::getAddress() const +{ + return p_address; +} + +uid_t KU::KUser::getUID() const +{ + return p_uid; +} + +gid_t KU::KUser::getGID() const +{ + return p_gid; +} + +const QString &KU::KUser::getSPwd() const +{ + return s_pwd; +} + +time_t KU::KUser::getLastChange() const +{ + return p_change; +} + +int KU::KUser::getMin() const +{ + return s_min; +} + +int KU::KUser::getMax() const +{ + return s_max; +} + +int KU::KUser::getWarn() const +{ + return s_warn; +} + +int KU::KUser::getInactive() const +{ + return s_inact; +} + +int KU::KUser::getFlag() const +{ + return s_flag; +} + +time_t KU::KUser::getExpire() const +{ + return p_expire; +} + +const QString &KU::KUser::getLMPwd() const // sam_lmpwd, +{ + return sam_lmpwd; +} + +const QString &KU::KUser::getNTPwd() const //sam_ntpwd, +{ + return sam_ntpwd; +} + +const QString &KU::KUser::getLoginScript() const //sam_loginscript, +{ + return sam_loginscript; +} + +const QString &KU::KUser::getProfilePath() const // sam_profile, +{ + return sam_profile; +} + +const QString &KU::KUser::getHomeDrive() const //sam_homedrive, +{ + return sam_homedrive; +} + +const QString &KU::KUser::getHomePath() const //sam_homepath; +{ + return sam_homepath; +} + +const QString &KU::KUser::getWorkstations() const //sam_workstation; +{ + return sam_workstations; +} + +const QString &KU::KUser::getDomain() const //sam_domain; +{ + return sam_domain; +} + +const SID &KU::KUser::getSID() const //sid, +{ + return sid; +} + +const SID &KU::KUser::getPGSID() const //pgroup_sid; +{ + return pgroup_sid; +} + +void KU::KUser::setName(const QString &data) +{ + p_name = data; +} + +void KU::KUser::setSurname(const QString &data) +{ + p_surname = data; +} + +void KU::KUser::setEmail(const QString &data) +{ + p_email = data; +} + +void KU::KUser::setPwd(const QString &data) +{ + p_pwd = data; +} + +void KU::KUser::setHomeDir(const QString &data) +{ + p_dir = data; +} + +void KU::KUser::setShell(const QString &data) +{ + p_shell = data; +} + +void KU::KUser::setFullName(const QString &data) +{ + p_fname = data; +} + +void KU::KUser::setDisabled(bool data) +{ + isDisabled = data; +} + +// FreeBSD apparently uses the GECOS fields differently than other Unices. +// Create some better named functions to make the FreeBSD code clear +void KU::KUser::setOffice(const QString &data) +{ + p_office = data; +} + +void KU::KUser::setWorkPhone(const QString &data) +{ + p_ophone = data; +} + +void KU::KUser::setHomePhone(const QString &data) +{ + p_hphone = data; +} + +// New fields needed for the FreeBSD /etc/master.passwd file +void KU::KUser::setClass(const QString &data) +{ + p_class = data; +} + +void KU::KUser::setLastChange(time_t data) +{ + p_change = data; +} + +void KU::KUser::setExpire(time_t data) +{ + p_expire = data; +} + +void KU::KUser::setOffice1(const QString &data) +{ + p_office1 = data; +} + +void KU::KUser::setOffice2(const QString &data) +{ + p_office2 = data; +} + +void KU::KUser::setAddress(const QString &data) +{ + p_address = data; +} + +void KU::KUser::setUID(uid_t data) +{ + p_uid = data; +} + +void KU::KUser::setGID(gid_t data) +{ + p_gid = data; +} + +void KU::KUser::setSPwd(const QString &data) +{ + s_pwd = data; +} + +void KU::KUser::setMin(int data) +{ + s_min = data; +} + +void KU::KUser::setMax(int data) +{ + s_max = data; +} + +void KU::KUser::setWarn(int data) +{ + s_warn = data; +} + +void KU::KUser::setInactive(int data) +{ + s_inact = data; +} + +void KU::KUser::setLMPwd( const QString &data ) // sam_lmpwd, +{ + sam_lmpwd = data; +} + +void KU::KUser::setNTPwd( const QString &data ) //sam_ntpwd, +{ + sam_ntpwd = data; +} + +void KU::KUser::setLoginScript( const QString &data ) //sam_loginscript, +{ + sam_loginscript = data; +} + +void KU::KUser::setProfilePath( const QString &data) // sam_profile, +{ + sam_profile = data; +} + +void KU::KUser::setHomeDrive( const QString &data ) //sam_homedrive, +{ + sam_homedrive = data; +} + +void KU::KUser::setHomePath( const QString &data ) //sam_homepath; +{ + sam_homepath = data; +} + +void KU::KUser::setWorkstations( const QString &data ) //sam_workstation; +{ + sam_workstations = data; +} + +void KU::KUser::setDomain( const QString &data ) //sam_domain +{ + sam_domain = data; +} + +void KU::KUser::setSID( const SID &data ) //sid, +{ + sid = data; +} + +void KU::KUser::setPGSID( const SID &data ) //pgroup_sid; +{ + pgroup_sid = data; +} + +void KU::KUser::setFlag(int data) +{ + s_flag = data; +} + +void KU::KUser::setCreateHome(bool data) +{ + isCreateHome = data; +} + +void KU::KUser::setCreateMailBox(bool data) +{ + isCreateMailBox = data; +} + +void KU::KUser::setCopySkel(bool data) +{ + isCopySkel = data; +} + +void KU::KUser::setDeleteHome(bool data) +{ + isDeleteHome = data; +} + +void KU::KUser::setDeleteMailBox(bool data) +{ + isDeleteMailBox = data; +} + +int KU::KUser::createHome() +{ + + if(p_dir.isNull() || p_dir.isEmpty()) { + KMessageBox::sorry( 0, i18n("Cannot create home folder for %1: it is null or empty.").arg(p_name) ); + return(0); + } + if (mkdir(QFile::encodeName(p_dir), 0700) != 0) { + if (errno != EEXIST) + { + KMessageBox::error( 0, i18n("Cannot create home folder %1.\nError: %2").arg(p_dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + return(0); + } + } + + if (chown(QFile::encodeName(p_dir), p_uid, p_gid) != 0) { + KMessageBox::error( 0, i18n("Cannot change owner of home folder %1.\nError: %2").arg(p_dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + return(1); + } + + if (chmod(QFile::encodeName(p_dir), KU_HOMEDIR_PERM) != 0) { + KMessageBox::error( 0, i18n("Cannot change permissions on home folder %1.\nError: %2").arg(p_dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + return(1); + } + return(1); +} + +int KU::KUser::tryCreate(const QString &dir) +{ + struct stat sb; + int rc = 0; + + rc = stat(QFile::encodeName(dir), &sb); + if (rc == 0) { + if (S_ISDIR(sb.st_mode)) { + if (KMessageBox::warningContinueCancel( 0, + i18n("Folder %1 already exists!\nWill make %2 owner and change permissions.\nDo you want to continue?").arg(dir).arg(p_name), + QString::null, KStdGuiItem::cont() ) == KMessageBox::Continue) { + + if (chown(QFile::encodeName(dir), p_uid, p_gid) != 0) { + KMessageBox::error( 0, i18n("Cannot change owner of %1 folder.\nError: %2") .arg(dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + return(0); + } else { + KMessageBox::information( 0, i18n("Folder %1 left 'as is'.\nVerify ownership and permissions for user %2 who may not be able to log in!").arg(dir).arg(p_name) ); + return(-1); + } + } else { + KMessageBox::information( 0, i18n("%1 exists and is not a folder. User %2 will not be able to log in!").arg(dir).arg(p_name) ); + return(-1); + } + } else { + if (errno == ENOENT) { + if (mkdir(QFile::encodeName(dir), 0700) != 0) { + KMessageBox::error( 0, i18n("Cannot create %1 folder.\nError: %2").arg(dir).arg(QString::fromLocal8Bit(strerror(errno)))); + return(-1); + } + if (chown(QFile::encodeName(dir), p_uid, p_gid) != 0) { + KMessageBox::error( 0, i18n("Cannot change owner of %1 folder.\nError: %2").arg(dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + return(0); + } else { + KMessageBox::error( 0, i18n("stat call on %1 failed.\nError: %2").arg(dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + return(-1); + } + } +} + +int KU::KUser::createMailBox() +{ + QString mailboxpath; + int fd; + mailboxpath = QFile::decodeName(MAIL_SPOOL_DIR) + "/" + p_name; + if((fd = open(QFile::encodeName(mailboxpath), O_CREAT|O_EXCL|O_WRONLY, + S_IRUSR|S_IWUSR)) < 0) { + if (errno != EEXIST) + { + KMessageBox::error( 0, i18n("Cannot create %1: %2") + .arg(mailboxpath) + .arg(QString::fromLocal8Bit(strerror(errno))) ); + return -1; + } + } + + close(fd); + + if (chown(QFile::encodeName(mailboxpath), p_uid, KU_MAILBOX_GID) != 0) { + KMessageBox::error( 0, i18n("Cannot change owner on mailbox: %1\nError: %2") + .arg(mailboxpath).arg(QString::fromLocal8Bit(strerror(errno))) ); + return -1; + } + + if (chmod(QFile::encodeName(mailboxpath), KU_MAILBOX_PERM) != 0) { + KMessageBox::error( 0, i18n("Cannot change permissions on mailbox: %1\nError: %2") + .arg(mailboxpath).arg(QString::fromLocal8Bit(strerror(errno))) ); + return -1; + } + + return 0; +} + +void KU::KUser::copyDir(const QString &srcPath, const QString &dstPath) +{ + mode_t mode; + QDir s(srcPath); + QDir d(dstPath); + + QString dot = QString::fromLatin1("."); + QString dotdot = QString::fromLatin1(".."); + + s.setFilter( QDir::All | QDir::Hidden | QDir::System ); + + for (uint i=0; i<s.count(); i++) { + QString name(s[i]); + + if (name == dot) + continue; + if (name == dotdot) + continue; + + QString filename(s.filePath(name)); + + QFileInfo info(filename); + mode = 0; + if ( info.permission(QFileInfo::ReadOwner) ) mode |= S_IRUSR; + if ( info.permission(QFileInfo::WriteOwner) ) mode |= S_IWUSR; + if ( info.permission(QFileInfo::ExeOwner) ) mode |= S_IXUSR; + if ( info.permission(QFileInfo::ReadGroup) ) mode |= S_IRGRP; + if ( info.permission(QFileInfo::WriteGroup) ) mode |= S_IWGRP; + if ( info.permission(QFileInfo::ExeGroup) ) mode |= S_IXGRP; + if ( info.permission(QFileInfo::ReadOther) ) mode |= S_IROTH; + if ( info.permission(QFileInfo::WriteOther) ) mode |= S_IWOTH; + if ( info.permission(QFileInfo::ExeOther) ) mode |= S_IXOTH; + + if ( info.isSymLink() ) { + QString link = info.readLink(); + + if (symlink(QFile::encodeName(link),QFile::encodeName(d.filePath(name))) != 0) { + KMessageBox::error( 0, i18n("Error creating symlink %1.\nError: %2") + .arg(d.filePath(s[i])).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + } else if ( info.isDir() ) { + QDir dir(filename); + + d.mkdir(name, FALSE); + copyDir(s.filePath(name), d.filePath(name)); + + if (chown(QFile::encodeName(d.filePath(name)), p_uid, p_gid) != 0) { + KMessageBox::error( 0, i18n("Cannot change owner of folder %1.\nError: %2") + .arg(d.filePath(s[i])).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + + if (chmod(QFile::encodeName(d.filePath(name)), mode) != 0) { + KMessageBox::error( 0, i18n("Cannot change permissions on folder %1.\nError: %2") + .arg(d.filePath(s[i])).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + + } else { + if (copyFile(filename, d.filePath(name)) == -1) { + continue; + } + + if (chown(QFile::encodeName(d.filePath(name)), p_uid, p_gid) != 0) { + KMessageBox::error( 0, i18n("Cannot change owner of file %1.\nError: %2") + .arg(d.filePath(s[i])).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + + if (chmod(QFile::encodeName(d.filePath(name)), mode) != 0) { + KMessageBox::error( 0, i18n("Cannot change permissions on file %1.\nError: %2") + .arg(d.filePath(s[i])).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + } + } +} + +int KU::KUser::copySkel() +{ + QDir s(QFile::decodeName(SKELDIR)); + QDir d(p_dir); + mode_t mode; + + if (!s.exists()) { + KMessageBox::error( 0, i18n("Folder %1 does not exist, cannot copy skeleton for %2.").arg(s.absPath()).arg(p_name) ); + return (-1); + } + + if (!d.exists()) { + KMessageBox::error( 0, i18n("Folder %1 does not exist, cannot copy skeleton.").arg(d.absPath()) ); + return (-1); + } + + mode = umask(0007); + copyDir(s.absPath(), d.absPath()); + umask( mode ); + + return 0; +} + +int KU::KUser::removeHome() +{ + struct stat sb; + + if (!stat(QFile::encodeName(p_dir), &sb)) + if (S_ISDIR(sb.st_mode) && sb.st_uid == p_uid) { + if (!KIO::NetAccess::del(KURL::fromPathOrURL(p_dir))) { + KMessageBox::error( 0, i18n("Cannot remove home folder %1.\nError: %2") + .arg(p_dir).arg(KIO::NetAccess::lastErrorString()) ); + } + } else { + KMessageBox::error( 0, i18n("Removal of home folder %1 failed (uid = %2, gid = %3).").arg(p_dir).arg(sb.st_uid).arg(sb.st_gid) ); + } + else { + KMessageBox::error( 0, i18n("stat call on file %1 failed.\nError: %2") + .arg(p_dir).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + + return 0; +} + +//TODO: remove at jobs too. + +int KU::KUser::removeCrontabs() +{ + QString file; + QString command; + + file = QFile::decodeName(CRONTAB_DIR) + "/" + p_name; + if ( access(QFile::encodeName(file), F_OK) == 0 ) { + command = QString::fromLatin1("crontab -u %1 -r").arg(KProcess::quote(p_name)); + if ( system(QFile::encodeName(command)) != 0 ) { + KMessageBox::error( 0, i18n("Cannot remove crontab %1.\nError: %2") + .arg(command).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + } + + return 0; +} + +int KU::KUser::removeMailBox() +{ + QString file; + + file = QFile::decodeName(MAIL_SPOOL_DIR) + "/" + p_name; + if (remove(QFile::encodeName(file)) != 0) { + KMessageBox::error( 0, i18n("Cannot remove mailbox %1.\nError: %2") + .arg(file).arg(QString::fromLocal8Bit(strerror(errno))) ); + } + + return 0; +} + +int KU::KUser::removeProcesses() +{ + // be paranoid -- kill all processes owned by that user, if not root. + + if (p_uid != 0) + switch (fork()) { + case 0: + setuid(p_uid); + kill(-1, 9); + _exit(0); + break; + case -1: + KMessageBox::error( 0, + i18n("Cannot fork while trying to kill processes for uid %1.").arg(p_uid) ); + break; + } + + return 0; +} + +KU::KUsers::KUsers(KUserPrefsBase *cfg) +{ + mUsers.setAutoDelete(TRUE); + mCfg = cfg; +} + +KU::KUsers::~KUsers() +{ + mUsers.clear(); +} + +const QString &KU::KUsers::getDOMSID() const +{ + return domsid; +} + +void KU::KUsers::parseGecos( const char *gecos, QString &name, + QString &field1, QString &field2, QString &field3 ) +{ + int no = 0; + const char *s = gecos; + const char *pos = NULL; + // At least one part of the string exists + for(;;) { + pos = strchr(s, ','); + QString val; + if(pos == NULL) + val = QString::fromLocal8Bit(s); + else + val = QString::fromLocal8Bit(s, (int)(pos-s)); + + switch(no) { + case 0: name = val; break; + case 1: field1 = val; break; + case 2: field2 = val; break; + case 3: field3 = val; break; + } + if(pos == NULL) break; + s = pos+1; + no++; + } +} + +void KU::KUsers::fillGecos(KU::KUser *user, const char *gecos) +{ + QString name,field1,field2,field3; + parseGecos( gecos, name, field1, field2, field3 ); + user->setFullName( name ); + caps & Cap_BSD ? user->setOffice( field1 ) : user->setOffice1( field1 ); + caps & Cap_BSD ? user->setWorkPhone( field2 ) : user->setOffice2( field2 ); + caps & Cap_BSD ? user->setHomePhone( field3 ) : user->setAddress( field3 ); +} + +bool KU::KUsers::doCreate(KU::KUser *user) +{ + QString h_dir; + + if(user->getCreateMailBox()) { + user->createMailBox(); + user->setCreateMailBox(false); + } + + if(user->getCreateHome()) { + if(user->createHome()) { + user->setCreateHome(false); + } else { + return false; // if createHome fails, copySkel is irrelevant! + } + + if(user->getCopySkel()) { + if((user->copySkel()) == 0) { + user->setCopySkel(false); + } + } + + } + return TRUE; +} + +bool KU::KUsers::doDelete( KU::KUser *user ) +{ + kdDebug() << "delete user: " << user->getName() << " uid: " << user->getUID() << endl; + if ( user->isDeleteHome ) { + user->removeHome(); + user->removeCrontabs(); + } + if ( user->isDeleteMailBox ) + user->removeMailBox(); +/* + user->removeProcesses(); +*/ + return TRUE; +} + +KU::KUser *KU::KUsers::lookup(const QString & name) +{ + KU::KUser *user; + QPtrListIterator<KU::KUser> it( mUsers ); + + while ( (user = it.current()) != 0 && user->getName() != name ) ++it; + return user; +} + +KU::KUser *KU::KUsers::lookup(uid_t uid) +{ + KU::KUser *user; + QPtrListIterator<KU::KUser> it( mUsers ); + + while ( (user = it.current()) != 0 && user->getUID() != uid ) ++it; + return user; +} + +KU::KUser *KU::KUsers::lookup_sam( const SID &sid ) +{ + KU::KUser *user; + QPtrListIterator<KU::KUser> it( mUsers ); + + while ( (user = it.current()) != 0 && user->getSID() != sid ) ++it; + return user; +} + +KU::KUser *KU::KUsers::lookup_sam( const QString &sid ) +{ + KU::KUser *user; + QPtrListIterator<KU::KUser> it( mUsers ); + + while ( (user = it.current()) != 0 && user->getSID().getSID() != sid ) ++it; + return user; +} + +KU::KUser *KU::KUsers::lookup_sam( uint rid ) +{ + KU::KUser *user; + QPtrListIterator<KU::KUser> it( mUsers ); + + while ( (user = it.current()) != 0 && user->getSID().getRID() != rid ) ++it; + return user; +} + +uid_t KU::KUsers::first_free() +{ + uid_t t; + + for (t = mCfg->firstUID() ; t<65534; t++) + if (lookup(t) == NULL) + return t; + + return NO_FREE; +} + +uint KU::KUsers::first_free_sam() +{ + uint t; + + for (t = 1000; t<65534; t++) + if (lookup_sam(t) == NULL) + return t; + + return 0; +} + +uint KU::KUsers::count() const +{ + return mUsers.count(); +} + +KU::KUser *KU::KUsers::operator[](uint num) +{ + return mUsers.at(num); +} + +KU::KUser *KU::KUsers::first() +{ + return mUsers.first(); +} + +KU::KUser *KU::KUsers::next() +{ + return mUsers.next(); +} + +void KU::KUsers::add(KU::KUser *user) +{ + mAdd.append( user ); +} + +void KU::KUsers::del(KU::KUser *user) +{ + mDel.append( user ); +} + +void KU::KUsers::mod(KU::KUser *uold, const KU::KUser &unew) +{ + mMod.insert( uold, unew ); +} + +void KU::KUsers::commit() +{ + kdDebug() << "KU::KUsers::commit()" << endl; + KU::KUser *user; + DelIt dit( mDelSucc ); + AddIt ait( mAddSucc ); + ModIt mit = mModSucc.begin(); + +//commit modifications + while ( mit != mModSucc.end() ) { + *(mit.key()) = mit.data(); + mit++; + } +//commit deletes + while ( (user = dit.current()) != 0 ) { + ++dit; + doDelete( user ); + mUsers.remove( user ); + } +//commit additions + while ( (user = ait.current()) != 0 ) { + ++ait; + doCreate( user ); + mUsers.append( user ); + } + +//clear the unsuccessful modifications + cancelMods(); +} + +void KU::KUsers::cancelMods() +{ + KU::KUser *user; + while ( (user = mAdd.first()) ) { + delete user; + mAdd.remove(); + } + mDel.clear(); + mMod.clear(); +} diff --git a/kuser/kuser.desktop b/kuser/kuser.desktop new file mode 100644 index 0000000..b28b25f --- /dev/null +++ b/kuser/kuser.desktop @@ -0,0 +1,104 @@ +[Desktop Entry] +Name=KUser +Name[af]=Kuser +Name[ar]=برنامج KUser +Name[bn]=কে-ব্যবহারকারী +Name[eo]=Uzantoadministrilo +Name[fo]=KNýtari +Name[hi]=के-यूज़र +Name[is]=KNotandi +Name[lv]=KLietotājs +Name[mn]=КДЕ Хэрэглэгч +Name[nb]=KBruker +Name[ne]=केडीई प्रयोगकर्ता +Name[pa]=ਕੇ-ਉਪਭੋਗਤਾ +Name[pl]=Użytkownicy +Name[ro]=Manager de utilizatori +Name[sv]=Kuser +Name[ta]=கேபயனீட்டாளர் +Name[tg]=KИстифодакунанда +Name[th]=จัดการบัญชีผู้ใช้ - K +Name[uz]=Foydalanuvchilar +Name[uz@cyrillic]=Фойдаланувчилар +GenericName=User Manager +GenericName[af]=Gebruiker Bestuurder +GenericName[ar]=مسيير المستخدمين +GenericName[az]=İstifadəçi İdarəçisi +GenericName[be]=Кіраванне карыстальнікамі +GenericName[bg]=Управление на потребителите +GenericName[bn]=ব্যবহারকারী ম্যানেজার +GenericName[br]=Merour an arveriaded +GenericName[bs]=Upravljanje korisnicima +GenericName[ca]=Gestor d'usuaris +GenericName[cs]=Správce uživatelů +GenericName[cy]=Rheolydd Defnyddwyr +GenericName[da]=Brugerhåndtering +GenericName[de]=Benutzerverwaltung +GenericName[el]=Διαχειριστής χρηστών +GenericName[eo]=Administrilo por la uzantoj de la komputilo +GenericName[es]=Administrador de usuarios +GenericName[et]=Kasutajate haldamine +GenericName[eu]=Erabiltzaile kudeatzailea +GenericName[fa]=مدیر کاربر +GenericName[fi]=Käyttäjienhallinta +GenericName[fo]=Nýtarahandfarari +GenericName[fr]=Gestionnaire d'utilisateurs +GenericName[ga]=Bainisteoir Úsáideora +GenericName[gl]=Xestor de Usuários +GenericName[he]=מנהל משתמשים +GenericName[hi]=उपयोक्ता प्रबंधक +GenericName[hr]=Upravljanje korisnicima +GenericName[hu]=Felhasználókezelő +GenericName[is]=Notandastjóri +GenericName[it]=Gestore utenti +GenericName[ja]=ユーザマネージャ +GenericName[ka]=მომხმარებელთა მმართველი +GenericName[kk]=Пайдаланушылар менеджерx +GenericName[km]=កម្មវិធីគ្រប់គ្រងអ្នកប្រើ +GenericName[ko]=사용자 관리자 +GenericName[lt]=Naudotojų tvarkyklė +GenericName[lv]=Lietotāju Menedžeris +GenericName[mk]=Менаџер на корисници +GenericName[mn]=Хэрэглэгч Зохицуулагч +GenericName[ms]=Pengurus Pengguna +GenericName[mt]=Manager tal-users +GenericName[nb]=Brukerbehandler +GenericName[nds]=Bruker-Pleger +GenericName[ne]=प्रयोगकर्ता प्रबन्धक +GenericName[nl]=Gebruikersbeheerder +GenericName[nn]=Brukarhandsamar +GenericName[pa]=ਉਪਭੋਗਤਾ ਪਰਬੰਧਕ +GenericName[pl]=Menedżer użytkowników +GenericName[pt]=Gestor de Utilizadores +GenericName[pt_BR]=Gerenciador de Usuários +GenericName[ro]=Manager de utilizatori +GenericName[ru]=Управление пользователями +GenericName[se]=Geavaheaddjiid gieđahalli +GenericName[sk]=Správca užívateľov +GenericName[sl]=Upravljalnik uporabnikov +GenericName[sr]=Менаџер корисника +GenericName[sr@Latn]=Menadžer korisnika +GenericName[sv]=Användarhanterare +GenericName[ta]=பயனீட்டாளர் மேலாளர் +GenericName[tg]=Роҳбари Истифодакунанда +GenericName[th]=เครื่องมือจัดการบัญชีผู้ใช้ +GenericName[tr]=Kullanıcı Yöneticisi +GenericName[uk]=Менеджер користувачів +GenericName[uz]=Foydalanuvchilar boshqaruvchisi +GenericName[uz@cyrillic]=Фойдаланувчилар бошқарувчиси +GenericName[ven]=Murangaphanda wa Mushumisi +GenericName[vi]=Bộ quản lý người dùng +GenericName[wa]=Manaedjeu d' uzeus +GenericName[xh]=Umphathi We Calendar +GenericName[zh_CN]=用户管理程序 +GenericName[zh_HK]=用戶管理員 +GenericName[zh_TW]=使用者管理程式 +GenericName[zu]=Umphathi we Calendar +Exec=kuser %i %m -caption "%c" +Icon=kuser +Type=Application +DocPath=kuser/index.html +Terminal=false +X-KDE-StartupNotify=true +X-KDE-SubstituteUID=true +Categories=Qt;KDE;System; diff --git a/kuser/kuser.h b/kuser/kuser.h new file mode 100644 index 0000000..4e3c24e --- /dev/null +++ b/kuser/kuser.h @@ -0,0 +1,309 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_USER_H_ +#define _KU_USER_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qptrlist.h> + +#include "globals.h" +#include "sid.h" + +namespace KU { + +class KUsers; + +class KUser { +public: + enum Cap { + Cap_POSIX = 1, + Cap_Samba = 2 + }; + KUser(); + KUser(const KUser *user); + ~KUser(); + + void copy(const KUser *user); + void setCaps( int data ); + int getCaps(); + +//General + const QString &getName() const; + const QString &getSurname() const; + const QString &getEmail() const; + const QString &getPwd() const; + const QString &getHomeDir() const; + const QString &getShell() const; + const QString &getFullName() const; + + uid_t getUID() const; + uid_t getGID() const; + bool getDisabled() const; + + void setName(const QString &data); + void setSurname(const QString &data); + void setEmail(const QString &data); + void setPwd(const QString &data); + void setHomeDir(const QString &data); + void setShell(const QString &data); + void setFullName(const QString &data); + + void setUID(uid_t data); + void setGID(uid_t data); + void setDisabled(bool data); + +//gecos +//--BSD gecos + const QString &getOffice() const; + const QString &getWorkPhone() const; + const QString &getHomePhone() const; + const QString &getClass() const; +//--BSD end + const QString &getOffice1() const; + const QString &getOffice2() const; + const QString &getAddress() const; + +//--BSD + void setOffice(const QString &data); + void setWorkPhone(const QString &data); + void setHomePhone(const QString &data); + void setClass(const QString &data); +//--BSD end + void setOffice1(const QString &data); + void setOffice2(const QString &data); + void setAddress(const QString &data); + +//shadow + const QString &getSPwd() const; + time_t getExpire() const; + time_t getLastChange() const; + int getMin() const; + int getMax() const; + int getWarn() const; + int getInactive() const; + int getFlag() const; + + void setSPwd(const QString &data); + void setLastChange(time_t data); + void setMin(int data); + void setMax(int data); + void setWarn(int data); + void setInactive(int data); + void setExpire(time_t data); + void setFlag(int data); + +//samba + const QString &getLMPwd() const; // sam_lmpwd, + const QString &getNTPwd() const; //sam_ntpwd, + const QString &getLoginScript() const; //sam_loginscript, + const QString &getProfilePath() const; // sam_profile, + const QString &getHomeDrive() const; //sam_homedrive, + const QString &getHomePath() const; //sam_homepath; + const QString &getWorkstations() const; //sam_workstations + const QString &getDomain() const; //sam_domain + const SID &getSID() const; //sid, + const SID &getPGSID() const; //pgroup_sid; + + void setLMPwd( const QString &data ); // sam_lmpwd, + void setNTPwd( const QString &data ); //sam_ntpwd, + void setLoginScript( const QString &data ); //sam_loginscript, + void setProfilePath( const QString &data); // sam_profile, + void setHomeDrive( const QString &data ); //sam_homedrive, + void setHomePath( const QString &data ); //sam_homepath; + void setWorkstations( const QString &data ); //sam_workstations + void setDomain( const QString &data ); //sam_domain + void setSID( const SID &data ); //sid, + void setPGSID( const SID &data ); //pgroup_sid; + +//Administrative + bool getCreateHome(); + bool getCreateMailBox(); + bool getCopySkel(); + bool getDeleteHome(); + bool getDeleteMailBox(); + + void setCreateHome(bool data); + void setCreateMailBox(bool data); + void setCopySkel(bool data); + void setDeleteHome(bool data); + void setDeleteMailBox(bool data); + +protected: + friend class KUsers; + + int createHome(); + int tryCreate(const QString &dir); + int createMailBox(); + int copySkel(); + + int removeHome(); + int removeCrontabs(); + int removeMailBox(); + int removeProcesses(); + + void copyDir(const QString &srcPath, const QString &dstPath); + + int caps; + QString + p_name, // parsed pw information + p_surname, + p_email, + p_pwd, + p_dir, + p_shell, + p_fname, // parsed comment information + p_office1, + p_office2, + p_address, +//BSD + p_office, + p_ophone, + p_hphone, + p_class; + time_t + p_change, + p_expire; +//BSD end + uid_t p_uid; + gid_t p_gid; + + QString + s_pwd, // parsed shadow password + sam_lmpwd, + sam_ntpwd, + sam_loginscript, + sam_profile, + sam_homedrive, + sam_homepath, + sam_workstations, + sam_domain; + SID + sid, + pgroup_sid; + signed int + s_min, // days until pwchange allowed. + s_max, // days before change required + s_warn, // days warning for expiration + s_inact, // days before account inactive + s_flag; // reserved for future use + bool + isDisabled, // account disabled? + isCreateHome, // create homedir + isCreateMailBox, // create mailbox + isCopySkel, // copy skeleton + isDeleteHome, // delete home dir + isDeleteMailBox; // delete mailbox +}; + +class KUsers { +public: + enum Cap { + Cap_ReadOnly = 1, + Cap_Passwd = 2, + Cap_Shadow = 4, + Cap_InetOrg = 8, + Cap_Samba = 16, + Cap_Disable_POSIX = 32, + Cap_BSD = 64 + }; + typedef QPtrListIterator<KUser> DelIt; + typedef QPtrListIterator<KUser> AddIt; + typedef QMapIterator<KUser*, KUser> ModIt; + + QPtrList<KUser> mDelSucc; + QPtrList<KUser> mAddSucc; + QMap<KUser*, KUser> mModSucc; + + KUsers(KUserPrefsBase *cfg); + virtual ~KUsers(); + KUser *lookup(const QString & name); + KUser *lookup(uid_t uid); + KUser *lookup_sam( const SID &sid ); + KUser *lookup_sam( const QString &sid ); + KUser *lookup_sam( uint rid ); + + int getCaps() { return caps; } + const QString &getDOMSID() const; + + KUser *first(); + KUser *next(); + uint count() const; + KUser *operator[](uint num); + + void add( KUser *user ); + void del( KUser *user ); + void mod( KUser *uold, const KUser &unew ); + void commit(); + void cancelMods(); + + enum { + NO_FREE = (uid_t) -1 + }; + + /** + * May be reimplemented in descendant classes. + * It should return the first available UID, or KUsers::NO_FREE if no more UID. + */ + virtual uid_t first_free(); + /** + * May be reimplemented in descendant classes. + * It should return the first available user RID, or 0 if no more RID. + */ + virtual uint first_free_sam(); + /** + * Must be reimplemented in various backends. It should encode @param password + * into the appropriate fields in @param user. + */ + virtual void createPassword( KUser *user, const QString &password ) = 0; + /** + * Must load the users from the storage backend. + */ + virtual bool reload() = 0; + /** + * Must write changes (in mDel, mAdd and mMod) to the storage backend. It must + * write successful modifications into mDelSucc, mAddSucc and mModSucc. + */ + virtual bool dbcommit() = 0; + +protected: + QPtrList<KUser> mUsers; + int caps; + KUserPrefsBase *mCfg; + + QPtrList<KUser> mDel; + QPtrList<KUser> mAdd; + QMap<KUser*, KUser> mMod; + + QString domsid; + + bool doCreate( KUser *user ); + bool doDelete( KUser *user ); + void parseGecos( const char *gecos, QString &name, + QString &field1, QString &field2, QString &field3 ); + void fillGecos( KUser *user, const char *gecos ); + +}; + +} //namespace KU + +#endif // _KU_USER_H_ diff --git a/kuser/kuser.kcfg b/kuser/kuser.kcfg new file mode 100644 index 0000000..a1ec974 --- /dev/null +++ b/kuser/kuser.kcfg @@ -0,0 +1,318 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <include>qfile.h</include> + <include>kapplication.h</include> + <include>config.h</include> + + <kcfgfile arg="true"> + <parameter name="connection"/> + </kcfgfile> + + <group name="general"> + <entry name="connection" type="String"> + <label>Default connection</label> + <default>default</default> + </entry> + <entry name="showsys" type="Bool"> + <label>Show system users</label> + <default>true</default> + </entry> + </group> + <group name="connection-$(connection)"> + <entry name="source" type="Enum"> + <label>The source of the user and group database</label> + <whatsthis>This option allows you to select where the user/group data stored. Currently three storage backends are supported. <BR><B>Files</B> stores user/group data in traditional /etc/passwd and /etc/group flat files. <BR><B>LDAP</B> stores data in a directory server using the posixAccount and posixGroup object classes; this backend allows the management of Samba users/groups via the sambaSamAccount object class.<BR><B>System</B> provides a read-only access to all users and groups which your installation knows about.</whatsthis> + <choices> + <choice name="Files"/> + <choice name="LDAP"/> + <choice name="System"/> + </choices> + <default>Files</default> + </entry> + <entry name="shell" type="String"> + <label>Shell</label> + <whatsthis>This option allows you to select the shell which will be the default for new users.</whatsthis> + </entry> + <entry name="homepath" type="String"> + <label>Home path template</label> + <whatsthis>This option specifies the UNIX home path template for new users. The '%U' macro will replaced with the actual user name.</whatsthis> + <default code="true">QFile::decodeName(KU_HOMETEMPLATE)</default> + </entry> + <entry name="firstUID" type="Int"> + <label>First UID</label> + <whatsthis>This options specifies the first user ID where searching for an available UID starts.</whatsthis> + <default code="true">KU_FIRSTUID</default> + </entry> + <entry name="firstGID" type="Int"> + <label>First GID</label> + <whatsthis>This options specifies the first group ID where searching for an available GID starts.</whatsthis> + <default code="true">KU_FIRSTGID</default> + </entry> + <entry name="createHomeDir" type="Bool"> + <label>Create home folder</label> + <whatsthis>If this option is checked then a home directory will created for the new user.</whatsthis> + <default>true</default> + </entry> + <entry name="copySkel" type="Bool"> + <label>Copy skeleton to home folder</label> + <whatsthis>If this option is checked then the contents of the skeleton folder will copied to the new user's home directory</whatsthis> + <default>true</default> + </entry> + <entry name="userPrivateGroup" type="Bool"> + <label>User private groups</label> + <whatsthis>If this option is enabled, new user creation will create a private group named as the user, and the primary group of the user will assigned to this private group.</whatsthis> + <default code="true">KU_USERPRIVATEGROUP</default> + </entry> + <entry name="defaultgroup" type="Int"> + <label>Default primary group</label> + <whatsthis>This is the default primary group which will be assigned to a newly created user.</whatsthis> + <default>100</default> + </entry> + + <entry name="smin" type="Int"> + <label>smin</label> + <default>0</default> + </entry> + <entry name="smax" type="Int"> + <label>smax</label> + <default>-1</default> + </entry> + <entry name="swarn" type="Int"> + <label>swarn</label> + <default>-1</default> + </entry> + <entry name="sinact" type="Int"> + <label>sinact</label> + <default>-1</default> + </entry> + <entry name="sexpire" type="DateTime"> + <label>sexpire</label> + <whatsthis>This setting is for specifying a date when user accounts will expire.</whatsthis> + <default code="true">QDateTime(QDate(1970,1,1))</default> + </entry> + <entry name="sneverexpire" type="Bool"> + <label>sneverexpire</label> + <whatsthis>Check this if you want to user accounts never expire.</whatsthis> + <default>true</default> + </entry> + + <entry name="passwdsrc" type="String"> + <label>Password file</label> + <whatsthis>This specifies the users database file (usually /etc/passwd).</whatsthis> + <default>/etc/passwd</default> + </entry> + <entry name="groupsrc" type="String"> + <label>Group file</label> + <whatsthis>This specifies the groups database file (usually /etc/group).</whatsthis> + <default>/etc/group</default> + </entry> + <entry name="md5shadow" type="Bool"> + <label>MD5 Shadow passwords</label> + <whatsthis>Check this if you want the passwords in the shadow file MD5 hashed. Leave this unchecked if DES encryption should be used.</whatsthis> + </entry> + <entry name="shadowsrc" type="String"> + <label>Shadow password file</label> + <whatsthis>Specifies the shadow password file (usually /etc/shadow). Leave this empty if your system does not use a shadow password file.</whatsthis> + <default>/etc/shadow</default> + </entry> + <entry name="gshadowsrc" type="String"> + <label>Group shadow file</label> + <whatsthis>Specifies the shadow group file (usually /etc/gshadow). Leave this empty if your system does not use a shadow group file.</whatsthis> + <default>/etc/gshadow</default> + </entry> + <entry name="nispasswdsrc" type="String"> + <label>NIS password source</label> + </entry> + <entry name="nisminuid" type="Int"> + <label>NIS minimum UID</label> + </entry> + <entry name="nisgroupsrc" type="String"> + <label>NIS group source</label> + </entry> + <entry name="nismingid" type="Int"> + <label>NIS minimum GID</label> + </entry> + + <entry name="ldapuser" type="String"> + <label>LDAP User</label> + </entry> + <entry name="ldappassword" type="Password"> + <label>LDAP Password</label> + </entry> + <entry name="ldaprealm" type="String"> + <label>LDAP SASL Realm</label> + </entry> + <entry name="ldapbinddn" type="String"> + <label>LDAP Bind DN</label> + </entry> + <entry name="ldaphost" type="String"> + <label>LDAP Host</label> + </entry> + <entry name="ldapport" type="Int"> + <label>LDAP Port</label> + <default>389</default> + </entry> + <entry name="ldapver" type="Int"> + <label>LDAP version</label> + <default>3</default> + </entry> + <entry name="ldapsizelimit" type="Int"> + <label>LDAP Size limit</label> + <default>0</default> + </entry> + <entry name="ldaptimelimit" type="Int"> + <label>LDAP Time limit</label> + <default>0</default> + </entry> + <entry name="ldapdn" type="String"> + <label>LDAP Base DN</label> + </entry> + <entry name="ldapfilter" type="String"> + <label>LDAP Filter</label> + </entry> + <entry name="ldapnosec" type="Bool"> + <label>LDAP no encryption</label> + <default>false</default> + </entry> + <entry name="ldaptls" type="Bool"> + <label>LDAP TLS</label> + <default>true</default> + </entry> + <entry name="ldapssl" type="Bool"> + <label>LDAP SSL</label> + <default>false</default> + </entry> + <entry name="ldapanon" type="Bool"> + <label>LDAP Anonymous</label> + <default>false</default> + </entry> + <entry name="ldapsimple" type="Bool"> + <label>LDAP Simple auth</label> + <default>true</default> + </entry> + <entry name="ldapsasl" type="Bool"> + <label>LDAP SASL auth</label> + <default>false</default> + </entry> + <entry name="ldapsaslmech" type="String"> + <label>LDAP SASL mechanism</label> + <default>LOGIN</default> + </entry> + <entry name="ldapuserbase" type="String"> + <label>LDAP User container</label> + <whatsthis>This specifies where to store users' entries relative to the LDAP base DN.</whatsthis> + <default>ou=People</default> + </entry> + <entry name="ldapuserfilter" type="String"> + <label>LDAP User filter</label> + <whatsthis>This specifies the filter used for user entries.</whatsthis> + </entry> + <entry name="ldapgroupbase" type="String"> + <label>LDAP Group container</label> + <whatsthis>This specifies where to store groups' entries relative to the LDAP base DN.</whatsthis> + <default>ou=Group</default> + </entry> + <entry name="ldapgroupfilter" type="String"> + <label>LDAP Group filter</label> + <whatsthis>This specifies the filter used for group entries.</whatsthis> + </entry> + <entry name="ldapuserrdn" type="Enum"> + <label>LDAP User RDN prefix</label> + <whatsthis>This specifies what prefix will used for user entries.</whatsthis> + <choices> + <choice name="uid"/> + <choice name="uidNumber"/> + <choice name="cn"/> + </choices> + <default>uid</default> + </entry> + <entry name="ldapcnfullname" type="Bool"> + <label>Store the user's full name in the cn attribute</label> + <whatsthis>Check this if the user's full name should be stored in the cn (Canonical Name) attribute.</whatsthis> + <default>true</default> + </entry> + <entry name="ldapgecos" type="Bool"> + <label>Update the gecos field</label> + <whatsthis>Check this if the gecos attribute should be updated.</whatsthis> + <default>false</default> + </entry> + <entry name="ldapshadow" type="Bool"> + <label>Manage LDAP shadowAccount objectclass</label> + <whatsthis>Check this if the shadowAccount object should be used in the users' entries. It allows to enforce password change/expiration policies.</whatsthis> + <default>true</default> + </entry> + <entry name="ldapstructural" type="Enum"> + <label>LDAP Structural objectclass</label> + <whatsthis>This option allows to specify the structural objectclass used with users' entries. If you want to use these entries not just for authentication, but for an addressbook, too, then choose inetOrgPerson.</whatsthis> + <choices> + <choice name="account"/> + <choice name="inetOrgPerson"/> + </choices> + <default>account</default> + </entry> + <entry name="ldapgrouprdn" type="Enum"> + <label>LDAP Group RDN prefix</label> + <whatsthis>This specifies what prefix will used for group entries.</whatsthis> + <choices> + <choice name="cn"/> + <choice name="gidNumber"/> + </choices> + <default>cn</default> + </entry> + <entry name="ldappasswordhash" type="Enum"> + <label>LDAP Password hash method</label> + <whatsthis>This specifies the password hashing method. The most secure is SSHA.</whatsthis> + <choices> + <choice name="Clear"/> + <choice name="CRYPT"/> + <choice name="MD5"/> + <choice name="SMD5"/> + <choice name="SHA"/> + <choice name="SSHA"/> + </choices> + <default>SSHA</default> + </entry> + <entry name="ldapsam" type="Bool"> + <label>Enable samba account management</label> + <whatsthis>Check this if you want to use the user/group entries in a Samba domain. KUser will create sambaSamAccount objectclass for each entry which is usable with the ldapsam passdb backend with Samba version greater than 3.0.</whatsthis> + </entry> + <entry name="samdomain" type="String"> + <label>Samba domain name</label> + <whatsthis>This specifies the samba domain name.</whatsthis> + </entry> + <entry name="samdomsid" type="String"> + <label>Samba domain SID</label> + <whatsthis>This specifies the domain Security IDentifier. It is unique in a single domain. You can query the value of the domain SID with 'net getlocalsid domain_name'.</whatsthis> + </entry> + <entry name="samridbase" type="Int"> + <label>Algorithmic RID base</label> + <whatsthis>This value is an offset for the algorithmic mapping from uids and gids to rids. The default (and minimum) value is 1000, it must be even, and the LDAP database and smb.conf must store the same values.</whatsthis> + <default>1000</default> + </entry> + <entry name="samloginscript" type="String"> + <label>Samba login script</label> + <whatsthis>This specifies a name of a login script (in the `Netlogon` share) which will be executed as the user logs in to a Windows machine.</whatsthis> + </entry> + <entry name="samhomedrive" type="String"> + <label>Samba home drive</label> + <whatsthis>Specifies a drive letter where the user's home directory will automatically mapped when he/she logs into a Windows machine.</whatsthis> + </entry> + <entry name="samprofilepath" type="String"> + <label>Samba profile path template</label> + <whatsthis>This specifies the location of the roaming profile of the user. The '%U' macro will be replaced with the actual user name.</whatsthis> + </entry> + <entry name="samhomepath" type="String"> + <label>Samba home path template</label> + <whatsthis>This specifies the location of the home directory of the user. This field is meaningful only for Windows machines. The '%U' macro will be replaced with the actual user name.</whatsthis> + </entry> + <entry name="lanmanhash" type="Bool"> + <label>Store LanManager hashed password</label> + <whatsthis>Store the LanManager hashed password in the sambaLMPassword attribute. Check this if you have older clients (Win9x series and before) on your network.</whatsthis> + <default>false</default> + </entry> + + </group> +</kcfg> diff --git a/kuser/kuserfiles.cpp b/kuser/kuserfiles.cpp new file mode 100644 index 0000000..5c987bc --- /dev/null +++ b/kuser/kuserfiles.cpp @@ -0,0 +1,620 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "globals.h" +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SHADOW +#include <shadow.h> +#endif + +#include <qstring.h> +#include <qdir.h> + +#include "kglobal_.h" +#include "kuserfiles.h" +#include "misc.h" +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include "editDefaults.h" + +KUserFiles::KUserFiles(KUserPrefsBase *cfg) : KUsers( cfg ) +{ + pw_backuped = FALSE; + pn_backuped = FALSE; + s_backuped = FALSE; + + pwd_mode = 0644; + pwd_uid = 0; + pwd_gid = 0; + + sdw_mode = 0600; + sdw_uid = 0; + sdw_gid = 0; + + mUsers.setAutoDelete(TRUE); + + caps = Cap_Passwd; +#ifdef HAVE_SHADOW + if ( !mCfg->shadowsrc().isEmpty() ) caps |= Cap_Shadow; +#endif +#if defined(__FreeBSD__) || defined(__bsdi__) + caps |= Cap_BSD; +#endif + + reload(); +} + +KUserFiles::~KUserFiles() +{ +} + +bool KUserFiles::reload() { + if (!loadpwd()) + return FALSE; + + if (!loadsdw()) + return FALSE; + + return TRUE; +} + +// Load passwd file + +bool KUserFiles::loadpwd() +{ + passwd *p; + KU::KUser *tmpKU = 0; + struct stat st; + QString filename; + QString passwd_filename; + QString nispasswd_filename; + int rc = 0; + int passwd_errno = 0; + int nispasswd_errno = 0; + char processing_file = '\0'; + #define P_PASSWD 0x01 + #define P_NISPASSWD 0x02 + #define MAXFILES 2 + + // Read KUser configuration + + passwd_filename = mCfg->passwdsrc(); + nispasswd_filename = mCfg->nispasswdsrc(); + + // Handle unconfigured environments + + if(passwd_filename.isEmpty() && nispasswd_filename.isEmpty()) { + mCfg->setPasswdsrc( PASSWORD_FILE ); + mCfg->setGroupsrc( GROUP_FILE ); + passwd_filename = mCfg->passwdsrc(); + KMessageBox::error( 0, i18n("KUser sources were not configured.\nLocal passwd source set to %1\nLocal group source set to %2.").arg(mCfg->passwdsrc().arg(mCfg->groupsrc())) ); + } + + if(!passwd_filename.isEmpty()) { + processing_file = processing_file | P_PASSWD; + filename.append(passwd_filename); + } + + // Start reading passwd file(s) + + for(int i = 0; i < MAXFILES; i++) { + rc = stat(QFile::encodeName(filename), &st); + if(rc != 0) { + KMessageBox::error( 0, i18n("Stat call on file %1 failed: %2\nCheck KUser settings.").arg(filename).arg(QString::fromLocal8Bit(strerror(errno))) ); + if( (processing_file & P_PASSWD) != 0 ) { + passwd_errno = errno; + if(!nispasswd_filename.isEmpty()) { + processing_file = processing_file & ~P_PASSWD; + processing_file = processing_file | P_NISPASSWD; + filename.truncate(0); + filename.append(nispasswd_filename); + } + continue; + } + else{ + nispasswd_errno = errno; + break; + } + } + + pwd_mode = st.st_mode & 0666; + pwd_uid = st.st_uid; + pwd_gid = st.st_gid; + + // We are reading our configuration specified passwd file + QString tmp; + +#ifdef HAVE_FGETPWENT + FILE *fpwd = fopen(QFile::encodeName(filename), "r"); + if(fpwd == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(filename) ); + return FALSE; + } + + while ((p = fgetpwent(fpwd)) != NULL) { +#else + setpwent(); //This should be enough for BSDs + while ((p = getpwent()) != NULL) { +#endif + tmpKU = new KU::KUser(); + tmpKU->setCaps( KU::KUser::Cap_POSIX ); + tmpKU->setUID(p->pw_uid); + tmpKU->setGID(p->pw_gid); + tmpKU->setName(QString::fromLocal8Bit(p->pw_name)); + tmp = QString::fromLocal8Bit( p->pw_passwd ); + if ( tmp != "x" && tmp != "*" && !tmp.startsWith("!") ) + tmpKU->setDisabled( false ); + else + tmpKU->setDisabled( true ); + if ( tmp.startsWith("!") ) tmp.remove(0, 1); + tmpKU->setPwd( tmp ); + tmpKU->setHomeDir(QString::fromLocal8Bit(p->pw_dir)); + tmpKU->setShell(QString::fromLocal8Bit(p->pw_shell)); +#if defined(__FreeBSD__) || defined(__bsdi__) + tmpKU->setClass(QString::fromLatin1(p->pw_class)); + tmpKU->setLastChange(p->pw_change); + tmpKU->setExpire(p->pw_expire); +#endif + + if ((p->pw_gecos != 0) && (p->pw_gecos[0] != 0)) + fillGecos(tmpKU, p->pw_gecos); + mUsers.append(tmpKU); + } + + // End reading passwd_filename + +#ifdef HAVE_FGETPWENT + fclose(fpwd); +#else + endpwent(); +#endif + if((!nispasswd_filename.isEmpty()) && (nispasswd_filename != passwd_filename)) { + processing_file = processing_file & ~P_PASSWD; + processing_file = processing_file | P_NISPASSWD; + filename.truncate(0); + filename.append(nispasswd_filename); + } + else + break; + + } // end of processing files, for loop + + if( (passwd_errno == 0) && (nispasswd_errno == 0) ) + return (TRUE); + if( (passwd_errno != 0) && (nispasswd_errno != 0) ) + return (FALSE); + else + return(TRUE); +} + +// Load shadow passwords + +bool KUserFiles::loadsdw() +{ +#ifdef HAVE_SHADOW + QString shadow_file,tmp; + struct spwd *spw; + KU::KUser *up = NULL; + struct stat st; + + shadow_file = mCfg->shadowsrc(); + if ( shadow_file.isEmpty() ) + return TRUE; + + stat( QFile::encodeName(shadow_file), &st); + sdw_mode = st.st_mode & 0666; + sdw_uid = st.st_uid; + sdw_gid = st.st_gid; + +#ifdef HAVE_FGETSPENT + FILE *f; + kdDebug() << "open shadow file: " << shadow_file << endl; + if ((f = fopen( QFile::encodeName(shadow_file), "r")) == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(shadow_file) ); + caps &= ~Cap_Shadow; + return TRUE; + } + while ((spw = fgetspent( f ))) { // read a shadow password structure +#else + setspent(); + while ((spw = getspent())) { // read a shadow password structure +#endif + + kdDebug() << "shadow entry: " << spw->sp_namp << endl; + if ((up = lookup(QString::fromLocal8Bit(spw->sp_namp))) == NULL) { + KMessageBox::error( 0, i18n("No /etc/passwd entry for %1.\nEntry will be removed at the next `Save'-operation.").arg(QString::fromLocal8Bit(spw->sp_namp)) ); + continue; + } + + tmp = QString::fromLocal8Bit( spw->sp_pwdp ); + if ( tmp.startsWith("!!") || tmp == "*" ) { + up->setDisabled( true ); + tmp.remove( 0, 2 ); + } else + up->setDisabled( false ); + + up->setSPwd( tmp ); // cp the encrypted pwd + up->setLastChange( daysToTime( spw->sp_lstchg ) ); + up->setMin(spw->sp_min); + up->setMax(spw->sp_max); +#ifndef _SCO_DS + up->setWarn(spw->sp_warn); + up->setInactive(spw->sp_inact); + up->setExpire( daysToTime( spw->sp_expire ) ); + up->setFlag(spw->sp_flag); +#endif + } + +#ifdef HAVE_FGETSPENT + fclose(f); +#else + endspent(); +#endif + +#endif // HAVE_SHADOW + return TRUE; +} + +// Save password file + +#define escstr(a,b) tmp2 = user->a(); \ + tmp2.replace(':',"_"); \ + tmp2.replace(',',"_"); \ + user->b( tmp2 ); + + +bool KUserFiles::savepwd() +{ + FILE *passwd_fd = NULL; + FILE *nispasswd_fd = NULL; + uid_t minuid = 0; + int nis_users_written = 0; + uid_t tmp_uid = 0; + QString s; + QString s1; + QString tmp, tmp2; + QString passwd_filename; + QString nispasswd_filename; + + + char errors_found = '\0'; + #define NOMINUID 0x01 + #define NONISPASSWD 0x02 + + // Read KUser configuration info + + passwd_filename = mCfg->passwdsrc(); + nispasswd_filename = mCfg->nispasswdsrc(); + QString new_passwd_filename = + passwd_filename + QString::fromLatin1(KU_CREATE_EXT); + QString new_nispasswd_filename = + nispasswd_filename+QString::fromLatin1(KU_CREATE_EXT); + + if( nispasswd_filename != passwd_filename ) { + minuid = mCfg->nisminuid(); + } + + // Backup file(s) + + if(!passwd_filename.isEmpty()) { + if (!pw_backuped) { + if (!backup(passwd_filename)) return FALSE; + pw_backuped = TRUE; + } + } + if(!nispasswd_filename.isEmpty() && + (nispasswd_filename != passwd_filename)) { + if (!pn_backuped) { + if (!backup(nispasswd_filename)) return FALSE; + pn_backuped = TRUE; + } + } + + // Open file(s) + + if(!passwd_filename.isEmpty()) { + if ((passwd_fd = + fopen(QFile::encodeName(new_passwd_filename),"w")) == NULL) + KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(passwd_filename) ); + } + + if(!nispasswd_filename.isEmpty() && (nispasswd_filename != passwd_filename)){ + if ((nispasswd_fd = + fopen(QFile::encodeName(new_nispasswd_filename),"w")) == NULL) + KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(nispasswd_filename) ); + } + + QPtrListIterator<KU::KUser> it( mUsers ); + KU::KUser *user; + bool addok = false; + user = (*it); + while (true) { + if ( user == 0 ) { + if ( addok ) break; + it = QPtrListIterator<KU::KUser> ( mAdd ); + user = (*it); + addok = true; + if ( user == 0 ) break; + }; + if ( mDel.containsRef( user ) ) { + ++it; + user = (*it); + continue; + } + if ( mMod.contains( user ) ) user = &( mMod[ user ] ); + + tmp_uid = user->getUID(); + if ( caps & Cap_Shadow ) + tmp = "x"; + else { + tmp = user->getPwd(); + if ( user->getDisabled() && tmp != "x" && tmp != "*" ) + tmp = "!" + tmp; + } + + escstr( getName, setName ); + escstr( getHomeDir, setHomeDir ); + escstr( getShell, setShell ); + escstr( getName, setName ); + escstr( getFullName, setFullName ); +#if defined(__FreeBSD__) || defined(__bsdi__) + escstr( getClass, setClass ); + escstr( getOffice, setOffice ); + escstr( getWorkPhone, setWorkPhone ); + escstr( getHomePhone, setHomePhone ); + s = + user->getName() + ":" + + tmp + ":" + + QString::number( user->getUID() ) + ":" + + QString::number( user->getGID() ) + ":" + + user->getClass() + ":" + + QString::number( user->getLastChange() ) + ":" + + QString::number( user->getExpire() ) + ":"; + + s1 = + user->getFullName() + "," + + user->getOffice() + "," + + user->getWorkPhone() + "," + + user->getHomePhone(); +#else + escstr( getOffice1, setOffice1 ); + escstr( getOffice2, setOffice2 ); + escstr( getAddress, setAddress ); + s = + user->getName() + ":" + + tmp + ":" + + QString::number( user->getUID() ) + ":" + + QString::number( user->getGID() ) + ":"; + + s1 = + user->getFullName() + "," + + user->getOffice1() + "," + + user->getOffice2() + "," + + user->getAddress(); + +#endif + for (int j=(s1.length()-1); j>=0; j--) { + if (s1[j] != ',') + break; + s1.truncate(j); + } + + s += s1 + ":" + + user->getHomeDir() + ":" + + user->getShell() + "\n"; + + if( (nispasswd_fd != 0) && (minuid != 0) ) { + if (minuid <= tmp_uid) { + fputs(s.local8Bit().data(), nispasswd_fd); + nis_users_written++; + ++it; + user = (*it); + continue; + } + } + + if( (nispasswd_fd != 0) && (minuid == 0) ) { + errors_found = errors_found | NOMINUID; + } + + if( (nispasswd_fd == 0) && (minuid != 0) ) { + errors_found = errors_found | NONISPASSWD; + } + kdDebug() << s << endl; + fputs(s.local8Bit().data(), passwd_fd); + + ++it; + user = (*it); + } + + if(passwd_fd) { + fclose(passwd_fd); + chmod(QFile::encodeName(new_passwd_filename), pwd_mode); + chown(QFile::encodeName(new_passwd_filename), pwd_uid, pwd_gid); + rename(QFile::encodeName(new_passwd_filename), + QFile::encodeName(passwd_filename)); + } + + if(nispasswd_fd) { + fclose(nispasswd_fd); + chmod(QFile::encodeName(new_nispasswd_filename), pwd_mode); + chown(QFile::encodeName(new_nispasswd_filename), pwd_uid, pwd_gid); + rename(QFile::encodeName(new_nispasswd_filename), + QFile::encodeName(nispasswd_filename)); + } + + if( (errors_found & NOMINUID) != 0 ) { + KMessageBox::error( 0, i18n("Unable to process NIS passwd file without a minimum UID specified.\nPlease update KUser settings (Files).") ); + } + + if( (errors_found & NONISPASSWD) != 0 ) { + KMessageBox::error( 0, i18n("Specifying NIS minimum UID requires NIS file(s).\nPlease update KUser settings (Files).") ); + } + + // need to run a utility program to build /etc/passwd, /etc/pwd.db + // and /etc/spwd.db from /etc/master.passwd +#if defined(__FreeBSD__) || defined(__bsdi__) + if (system(PWMKDB) != 0) { + KMessageBox::error( 0, i18n("Unable to build password database.") ); + return FALSE; + } +#else + if( (nis_users_written > 0) || (nispasswd_filename == passwd_filename) ) { + if (system(PWMKDB) != 0) { + KMessageBox::error( 0, i18n("Unable to build password databases.") ); + return FALSE; + } + } +#endif + + return TRUE; +} + +#undef escstr + +// Save shadow passwords file + +bool KUserFiles::savesdw() +{ +#ifdef HAVE_SHADOW + bool addok = false; + QString tmp; + FILE *f; + struct spwd *spwp; + struct spwd s; + KU::KUser *up; + QString shadow_file = mCfg->shadowsrc(); + QString new_shadow_file = shadow_file+QString::fromLatin1(KU_CREATE_EXT); + + if ( shadow_file.isEmpty() ) + return TRUE; + + if (!s_backuped) { + if (!backup(shadow_file)) return FALSE; + s_backuped = TRUE; + } + + if ((f = fopen(QFile::encodeName(new_shadow_file), "w")) == NULL) { + KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_shadow_file) ); + return FALSE; + } + + s.sp_namp = (char *)malloc(200); + s.sp_pwdp = (char *)malloc(200); + + QPtrListIterator<KU::KUser> it( mUsers ); + up = (*it); + while (true) { + + if ( up == 0 ) { + if ( addok ) break; + it = QPtrListIterator<KU::KUser> ( mAdd ); + up = (*it); + addok = true; + if ( up == 0 ) break; + }; + + if ( mDel.containsRef( up ) ) { + ++it; + up = (*it); + continue; + } + if ( mMod.contains( up ) ) up = &( mMod[ up ] ); + + strncpy( s.sp_namp, up->getName().local8Bit(), 200 ); + if ( up->getDisabled() ) + strncpy( s.sp_pwdp, QString("!!" + up->getSPwd()).local8Bit(), 200 ); + else + strncpy( s.sp_pwdp, up->getSPwd().local8Bit(), 200 ); + + s.sp_lstchg = timeToDays( up->getLastChange() ); + s.sp_min = up->getMin(); + s.sp_max = up->getMax(); +#ifndef _SCO_DS + s.sp_warn = up->getWarn(); + s.sp_inact = up->getInactive(); + s.sp_expire = timeToDays( up->getExpire() ); + s.sp_flag = up->getFlag(); +#endif + spwp = &s; + putspent(spwp, f); + + ++it; + up = (*it); + } + fclose(f); + + chmod(QFile::encodeName(new_shadow_file), sdw_mode); + chown(QFile::encodeName(new_shadow_file), sdw_uid, sdw_gid); + rename(QFile::encodeName(new_shadow_file), + QFile::encodeName(shadow_file)); + + free(s.sp_namp); + free(s.sp_pwdp); +#endif // HAVE_SHADOW + return TRUE; +} + + +void KUserFiles::createPassword( KU::KUser *user, const QString &password ) +{ + if ( caps & Cap_Shadow ) { + user->setSPwd( encryptPass( password, mCfg->md5shadow() ) ); + user->setPwd( QString::fromLatin1("x") ); + } else + user->setPwd( encryptPass( password, false ) ); +} + +bool KUserFiles::dbcommit() +{ + bool ret; + mode_t mode; + + mAddSucc.clear(); + mDelSucc.clear(); + mModSucc.clear(); + if ( mDel.isEmpty() && mAdd.isEmpty() && mMod.isEmpty() ) + return true; + + mode = umask(0077); + ret = savepwd(); + if ( ret && ( caps & Cap_Shadow ) ) ret = savesdw(); + umask( mode ); + if ( !ret ) return false; + + mDelSucc = mDel; + mAddSucc = mAdd; + mModSucc = mMod; + mDel.clear(); + mAdd.clear(); + mMod.clear(); + return TRUE; +} diff --git a/kuser/kuserfiles.h b/kuser/kuserfiles.h new file mode 100644 index 0000000..bb19c45 --- /dev/null +++ b/kuser/kuserfiles.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KUSERFILES_H_ +#define _KUSERFILES_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qptrlist.h> + +#include "kuser.h" + +class KUserFiles : public KU::KUsers { +public: + KUserFiles(KUserPrefsBase *cfg); + virtual ~KUserFiles(); + + virtual bool dbcommit(); + virtual bool reload(); + virtual void createPassword( KU::KUser *user, const QString &password ); + +private: + bool pw_backuped; + bool pn_backuped; + bool s_backuped; + + mode_t pwd_mode; + mode_t sdw_mode; + + uid_t pwd_uid; + gid_t pwd_gid; + + uid_t sdw_uid; + gid_t sdw_gid; + + bool loadpwd(); + bool loadsdw(); + + bool savepwd(); + bool savesdw(); +}; +#endif // _KUSERFILES_H_ + diff --git a/kuser/kuserldap.cpp b/kuser/kuserldap.cpp new file mode 100644 index 0000000..9eb6afe --- /dev/null +++ b/kuser/kuserldap.cpp @@ -0,0 +1,660 @@ +/* + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * + * This mProgram is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qstring.h> + +#include <kdebug.h> +#include <kmdcodec.h> +#include <kmessagebox.h> +#include <kio/kntlm.h> + +#include "kglobal_.h" +#include "kuserldap.h" +#include "misc.h" +#include "sha1.h" + +#include "kuserldap.moc" + +KUserLDAP::KUserLDAP(KUserPrefsBase *cfg) : KU::KUsers( cfg ) +{ + schemaversion = 0; + + if ( mCfg->ldapssl() ) + mUrl.setProtocol("ldaps"); + else + mUrl.setProtocol("ldap"); + + mUrl.setHost( mCfg->ldaphost() ); + mUrl.setPort( mCfg->ldapport() ); + mUrl.setDn( mCfg->ldapuserbase() + "," + mCfg->ldapdn() ); + if ( !mCfg->ldapanon() ) { + mUrl.setUser( mCfg->ldapuser() ); + mUrl.setPass( mCfg->ldappassword() ); + } + mUrl.setFilter( mCfg->ldapuserfilter() ); + + if ( mCfg->ldaptls() ) mUrl.setExtension( "x-tls", "" ); + if ( mCfg->ldapsasl() ) { + mUrl.setExtension( "x-sasl", "" ); + mUrl.setExtension( "x-mech", mCfg->ldapsaslmech() ); + } + + mUrl.setScope(KABC::LDAPUrl::One); + mUrl.setExtension("x-dir","base"); + + caps = Cap_Passwd | Cap_Disable_POSIX; + if ( mCfg->ldapshadow() ) caps |= Cap_Shadow; + if ( mCfg->ldapstructural() == + KUserPrefsBase::EnumLdapstructural::inetOrgPerson ) + caps |= Cap_InetOrg; + + if ( mCfg->ldapsam() ) { + caps |= Cap_Samba; + domsid = mCfg->samdomsid(); + } + + reload(); +} + +KUserLDAP::~KUserLDAP() +{ + mUsers.clear(); +} + +void KUserLDAP::result( KIO::Job *job ) +{ + delete mProg; + mCancel = false; + if ( job->error() ) { + QString errstr = job->errorString(); + if ( !errstr.isEmpty() ) { + if ( ldif.isEmpty() ) + KMessageBox::error( 0, errstr ); + else + KMessageBox::detailedError( 0, errstr, QString::fromUtf8( ldif, ldif.size()-1 ) ); + } + mOk = false; + } else { + mOk = true; + } +} + +void KUserLDAP::data( KIO::Job *, const QByteArray& data ) +{ + if ( data.size() ) { + mParser.setLDIF( data ); + } else { + mParser.endLDIF(); + } + + KABC::LDIF::ParseVal ret; + QString name, val; + QByteArray value; + do { + ret = mParser.nextItem(); + switch ( ret ) { + case KABC::LDIF::Item: + name = mParser.attr().lower(); + value = mParser.val(); + val = QString::fromUtf8( value, value.size() ); + if ( name == "objectclass" ) { + if ( val.lower() == "posixaccount" ) + mUser->setCaps( mUser->getCaps() | KU::KUser::Cap_POSIX ); + else if ( val.lower() == "sambasamaccount" ) + mUser->setCaps( mUser->getCaps() | KU::KUser::Cap_Samba ); + else if ( val.lower() != "inetorgperson" && + val.lower() != "shadowaccount" && + val.lower() != "account" ) + mOc.append( val ); + + } else if ( name == "uidnumber" ) + mUser->setUID( val.toLong() ); + else if ( name == "gidnumber" ) + mUser->setGID( val.toLong() ); + else if ( name == "uid" || name == "userid" ) + mUser->setName( val ); + else if ( name == "sn" ) + mUser->setSurname( val ); + else if ( name == "mail" ) + mUser->setEmail( val ); + else if ( name == "homedirectory" ) + mUser->setHomeDir( val ); + else if ( name == "loginshell" ) + mUser->setShell( val ); + else if ( name == "postaladdress" ) + mUser->setAddress( val ); + else if ( name == "telephonenumber" ) { + if ( mUser->getOffice1().isEmpty() ) + mUser->setOffice1( val ); + else + mUser->setOffice2( val ); + } else if ( name == "gecos" ) { + QString name, f1, f2, f3; + parseGecos( QCString( value.data(), value.size()+1 ), name, f1, f2, f3 ); + if ( mUser->getFullName().isEmpty() ) mUser->setFullName( val ); + if ( mUser->getOffice1().isEmpty() ) mUser->setOffice1( f1 ); + if ( mUser->getOffice2().isEmpty() ) mUser->setOffice2( f1 ); + if ( mUser->getAddress().isEmpty() ) mUser->setAddress( f1 ); + } else if ( name == "cn" ) { + if ( mUser->getFullName().isEmpty() || mCfg->ldapcnfullname() ) + mUser->setFullName( val ); + if ( mUser->getName().isEmpty() ) + mUser->setName( val ); + } else if ( name == "displayname" ) { + mUser->setFullName( val ); + } else if ( name == "userpassword" ) { + if ( !val.isEmpty() ) mUser->setDisabled( false ); + mUser->setPwd( val ); + } else if ( name == "shadowlastchange" ) { + if ( mUser->getLastChange() == 0 ) //sambapwdlastset is more precise + mUser->setLastChange( daysToTime( val.toLong() ) ); + } else if ( name == "shadowmin" ) + mUser->setMin( val.toInt() ); + else if ( name == "shadowmax" ) + mUser->setMax( val.toLong() ); + else if ( name == "shadowwarning" ) + mUser->setWarn( val.toLong() ); + else if ( name == "shadowinactive" ) + mUser->setInactive( val.toLong() ); + else if ( name == "shadowexpire" ) + mUser->setExpire( val.toLong() ); + else if ( name == "shadowflag" ) + mUser->setFlag( val.toLong() ); + else if ( name == "sambaacctflags" ) { + if ( !val.contains( 'D' ) ) mUser->setDisabled( false ); + } else if ( name == "sambasid" ) + mUser->setSID( val ); + else if ( name == "sambaprimarygroupsid" ) + mUser->setPGSID( val ); + else if ( name == "sambalmpassword" ) + mUser->setLMPwd( val ); + else if ( name == "sambantpassword" ) + mUser->setNTPwd( val ); + else if ( name == "sambahomepath" ) + mUser->setHomePath( val ); + else if ( name == "sambahomedrive" ) + mUser->setHomeDrive( val ); + else if ( name == "sambalogonscript" ) + mUser->setLoginScript( val ); + else if ( name == "sambaprofilepath" ) + mUser->setProfilePath( val ); + else if ( name == "sambauserworkstations" ) + mUser->setWorkstations( val ); + else if ( name == "sambadomainname" ) + mUser->setDomain( val ); + else if ( name == "sambapwdlastset" ) + mUser->setLastChange( val.toLong() ); + //these new attributes introduced around samba 3.0.6 + else if ( name == "sambapasswordhistory" || name == "sambalogonhours" ) + schemaversion = 1; + break; + case KABC::LDIF::EndEntry: { + KU::KUser emptyUser, *newUser; + kdDebug() << "new user: " << mUser->getName() << endl; + newUser = new KU::KUser( mUser ); + mUsers.append( newUser ); + if ( !mOc.isEmpty() ) { + mObjectClasses.insert( newUser, mOc ); + kdDebug() << "user: " << newUser->getName() << " other objectclasses: " << mOc.join(",") << endl; + } + mOc.clear(); + mUser->copy( &emptyUser ); + mUser->setDisabled( true ); + + if ( ( mUsers.count() & 7 ) == 7 ) { + mProg->progressBar()->advance( mAdv ); + if ( mProg->progressBar()->progress() == 0 ) mAdv = 1; + if ( mProg->progressBar()->progress() == mProg->progressBar()->totalSteps()-1 ) mAdv = -1; + } + + break; + } + default: + break; + } + } while ( ret != KABC::LDIF::MoreData ); +} + +bool KUserLDAP::reload() +{ + kdDebug() << "kuserldap::reload()" << endl; + mObjectClasses.clear(); + mOc.clear(); + mUser = new KU::KUser(); + mUser->setPwd( "" ); + mUser->setSPwd( "" ); + mParser.startParsing(); + mCancel = true; + mProg = new KProgressDialog( 0, "", "", i18n("Loading Users From LDAP"), true ); + mProg->setAutoClose( false ); + mProg->progressBar()->setFormat(""); + mProg->progressBar()->setTotalSteps( 100 ); + mAdv = 1; + ldif = ""; + + KIO::Job *job = KIO::get( mUrl, true, false ); + connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ), + this, SLOT( data( KIO::Job*, const QByteArray& ) ) ); + connect( job, SIGNAL( result( KIO::Job* ) ), + this, SLOT( result( KIO::Job* ) ) ); +// job->addMetaData( "SERVER_CTRL0", "1.2.840.113556.1.4.473 true: uidNumber"); + mProg->exec(); + if ( mCancel ) job->kill(); + delete mUser; + return( mOk ); +} + +QString KUserLDAP::getRDN(KU::KUser *user) +{ + switch ( mCfg->ldapuserrdn() ) { + case KUserPrefsBase::EnumLdapuserrdn::uid: + return "uid=" + user->getName(); + case KUserPrefsBase::EnumLdapuserrdn::uidNumber: + return "uidNumber=" + QString::number( user->getUID() ); + case KUserPrefsBase::EnumLdapuserrdn::cn: { + QString cn = mCfg->ldapcnfullname() ? user->getFullName() : user->getName(); + if ( cn.isEmpty() ) cn = user->getName(); + return "cn=" + cn; + } + } + return ""; +} + +void KUserLDAP::createPassword( KU::KUser *user, const QString &password ) +{ + switch ( mCfg->ldappasswordhash() ) { + case KUserPrefsBase::EnumLdappasswordhash::Clear: + user->setPwd( password ); + break; + case KUserPrefsBase::EnumLdappasswordhash::CRYPT: + user->setPwd( "{CRYPT}" + encryptPass( password, false ) ); + break; + case KUserPrefsBase::EnumLdappasswordhash::MD5: { + KMD5 md5( password.utf8() ); + user->setPwd( "{MD5}" + md5.base64Digest() ); + break; + } + case KUserPrefsBase::EnumLdappasswordhash::SMD5: { + QCString salt = genSalt( 4 ); + QCString pwd = password.utf8() + salt; + KMD5::Digest digest; + QByteArray hash(20); + + KMD5 md5( pwd ); + md5.rawDigest( digest ); + memcpy( hash.data(), digest, 16 ); + memcpy( &(hash.data()[16]), salt.data(), 4 ); + user->setPwd( "{SMD5}" + KCodecs::base64Encode( hash ) ); + break; + } + case KUserPrefsBase::EnumLdappasswordhash::SHA: { + struct sha1_ctx ctx; + QByteArray hash(20); + + sha1_init( &ctx ); + sha1_update( &ctx, (const Q_UINT8*) password.utf8().data(), + password.utf8().length() ); + sha1_final( &ctx, (Q_UINT8*) hash.data() ); + user->setPwd( "{SHA}" + KCodecs::base64Encode( ( hash ) ) ); + break; + } + case KUserPrefsBase::EnumLdappasswordhash::SSHA: { + struct sha1_ctx ctx; + QByteArray hash(24); + QCString salt = genSalt( 4 ); + QCString pwd = password.utf8() + salt; + + sha1_init( &ctx ); + sha1_update( &ctx, (const Q_UINT8*) pwd.data(), pwd.length() ); + sha1_final( &ctx, (Q_UINT8*) hash.data() ); + memcpy( &(hash.data()[ 20 ]), salt.data(), 4 ); + user->setPwd( "{SSHA}" + KCodecs::base64Encode( ( hash ) ) ); + break; + } + } + + if ( caps & Cap_Samba ) { + Q_UINT8 hex[33]; + + QByteArray ntlmhash; + ntlmhash = KNTLM::ntlmHash( password ); + unsigned char *hash = (unsigned char*) ntlmhash.data(); + + snprintf( (char*) &hex, 33, + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], + hash[6], hash[7], hash[8], hash[9], hash[10], hash[11], + hash[12], hash[13], hash[14], hash[15]); + + user->setNTPwd( QString::fromLatin1( (const char*) &hex, 32 ) ); + + if ( mCfg->lanmanhash() ) { + + QByteArray lmhash; + lmhash = KNTLM::lmHash( password ); + unsigned char *hash = (unsigned char*) lmhash.data(); + snprintf( (char*) &hex, 33, + "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], + hash[6], hash[7], hash[8], hash[9], hash[10], hash[11], + hash[12], hash[13], hash[14], hash[15]); + + user->setLMPwd( QString::fromLatin1( (const char*) &hex, 32 ) ); + } else { + user->setLMPwd( "" ); + } + } +} + +void KUserLDAP::getLDIF( KU::KUser *user, bool mod ) +{ + QString gecos, cn, pwd, samflags; + ldif.resize( 0 ); + + pwd = user->getPwd(); + if ( user->getDisabled() ) pwd = ""; + + cn = mCfg->ldapcnfullname() ? user->getFullName() : user->getName(); + if ( cn.isEmpty() ) cn = user->getName(); + + gecos = QString::fromLatin1("%1,%2,%3,%4") + .arg(user->getFullName()) + .arg(user->getOffice1()) + .arg(user->getOffice2()) + .arg(user->getAddress()); + + samflags = "[U"; + samflags += user->getDisabled() ? 'D' : ' '; + samflags += " ]"; + + ldif = ""; + + if ( mod ) { + QString oldrdn = getRDN( mUser ); + QString newrdn = getRDN( user ); + + if ( oldrdn != newrdn ) { + ldif = "dn: " + oldrdn.utf8() + "," + mUrl.dn().utf8() + "\n" + + "changetype: modrdn\n" + + "newrdn: " + newrdn.utf8() + "\n" + + "deleteoldrdn: 1\n\n"; + } + } + + ldif += "dn: " + getRDN( user ).utf8() + "," + mUrl.dn().utf8() + "\n"; + if ( mod ) { + ldif += "changetype: modify\n"; + ldif += "replace: objectClass\n"; + } + + if ( caps & Cap_InetOrg ) + ldif += "objectClass: inetOrgPerson\n"; + else + ldif += "objectClass: account\n"; + + if ( user->getCaps() & KU::KUser::Cap_POSIX ) { + ldif += "objectClass: posixAccount\n"; + } + if ( ( caps & Cap_Shadow ) && ( user->getCaps() & KU::KUser::Cap_POSIX ) ) { + ldif += "objectClass: shadowAccount\n"; + } + if ( ( caps & Cap_Samba ) && ( user->getCaps() & KU::KUser::Cap_Samba ) ) { + ldif += "objectClass: sambaSamAccount\n"; + } + if ( mod && mObjectClasses.contains( mUser ) ) { + QStringList ocs = mObjectClasses[ mUser ]; + kdDebug() << user->getName() << " has additional objectclasses: " << ocs.join(",") << endl; + QValueListIterator<QString> it; + for ( it = ocs.begin(); it != ocs.end(); ++it ) { + ldif += "objectClass: "; + ldif += (*it).utf8(); + ldif += "\n"; + } + } + + if ( mod ) ldif += "-\nreplace: cn\n"; + ldif += KABC::LDIF::assembleLine( "cn", cn )+"\n"; + if ( caps & Cap_InetOrg ) { + if ( mod ) ldif += "-\nreplace: uid\n"; + ldif += KABC::LDIF::assembleLine( "uid", user->getName() ) + "\n"; + } else { + if ( mod ) ldif += "-\nreplace: userid\n"; + ldif += KABC::LDIF::assembleLine( "userid", user->getName() ) + "\n"; + } + if ( mod ) ldif += "-\n"; + + if ( ( user->getCaps() & KU::KUser::Cap_POSIX ) || ( caps & Cap_InetOrg ) ) { + if ( mod ) ldif += "replace: userpassword\n"; + ldif += KABC::LDIF::assembleLine( "userpassword", pwd )+"\n"; + if ( mod ) ldif += "-\n"; + } + + if ( user->getCaps() & KU::KUser::Cap_POSIX ) { + if ( mod ) ldif += "replace: uidnumber\n"; + ldif += KABC::LDIF::assembleLine( "uidnumber", + QString::number( user->getUID() ) )+"\n"; + if ( mod ) ldif += "-\nreplace: gidnumber\n"; + ldif += KABC::LDIF::assembleLine( "gidnumber", + QString::number( user->getGID() ) )+"\n"; + if ( mod ) ldif += "-\nreplace: gecos\n"; + ldif += KABC::LDIF::assembleLine( "gecos", !mCfg->ldapgecos() ? QCString() : + QCString( gecos.latin1() ) )+"\n"; + if ( mod ) ldif += "-\nreplace: homedirectory\n"; + ldif += KABC::LDIF::assembleLine( "homedirectory", + user->getHomeDir() )+"\n"; + if ( mod ) ldif += "-\nreplace: loginshell\n"; + ldif += KABC::LDIF::assembleLine( "loginshell", + user->getShell() )+"\n"; + if ( mod ) ldif += "-\n"; + } else { + if ( mod ) { + ldif += "replace: uidnumber\n"; + ldif += "-\nreplace: gidnumber\n"; + ldif += "-\nreplace: homedirectory\n"; + ldif += "-\nreplace: loginshell\n"; + ldif += "-\nreplace: gecos\n"; + ldif += "-\n"; + } + } + + if ( caps & Cap_InetOrg ) { + if ( mod ) ldif += "replace: sn\n"; + ldif += KABC::LDIF::assembleLine( "sn", user->getSurname() ) + "\n"; + if ( mod ) ldif += "-\nreplace: mail\n"; + ldif += KABC::LDIF::assembleLine( "mail", user->getEmail() ) + "\n"; + if ( mod ) ldif += "-\nreplace: displayName\n"; + ldif += KABC::LDIF::assembleLine( "displayname", user->getFullName() ) + "\n"; + if ( mod ) ldif += "-\nreplace: postaladdress\n"; + ldif += KABC::LDIF::assembleLine( "postaladdress", user->getAddress() ) + "\n"; + if ( mod ) ldif += "-\nreplace: telephoneNumber\n"; + ldif += KABC::LDIF::assembleLine( "telephoneNumber", user->getOffice1() ) + "\n"; + ldif += KABC::LDIF::assembleLine( "telephoneNumber", user->getOffice2() ) + "\n"; + if ( mod ) ldif += "-\n"; + } + + if ( caps & Cap_Samba ) { + if ( user->getCaps() & KU::KUser::Cap_Samba ) { + if ( mod ) ldif += "replace: sambadomainname\n"; + ldif += KABC::LDIF::assembleLine( "sambadomainname", user->getDomain() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambauserworkstations\n"; + ldif += KABC::LDIF::assembleLine( "sambauserworkstations", user->getWorkstations() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambahomepath\n"; + ldif += KABC::LDIF::assembleLine( "sambahomepath", user->getHomePath() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambahomedrive\n"; + ldif += KABC::LDIF::assembleLine( "sambahomedrive", user->getHomeDrive() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambalogonscript\n"; + ldif += KABC::LDIF::assembleLine( "sambalogonscript", user->getLoginScript() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambaprofilepath\n"; + ldif += KABC::LDIF::assembleLine( "sambaprofilepath", user->getProfilePath() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambalmpassword\n"; + ldif += KABC::LDIF::assembleLine( "sambalmpassword", user->getLMPwd() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambantpassword\n"; + ldif += KABC::LDIF::assembleLine( "sambantpassword", user->getNTPwd() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambasid\n"; + ldif += KABC::LDIF::assembleLine( "sambasid", user->getSID().getSID() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambaacctflags\n"; + ldif += KABC::LDIF::assembleLine( "sambaacctflags", samflags ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambaprimarygroupsid\n"; + ldif += KABC::LDIF::assembleLine( "sambaprimarygroupsid", + user->getPGSID().getSID() ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambapwdlastset\n"; + ldif += KABC::LDIF::assembleLine( "sambapwdlastset", + QString::number( user->getLastChange() ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: sambakickofftime\n"; + if ( user->getExpire() != -1 ) ldif += + KABC::LDIF::assembleLine( "sambakickofftime", + QString::number( user->getExpire() ) ) + "\n"; + if ( mod ) ldif += "-\n"; + } else { + if ( mod ) { + ldif += "replace: sambahomepath\n"; + ldif += "-\nreplace: sambahomedrive\n"; + ldif += "-\nreplace: sambalogonscript\n"; + ldif += "-\nreplace: sambaprofilepath\n"; + ldif += "-\nreplace: sambalmpassword\n"; + ldif += "-\nreplace: sambantpassword\n"; + ldif += "-\nreplace: sambasid\n"; + ldif += "-\nreplace: sambaacctflags\n"; + ldif += "-\nreplace: sambaprimarygroupsid\n"; + ldif += "-\nreplace: sambapwdlastset\n"; + ldif += "-\nreplace: sambakickofftime\n"; + ldif += "-\nreplace: sambalogontime\n"; + ldif += "-\nreplace: sambalogofftime\n"; + ldif += "-\nreplace: sambapwdcanchange\n"; + ldif += "-\nreplace: sambapwdmustchange\n"; + ldif += "-\nreplace: sambauserworkstations\n"; + ldif += "-\nreplace: sambadomainname\n"; + ldif += "-\nreplace: sambamungeddial\n"; + ldif += "-\nreplace: sambabadpasswordcount\n"; + ldif += "-\nreplace: sambabadpasswordtime\n"; + ldif += "-\nreplace: sambadomainname\n"; + if ( schemaversion > 0 ) { + ldif += "-\nreplace: sambapasswordhistory\n"; + ldif += "-\nreplace: sambalogonhours\n"; + } + ldif += "-\n"; + } + } + } + + if ( caps & Cap_Shadow ) { + if ( user->getCaps() & KU::KUser::Cap_POSIX ) { + if ( mod ) ldif += "replace: shadowlastchange\n"; //sambapwdlastset + ldif += KABC::LDIF::assembleLine( "shadowlastchange", + QString::number( timeToDays( user->getLastChange() ) ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: shadowmin\n"; //sambaPwdCanChange + ldif += KABC::LDIF::assembleLine( "shadowmin", + QString::number( user->getMin() ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: shadowmax\n"; //sambaPwdMustChange + ldif += KABC::LDIF::assembleLine( "shadowmax", + QString::number( user->getMax() ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: shadowwarning\n"; + ldif += KABC::LDIF::assembleLine( "shadowwarning", + QString::number( user->getWarn() ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: shadowinactive\n"; + ldif += KABC::LDIF::assembleLine( "shadowinactive", + QString::number( user->getInactive() ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: shadowexpire\n"; //sambaKickoffTime + ldif += KABC::LDIF::assembleLine( "shadowexpire", + QString::number( timeToDays( user->getExpire() ) ) ) + "\n"; + if ( mod ) ldif += "-\nreplace: shadowflag\n"; + ldif += KABC::LDIF::assembleLine( "shadowflag", + QString::number( user->getFlag() ) ) + "\n"; + if ( mod ) ldif += "-\n"; + } else { + if ( mod ) { + ldif += "replace: shadowlastchange\n"; + ldif += "-\nreplace: shadowmin\n"; + ldif += "-\nreplace: shadowmax\n"; + ldif += "-\nreplace: shadowwarning\n"; + ldif += "-\nreplace: shadowinactive\n"; + ldif += "-\nreplace: shadowexpire\n"; + ldif += "-\nreplace: shadowflag\n"; + ldif += "-\n"; + } + } + } + ldif += "\n"; +// kdDebug() << "ldif: " << ldif << endl; +} + +void KUserLDAP::delData( KU::KUser *user ) +{ + ldif = "dn: " + getRDN( user ).utf8() + "," + mUrl.dn().utf8() + "\n" + + "changetype: delete\n\n"; +} + +bool KUserLDAP::dbcommit() +{ + mAddSucc.clear(); + mDelSucc.clear(); + mModSucc.clear(); + mAdd.first(); + mDel.first(); + mAddUser = 0; mDelUser = 0; mUser = 0; + + mProg = new KProgressDialog( 0, "", i18n("LDAP Operation"), "", true ); + KIO::Job *job = KIO::put( mUrl, -1, false, false, false ); + connect( job, SIGNAL( dataReq( KIO::Job*, QByteArray& ) ), + this, SLOT( putData( KIO::Job*, QByteArray& ) ) ); + connect( job, SIGNAL( result( KIO::Job* ) ), + this, SLOT( result( KIO::Job* ) ) ); + mProg->exec(); + return( mOk ); +} + +void KUserLDAP::putData( KIO::Job *, QByteArray& data ) +{ + ModIt mit = mMod.begin(); + + if ( mAddUser ) { + mAddSucc.append( mAddUser ); + mAdd.remove(); + mAddUser = 0; + } + if ( mDelUser ) { + kdDebug() << "delete ok for: " << mDelUser->getName() << endl; + mDelSucc.append( mDelUser ); + if ( mObjectClasses.contains( mDelUser ) ) { + kdDebug() << "deleting additonal objectclasses!" << endl; + mObjectClasses.remove( mDelUser ); + } + mDel.remove(); + mDelUser = 0; + } + if ( mUser ) { + mModSucc.insert( mUser, mit.data() ); + mMod.remove( mit ); + mit = mMod.begin(); + mUser = 0; + } + + if ( (mAddUser = mAdd.current()) ) { + getLDIF( mAddUser, false ); + data = ldif; + } else if ( mit != mMod.end() ) { + mUser = mit.key(); + getLDIF( &(mit.data()), true ); + data = ldif; + } else if ( (mDelUser = mDel.current()) ) { + kdDebug() << "deleting: " << mDelUser->getName() << endl; + delData( mDelUser ); + data = ldif; + } else + data.resize(0); +} diff --git a/kuser/kuserldap.h b/kuser/kuserldap.h new file mode 100644 index 0000000..8d921c1 --- /dev/null +++ b/kuser/kuserldap.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KUSERLDAP_H_ +#define _KUSERLDAP_H_ + +#include <sys/types.h> + +#include <qobject.h> +#include <qstring.h> +#include <qptrlist.h> + +#include <kprogress.h> +#include <kabc/ldapurl.h> +#include <kabc/ldif.h> +#include <kio/job.h> + +#include "kuser.h" + +class KUserLDAP : public QObject, public KU::KUsers { +Q_OBJECT +public: + KUserLDAP(KUserPrefsBase *cfg); + virtual ~KUserLDAP(); + + virtual bool reload(); + virtual bool dbcommit(); + +private slots: + void data( KIO::Job*, const QByteArray& ); + void putData( KIO::Job *job, QByteArray& data ); + void result( KIO::Job* ); +private: + KABC::LDIF mParser; + KABC::LDAPUrl mUrl; + KProgressDialog *mProg; + bool mOk, mCancel; + KU::KUser *mUser, *mDelUser, *mAddUser; + int mAdv; + QCString ldif; + int schemaversion; + QStringList mOc; + QMap<KU::KUser*, QStringList> mObjectClasses; + + QString getRDN( KU::KUser *user ); + void getLDIF( KU::KUser *user, bool mod ); + void delData( KU::KUser *user ); + + virtual void createPassword( KU::KUser *user, const QString &password ); +}; + +#endif // _KUSERLDAP_H_ diff --git a/kuser/kuserprefs.kcfgc b/kuser/kuserprefs.kcfgc new file mode 100644 index 0000000..c9519e1 --- /dev/null +++ b/kuser/kuserprefs.kcfgc @@ -0,0 +1,20 @@ +# Code generation options for kconfig_compiler +File=kuser.kcfg +ClassName=KUserPrefsBase +SetUserTexts=true +# +# Singleton=false +# +# Inherits=KConfigSkeleton +# +# IncludeFiles=libkdepim/kpimprefs.h +# +# MemberVariables=public +# +### The following line includes the file exampleprefs_base_addon.h +### It can be used to add extra functions and variables to the +### class. +# CustomAdditions=true +# +### Provide setFooBar(int) style functions +Mutators=true diff --git a/kuser/kusersystem.cpp b/kuser/kusersystem.cpp new file mode 100644 index 0000000..ef0247f --- /dev/null +++ b/kuser/kusersystem.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "globals.h" +#include <errno.h> +#include <pwd.h> +#ifdef HAVE_SHADOW +#include <shadow.h> +#endif + +#include <qstring.h> + +#include <kmessagebox.h> +#include <kdebug.h> + +#include "kglobal_.h" +#include "misc.h" +#include "kusersystem.h" + +KUserSystem::KUserSystem(KUserPrefsBase *cfg) : KU::KUsers( cfg ) +{ + mUsers.setAutoDelete(TRUE); + + caps = Cap_ReadOnly | Cap_Passwd; +#ifdef HAVE_SHADOW + if ( !mCfg->shadowsrc().isEmpty() ) caps |= Cap_Shadow; +#endif +#if defined(__FreeBSD__) || defined(__bsdi__) + caps |= Cap_BSD; +#endif + + reload(); +} + +KUserSystem::~KUserSystem() +{ +} + +bool KUserSystem::reload() +{ + if (!loadpwd()) + return FALSE; + + if (!loadsdw()) + return FALSE; + + return TRUE; +} + +// Load passwd file + +bool KUserSystem::loadpwd() +{ + passwd *p; + KU::KUser *tmpKU = 0; + QString tmp; + + setpwent(); //This should be enough for BSDs + while ((p = getpwent()) != NULL) { + tmpKU = new KU::KUser(); + tmpKU->setUID(p->pw_uid); + tmpKU->setGID(p->pw_gid); + tmpKU->setName(QString::fromLocal8Bit(p->pw_name)); + tmp = QString::fromLocal8Bit( p->pw_passwd ); + if ( tmp != "x" && tmp != "*" && !tmp.startsWith("!") ) + tmpKU->setDisabled( false ); + else + tmpKU->setDisabled( true ); + if ( tmp.startsWith("!") ) tmp.remove(0, 1); + tmpKU->setPwd( tmp ); + tmpKU->setHomeDir(QString::fromLocal8Bit(p->pw_dir)); + tmpKU->setShell(QString::fromLocal8Bit(p->pw_shell)); +#if defined(__FreeBSD__) || defined(__bsdi__) + tmpKU->setClass(QString::fromLatin1(p->pw_class)); + tmpKU->setLastChange(p->pw_change); + tmpKU->setExpire(p->pw_expire); +#endif + + if ((p->pw_gecos != 0) && (p->pw_gecos[0] != 0)) + fillGecos(tmpKU, p->pw_gecos); + mUsers.append(tmpKU); + } + + endpwent(); + return(TRUE); +} + +// Load shadow passwords + +bool KUserSystem::loadsdw() +{ +#ifdef HAVE_SHADOW + struct spwd *spw; + KU::KUser *up = NULL; + QString tmp; + + setspent(); + while ((spw = getspent())) { // read a shadow password structure + + if ((up = lookup(QString::fromLocal8Bit(spw->sp_namp))) == NULL) { + continue; + } + + tmp = QString::fromLocal8Bit( spw->sp_pwdp ); + if ( tmp.startsWith("!!") || tmp == "*" ) { + up->setDisabled( true ); + tmp.remove( 0, 2 ); + } else + up->setDisabled( false ); + + up->setSPwd( tmp ); // cp the encrypted pwd + up->setLastChange( daysToTime( spw->sp_lstchg ) ); + up->setMin(spw->sp_min); + up->setMax(spw->sp_max); +#ifndef _SCO_DS + up->setWarn(spw->sp_warn); + up->setInactive(spw->sp_inact); + up->setExpire( daysToTime( spw->sp_expire ) ); + up->setFlag(spw->sp_flag); +#endif + } + + endspent(); +#endif //HAVE_SHADOW + return true; +} diff --git a/kuser/kusersystem.h b/kuser/kusersystem.h new file mode 100644 index 0000000..b982447 --- /dev/null +++ b/kuser/kusersystem.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_USERSYSTEM_H_ +#define _KU_USERSYSTEM_H_ + +#include <sys/types.h> + +#include <qstring.h> +#include <qptrlist.h> + +#include "kuser.h" + +class KUserSystem : public KU::KUsers { +public: + KUserSystem(KUserPrefsBase *cfg); + virtual ~KUserSystem(); + + virtual bool dbcommit() { return true; } + virtual bool reload(); + virtual void createPassword( KU::KUser * /*user*/, const QString & /*password*/ ) {} + +private: + + bool loadpwd(); + bool loadsdw(); +}; +#endif // _KU_USERSYSTEM_H_ + diff --git a/kuser/kuserui.rc b/kuser/kuserui.rc new file mode 100644 index 0000000..6e0a93f --- /dev/null +++ b/kuser/kuserui.rc @@ -0,0 +1,36 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kuser"> + <MenuBar> + <Menu name="file"><text>&File</text> + <Action name="select_conn"/> + <Action name="reload"/> + </Menu> + <Menu name="user"><text>&User</text> + <Action name="add_user"/> + <Action name="edit_user"/> + <Action name="delete_user"/> + <Action name="set_password_user"/> + </Menu> + <Menu name="group"><text>&Group</text> + <Action name="add_group"/> + <Action name="edit_group"/> + <Action name="delete_group"/> + </Menu> + <Menu name="settings"><text>&Settings</text> + <Action name="show_sys" append="show_merge"/> + </Menu> + </MenuBar> + <ToolBar fullWidth="true" name="mainToolBar"> + <Action name="add_user"/> + <Action name="edit_user"/> + <Action name="delete_user"/> + <Separator/> + <Action name="add_group"/> + <Action name="edit_group"/> + <Action name="delete_group"/> + <Separator/> + <Action name="reload"/> + <Separator/> + </ToolBar> +</kpartgui> + diff --git a/kuser/kuservw.cpp b/kuser/kuservw.cpp new file mode 100644 index 0000000..766700c --- /dev/null +++ b/kuser/kuservw.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "kglobal_.h" +#include "misc.h" + +#include "kuservw.h" + + +KUserViewItem::KUserViewItem(KListView *parent, KU::KUser *aku) + : KListViewItem(parent), mUser(aku) +{ +} + +int KUserViewItem::compare( QListViewItem *i, int col, bool ascending ) const +{ + if ( col == 0 ) { + uid_t uid1, uid2; + + uid1 = mUser->getUID(); + uid2 = ((KUserViewItem*) i)->mUser->getUID(); + + if ( uid1 == uid2 ) return 0; + return ( uid1 < uid2) ? -1: 1; + } else { + return QListViewItem::compare( i, col, ascending ); + } +} + +void KUserViewItem::paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ) +{ + QColorGroup _cg( cg ); + QColor c = _cg.text(); + + if ( mUser->getDisabled() ) + _cg.setColor( QColorGroup::Text, KGlobalSettings::visitedLinkColor() ); + + KListViewItem::paintCell( p, _cg, column, width, alignment ); + + _cg.setColor( QColorGroup::Text, c ); +} + +QString KUserViewItem::text(int num) const +{ + switch(num) + { + case 0: return mUser->getCaps() & KU::KUser::Cap_POSIX ? + QString::number( mUser->getUID() ) : QString::null; + case 1: return mUser->getName(); + case 2: return mUser->getFullName(); + case 3: return mUser->getHomeDir(); + case 4: return mUser->getShell(); + case 5: return mUser->getSID().getDOM(); + case 6: return mUser->getCaps() & KU::KUser::Cap_Samba ? + QString::number( mUser->getSID().getRID() ) : QString::null; + case 7: return mUser->getLoginScript(); + case 8: return mUser->getProfilePath(); + case 9: return mUser->getHomeDrive(); + case 10: return mUser->getHomePath(); + } + + return QString::null; +} + +KUserView::KUserView(QWidget *parent, const char *name) + : KListView( parent, name ) +{ + setSelectionMode( QListView::Extended ); +} + +KUserView::~KUserView() +{ +} + +void KUserView::insertItem(KU::KUser *aku) { + KUserViewItem *userItem = new KUserViewItem(this, aku); + KListView::insertItem(userItem); +} + +void KUserView::removeItem(KU::KUser *aku) { + KUserViewItem *userItem = (KUserViewItem *)firstChild(); + + while(userItem) + { + if (userItem->user() == aku) + { + delete userItem; + return; + } + userItem = (KUserViewItem*) userItem->nextSibling(); + } +} + +void KUserView::init() +{ + while ( columns() > 5 ) { + removeColumn( 5 ); + } + + setAllColumnsShowFocus(true); + if ( columns() < 5 ) { + addColumn(i18n("UID")); + setColumnAlignment(0, AlignRight); + addColumn(i18n("User Login")); + addColumn(i18n("Full Name")); + addColumn(i18n("Home Directory")); + addColumn(i18n("Login Shell")); + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + addColumn(i18n("Domain SID")); + addColumn(i18n("RID")); + addColumn(i18n("Samba Login Script")); + addColumn(i18n("Samba Profile Path")); + addColumn(i18n("Samba Home Drive")); + addColumn(i18n("Samba Home Path")); + } +} + +KU::KUser *KUserView::getCurrentUser() { + KUserViewItem *userItem = (KUserViewItem *)currentItem(); + if (!userItem) return 0; + + return userItem->user(); +} + +#include "kuservw.moc" diff --git a/kuser/kuservw.h b/kuser/kuservw.h new file mode 100644 index 0000000..3f28948 --- /dev/null +++ b/kuser/kuservw.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_USERVW_H_ +#define _KU_USERVW_H_ + +#include <qwidget.h> + +#include <klistview.h> + +#include "kuser.h" + +class KUserViewItem : public KListViewItem +{ +public: + KUserViewItem(KListView *parent, KU::KUser *aku); + KU::KUser *user() { return mUser; } +private: + virtual QString text ( int ) const; + virtual void paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ); + virtual int compare( QListViewItem *i, int col, bool ascending ) const; + KU::KUser *mUser; +}; + +class KUserView : public KListView +{ + Q_OBJECT + +public: + KUserView( QWidget* parent = 0, const char* name = 0 ); + + virtual ~KUserView(); + + void insertItem(KU::KUser *aku); + void removeItem(KU::KUser *aku); + KU::KUser *getCurrentUser(); + void init(); +}; + +#endif // _KU_USERVW_H_ diff --git a/kuser/ldapsamba.ui b/kuser/ldapsamba.ui new file mode 100644 index 0000000..b705cf7 --- /dev/null +++ b/kuser/ldapsamba.ui @@ -0,0 +1,366 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>LdapSamba</class> +<widget class="QDialog"> + <property name="name"> + <cstring>LdapSamba</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>465</width> + <height>281</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Samba</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_ldapsam</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Manage Samba user accounts/groups</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_samloginscript</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2_2_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Default login script:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samloginscript</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel4_2_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Home drive:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samhomedrive</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3_2_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Profile path template:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samprofilepath</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel5_2_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="text"> + <string>Home path template:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samhomepath</cstring> + </property> + </widget> + <widget class="KLineEdit" row="3" column="1"> + <property name="name"> + <cstring>kcfg_samhomepath</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>kcfg_samprofilepath</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>kcfg_samhomedrive</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_lanmanhash</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Store LanManager hashed password</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Domain name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samdomain</cstring> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>kcfg_samdomain</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>domQuery</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Query Server</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Domain SID (you can obtain with 'net getlocalsid domain_name'):</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samdomsid</cstring> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>kcfg_samdomsid</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="maxLength"> + <number>41</number> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Algorithmic RID base:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_samridbase</cstring> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>kcfg_samridbase</cstring> + </property> + <property name="maxValue"> + <number>9999999</number> + </property> + <property name="minValue"> + <number>1000</number> + </property> + <property name="lineStep"> + <number>2</number> + </property> + <property name="value"> + <number>1000</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_samloginscript</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_samdomsid</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_samhomedrive</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_samhomepath</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_samprofilepath</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_samdomain</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_lanmanhash</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>kcfg_ldapsam</sender> + <signal>toggled(bool)</signal> + <receiver>domQuery</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_ldapsam</tabstop> + <tabstop>kcfg_samloginscript</tabstop> + <tabstop>kcfg_samprofilepath</tabstop> + <tabstop>kcfg_samhomedrive</tabstop> + <tabstop>kcfg_samhomepath</tabstop> + <tabstop>kcfg_lanmanhash</tabstop> + <tabstop>kcfg_samdomain</tabstop> + <tabstop>kcfg_samdomsid</tabstop> + <tabstop>domQuery</tabstop> +</tabstops> +<slots> + <slot>kcfg_ldapsam_toggled( bool )</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/kuser/ldapsettings.ui b/kuser/ldapsettings.ui new file mode 100644 index 0000000..6bdd35b --- /dev/null +++ b/kuser/ldapsettings.ui @@ -0,0 +1,278 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>LdapSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>LdapSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>394</width> + <height>227</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit" row="1" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_ldapuserfilter</cstring> + </property> + </widget> + <widget class="KComboBox" row="2" column="3"> + <item> + <property name="text"> + <string>cn</string> + </property> + </item> + <item> + <property name="text"> + <string>gidNumber</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_ldapgrouprdn</cstring> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>kcfg_ldapgroupbase</cstring> + </property> + </widget> + <widget class="KComboBox" row="4" column="1"> + <item> + <property name="text"> + <string>Plain Text</string> + </property> + </item> + <item> + <property name="text"> + <string>CRYPT</string> + </property> + </item> + <item> + <property name="text"> + <string>MD5</string> + </property> + </item> + <item> + <property name="text"> + <string>SMD5</string> + </property> + </item> + <item> + <property name="text"> + <string>SHA</string> + </property> + </item> + <item> + <property name="text"> + <string>SSHA</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_ldappasswordhash</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>User base:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapuserbase</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel1_4_2</cstring> + </property> + <property name="text"> + <string>Group filter:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapgroupfilter</cstring> + </property> + </widget> + <widget class="QLabel" row="4" column="2"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Structural objectclass:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapstructural</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>User filter:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapuserfilter</cstring> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>kcfg_ldapuserbase</cstring> + </property> + </widget> + <widget class="QLineEdit" row="3" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_ldapgroupfilter</cstring> + </property> + </widget> + <widget class="KComboBox" row="4" column="3"> + <item> + <property name="text"> + <string>account</string> + </property> + </item> + <item> + <property name="text"> + <string>inetOrgPerson</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_ldapstructural</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="2"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Group RDN prefix:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapgrouprdn</cstring> + </property> + </widget> + <widget class="KComboBox" row="0" column="3"> + <item> + <property name="text"> + <string>uid</string> + </property> + </item> + <item> + <property name="text"> + <string>uidNumber</string> + </property> + </item> + <item> + <property name="text"> + <string>cn</string> + </property> + </item> + <property name="name"> + <cstring>kcfg_ldapuserrdn</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Group base:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapgroupbase</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>User RDN prefix:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldapuserrdn</cstring> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Password hash:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_ldappasswordhash</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_ldapshadow</cstring> + </property> + <property name="text"> + <string>Manage shadowAccount objectclass</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_ldapcnfullname</cstring> + </property> + <property name="text"> + <string>Store the user's full name in the cn attribute</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_ldapgecos</cstring> + </property> + <property name="text"> + <string>Update the gecos attribute</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<tabstops> + <tabstop>kcfg_ldapuserbase</tabstop> + <tabstop>kcfg_ldapuserrdn</tabstop> + <tabstop>kcfg_ldapuserfilter</tabstop> + <tabstop>kcfg_ldapgroupbase</tabstop> + <tabstop>kcfg_ldapgrouprdn</tabstop> + <tabstop>kcfg_ldapgroupfilter</tabstop> + <tabstop>kcfg_ldappasswordhash</tabstop> + <tabstop>kcfg_ldapstructural</tabstop> + <tabstop>kcfg_ldapshadow</tabstop> + <tabstop>kcfg_ldapcnfullname</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kuser/main.cpp b/kuser/main.cpp new file mode 100644 index 0000000..d6b4bfb --- /dev/null +++ b/kuser/main.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qfont.h> + +#include <kiconloader.h> +#include <kapplication.h> +#include <kconfig.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <kdebug.h> + +#include "kglobal_.h" +#include "misc.h" +#include "mainWidget.h" + +static const char *description = + I18N_NOOP("KDE User Editor"); + +KUserGlobals *kug = 0; + +int main(int argc, char **argv) +{ + + KAboutData aboutData("kuser", I18N_NOOP("KUser"), + _KU_VERSION, description, KAboutData::License_GPL, + "(c) 1997-2000, Denis Perchine\n(c) 2004, Szombathelyi György"); + aboutData.addAuthor("Denis Perchine", I18N_NOOP("kuser author"), + "dyp@perchine.com", "http://www.perchine.com/dyp/"); + aboutData.addAuthor("Szombathelyi György", I18N_NOOP("kuser author"), + "gyurco@freemail.hu"); + KCmdLineArgs::init(argc, argv, &aboutData); + mainWidget *mw = 0; + + KApplication a; + + kapp->sharedConfig()->setGroup( "general" ); + kug = new KUserGlobals(); + kug->initCfg( kapp->sharedConfig()->readEntry( "connection", "default" ) ); + + mw = new mainWidget("kuser"); + a.setMainWidget(mw); + mw->setCaption(i18n("KDE User Manager")); + mw->show(); + + a.exec(); + + kug->kcfg()->writeConfig(); + delete kug; + +} diff --git a/kuser/mainView.cpp b/kuser/mainView.cpp new file mode 100644 index 0000000..4f4e388 --- /dev/null +++ b/kuser/mainView.cpp @@ -0,0 +1,526 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "mainView.h" + +#include <stdio.h> + +#include <qtooltip.h> +#include <qfile.h> + +#include <kinputdialog.h> +#include <ktoolbar.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include "misc.h" +#include "kglobal_.h" +#include "propdlg.h" +#include "addUser.h" +#include "delUser.h" +#include "pwddlg.h" +#include "editGroup.h" + +mainView::mainView(QWidget *parent) : QTabWidget(parent) +{ + init(); +} + +void mainView::init() { + + lbusers = new KUserView( this, "lbusers" ); + addTab( lbusers, i18n("Users") ); + + lbgroups = new KGroupView( this, "lbgroups" ); + addTab( lbgroups, i18n("Groups")); + + connect(lbusers, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(userSelected())); + connect(lbusers, SIGNAL(returnPressed(QListViewItem *)), this, SLOT(userSelected())); + + connect(lbgroups, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(groupSelected())); + connect(lbgroups, SIGNAL(returnPressed(QListViewItem *)), this, SLOT(groupSelected())); + + connect(this, SIGNAL(currentChanged(QWidget *)), this, SLOT(slotTabChanged())); +} + +mainView::~mainView() +{ +} + +void mainView::slotTabChanged() +{ + if (currentPage() == lbusers) + { + emit userSelected(true); + emit groupSelected(false); + } + else + { + emit userSelected(false); + emit groupSelected(true); + } +} + +void mainView::clearUsers() +{ + lbusers->clear(); +} + +void mainView::clearGroups() +{ + lbgroups->clear(); +} + +void mainView::reloadUsers() +{ + KU::KUser *ku; + + lbusers->clear(); + lbusers->init(); + uid_t uid = kug->kcfg()->firstUID(); + + ku = kug->getUsers().first(); + while ( ku ) { + if ( ku->getUID() >= uid || mShowSys ) lbusers->insertItem( ku ); + ku = kug->getUsers().next(); + } + if (lbusers->firstChild()) + lbusers->setSelected(lbusers->firstChild(), true); +} + +void mainView::reloadGroups() +{ + KU::KGroup *kg; + + lbgroups->clear(); + lbgroups->init(); + gid_t gid = kug->kcfg()->firstGID(); + + kg = kug->getGroups().first(); + while ( kg ) { + if ( kg->getGID() >= gid || mShowSys ) lbgroups->insertItem(kg); + kg = kug->getGroups().next(); + } +} + +void mainView::useredit() +{ + userSelected(); +} + +void mainView::userdel() +{ + KU::KUser *user = lbusers->getCurrentUser(); + if (!user) + return; + + QString username = user->getName(); + gid_t gid = user->getGID(); + delUser dlg(user, this); + + if ( dlg.exec() == QDialog::Rejected ) + return; + + user->setDeleteHome( dlg.getDeleteHomeDir() ); + user->setDeleteMailBox( dlg.getDeleteMailBox() ); + + kug->getUsers().del( user ); + if ( !updateUsers() ) return; + + KU::KGroup *group = 0; + group = kug->getGroups().first(); + while ( group ) { + kdDebug() << "group: " << group->getName() << endl; + if ( group->lookup_user( username ) ) { + kdDebug() << "group: " << group->getName() << " found user: " << username << endl; + KU::KGroup newgroup( group ); + newgroup.removeUser( username ); + kug->getGroups().mod( group, newgroup ); + } + group = kug->getGroups().next(); + } + + if ( kug->kcfg()->userPrivateGroup() ) { + + group = kug->getGroups().lookup( gid ); + + if ( group && + KMessageBox::questionYesNo( 0, i18n("You are using private groups.\n" + "Do you want to delete the user's private group '%1'?") + .arg(group->getName()), QString::null, + KStdGuiItem::del(), i18n("Do Not Delete")) == KMessageBox::Yes) { + kdDebug() << "del private group" << endl; + kug->getGroups().del( group ); + } + } + kdDebug() << "update groups" << endl; + updateGroups(); +} + +void mainView::useradd() +{ + KU::KUser *tk; + + showPage(lbusers); + + uid_t uid, rid = 0; + bool samba = kug->getUsers().getCaps() & KU::KUsers::Cap_Samba; + + if ((uid = kug->getUsers().first_free()) == KU::KUsers::NO_FREE) { + KMessageBox::sorry( 0, i18n("You have run out of uid space.") ); + return; + } +/* + if ( samba && (rid = kug->getUsers().first_free_sam()) == 0) { + KMessageBox::sorry( 0, i18n("You have run out of user RID space.") ); + return; + } +*/ + if ( samba ) rid = SID::uid2rid( uid ); + bool ok; + QString name = KInputDialog::getText( QString::null, + i18n("Please type the name of the new user:"), + QString::null, &ok ); + + if ( !ok ) return; + + if ( kug->getUsers().lookup( name ) ) { + KMessageBox::sorry( 0, i18n("User with name %1 already exists.").arg( name ) ); + return; + } + + tk = new KU::KUser(); + tk->setCaps( samba ? KU::KUser::Cap_POSIX | KU::KUser::Cap_Samba : KU::KUser::Cap_POSIX ); + tk->setUID( uid ); + tk->setName( name ); + + if ( samba ) { + SID sid; + sid.setDOM( kug->getUsers().getDOMSID() ); + sid.setRID( rid ); + tk->setSID( sid ); + tk->setProfilePath( kug->kcfg()->samprofilepath().replace( "%U",name ) ); + tk->setHomePath( kug->kcfg()->samhomepath().replace( "%U", name ) ); + tk->setHomeDrive( kug->kcfg()->samhomedrive() ); + tk->setLoginScript( kug->kcfg()->samloginscript() ); + tk->setDomain( kug->kcfg()->samdomain() ); + } + + tk->setShell( kug->kcfg()->shell() ); + tk->setHomeDir( kug->kcfg()->homepath().replace( "%U", name ) ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow || samba ) { + tk->setLastChange( now() ); + } + + tk->setMin( kug->kcfg()->smin() ); + tk->setMax( kug->kcfg()->smax() ); + tk->setWarn( kug->kcfg()->swarn() ); + tk->setInactive( kug->kcfg()->sinact() ); + tk->setExpire( kug->kcfg()->sneverexpire() ? (uint) -1 : + (kug->kcfg()->sexpire()).toTime_t() ); + + bool privgroup = kug->kcfg()->userPrivateGroup(); + + if ( !privgroup ) tk->setGID( kug->kcfg()->defaultgroup() ); + + addUser au( tk, privgroup, this ); + + au.setCreateHomeDir( kug->kcfg()->createHomeDir() ); + au.setCopySkel( kug->kcfg()->copySkel() ); + + if ( au.exec() == QDialog::Rejected ) { + delete tk; + return; + } + if ( privgroup ) { + KU::KGroup *tg; + + if ((tg = kug->getGroups().lookup(tk->getName())) == 0) { + gid_t gid; + if ( kug->getGroups().lookup( tk->getUID() ) == 0 ) { + gid = tk->getUID(); + } else { + gid = kug->getGroups().first_free(); + } + kdDebug() << "private group GID: " << gid << endl; + uid_t rid = 0; +// if ( samba ) rid = kug->getGroups().first_free_sam(); + if ( samba ) rid = SID::gid2rid( gid ); + if ( gid == KU::KGroups::NO_FREE || ( samba && rid == 0 ) ) { + kug->getGroups().cancelMods(); + delete tk; + return; + } + tg = new KU::KGroup(); + tg->setGID( gid ); + if ( samba && ( tk->getCaps() & KU::KUser::Cap_Samba ) ) { + SID sid; + sid.setDOM( kug->getGroups().getDOMSID() ); + sid.setRID( rid ); + tg->setSID( sid ); + tg->setDisplayName( tk->getName() ); + tg->setCaps( KU::KGroup::Cap_Samba ); + } + tg->setName( tk->getName() ); + kug->getGroups().add( tg ); + } + tk->setGID( tg->getGID() ); + tk->setPGSID( tg->getSID() ); + } + kug->getUsers().add( tk ); + if ( !updateUsers() ) { + kug->getGroups().cancelMods(); + return; + } + updateGroups(); +} + +bool mainView::queryClose() +{ + return true; +} + +void mainView::setpwd() +{ + int count = lbusers->selectedItems().count(); + if ( count == 0 ) return; + if ( count > 1 ) { + if ( KMessageBox::questionYesNo( 0, + i18n("You have selected %1 users. Do you really want to change the password for all the selected users?") + .arg( count ), QString::null, i18n("Change"), i18n("Do Not Change") ) == KMessageBox::No ) return; + } + pwddlg d( this ); + if ( d.exec() != QDialog::Accepted ) return; + + KU::KUser newuser, *user; + QListViewItem *item; + + item = lbusers->firstChild(); + while ( item ) { + if ( item->isSelected() ) { + user = ((KUserViewItem*) item)->user(); + newuser.copy( user ); + kug->getUsers().createPassword( &newuser, d.getPassword() ); + newuser.setLastChange( now() ); + newuser.setDisabled( false ); + kug->getUsers().mod( user, newuser ); + } + item = item->nextSibling(); + } + updateUsers(); +} + +void mainView::groupSelected() +{ + bool samba = kug->getGroups().getCaps() & KU::KGroups::Cap_Samba; + KU::KGroup *tmpKG = lbgroups->getCurrentGroup(); + if ( !tmpKG ) return; + KU::KGroup newGroup( tmpKG ); + + kdDebug() << "The SID for group " << newGroup.getName() << " is: '" << newGroup.getSID().getSID() << "'" << endl; + if ( samba && ( newGroup.getCaps() & KU::KGroup::Cap_Samba ) && + newGroup.getSID().isEmpty() ) { + SID sid; + sid.setDOM( kug->getGroups().getDOMSID() ); +// sid.setRID( kug->getGroups().first_free_sam() ); + sid.setRID( SID::gid2rid( newGroup.getGID() ) ); + newGroup.setSID( sid ); + kdDebug() << "The new SID for group " << newGroup.getName() << " is: " << sid.getSID() << endl; + } + editGroup egdlg( &newGroup, samba, false ); + + if ( egdlg.exec() == QDialog::Accepted ) { + kug->getGroups().mod( tmpKG, newGroup ); + updateGroups(); + } +} + +void mainView::userSelected() +{ + QListViewItem *item; + QPtrList<KU::KUser> ulist; + + item = lbusers->firstChild(); + while ( item ) { + if ( item->isSelected() ) { + ulist.append( ((KUserViewItem*) item)->user() ); + } + item = item->nextSibling(); + } + if ( ulist.isEmpty() ) return; + + propdlg editUser( ulist, this ); + if ( editUser.exec() == QDialog::Rejected ) return; + + KU::KUser *user, newuser; + user = ulist.first(); + while ( user ) { + editUser.mergeUser( user, &newuser ); + kug->getUsers().mod( user, newuser ); + user = ulist.next(); + } + updateUsers(); + updateGroups(); +} + +void mainView::grpadd() +{ + showPage(lbgroups); + + gid_t gid; + uid_t rid = 0; + bool samba; + + samba = kug->getGroups().getCaps() & KU::KGroups::Cap_Samba; + + if ( (gid = kug->getGroups().first_free()) == KU::KGroups::NO_FREE ) + { + KMessageBox::sorry( 0, i18n("You have run out of gid space.") ); + return; + } +/* + if ( samba && (rid = kug->getGroups().first_free_sam()) == 0 ) + { + KMessageBox::sorry( 0, i18n("You have run out of group RID space.") ); + return; + } +*/ + if ( samba ) rid = SID::gid2rid( gid ); + + KU::KGroup *tk = new KU::KGroup(); + tk->setGID(gid); + if ( samba ) { + SID sid; + sid.setRID( rid ); + sid.setDOM( kug->getGroups().getDOMSID() ); + tk->setSID( sid ); + } + editGroup egdlg( tk, samba, true ); + + if ( egdlg.exec() == QDialog::Rejected ) { + delete tk; + return; + } + kug->getGroups().add(tk); + updateGroups(); +} + +void mainView::grpedit() +{ + groupSelected(); +} + +void mainView::grpdel() +{ + QListViewItem *item; + KU::KGroup *group = NULL; + int selected = 0; + + item = lbgroups->firstChild(); + while ( item ) { + if ( item->isSelected() ) { + + selected++; + group = ((KGroupViewItem*) item)->group(); + + KU::KUser *user = kug->getUsers().first(); + while ( user ) { + if ( user->getGID() == group->getGID() ) { + KMessageBox::error( 0, i18n( "The group '%1' is the primary group of one or more users (such as '%2'); it cannot be deleted." ).arg( group->getName() ).arg( user->getName() ) ); + return; + } + user = kug->getUsers().next(); + } + } + item = item->nextSibling(); + } + + switch ( selected ) { + case 0: return; + case 1: + if (KMessageBox::warningContinueCancel( 0, + i18n("Do you really want to delete the group '%1'?").arg(group->getName()), + QString::null, KStdGuiItem::del()) != KMessageBox::Continue) return; + break; + default: + if (KMessageBox::warningContinueCancel( 0, + i18n("Do you really want to delete the %1 selected groups?").arg(selected), + QString::null, KStdGuiItem::del()) != KMessageBox::Continue) return; + } + + item = lbgroups->firstChild(); + while ( item ) { + if ( item->isSelected() ) { + group = ((KGroupViewItem*) item)->group(); + kug->getGroups().del( group ); + } + item = item->nextSibling(); + } + updateGroups(); +} + +bool mainView::updateGroups() +{ + bool ret; + kdDebug() << "updateGroups() " << endl; + ret = kug->getGroups().dbcommit(); + + KU::KGroup *group; + KU::KGroups::DelIt dit( kug->getGroups().mDelSucc ); + KU::KGroups::AddIt ait( kug->getGroups().mAddSucc ); + + while ( (group = dit.current()) != 0 ) { + ++dit; + lbgroups->removeItem( group ); + } + while ( (group = ait.current()) != 0 ) { + ++ait; + lbgroups->insertItem( group ); + } + kdDebug() << "commit groups" << endl; + kug->getGroups().commit(); + return ret; +} + +bool mainView::updateUsers() +{ + bool ret; + kdDebug() << "updateUsers() " << endl; + ret = kug->getUsers().dbcommit(); + + KU::KUser *user; + KU::KUsers::DelIt dit( kug->getUsers().mDelSucc ); + KU::KUsers::AddIt ait( kug->getUsers().mAddSucc ); + + while ( (user = dit.current()) != 0 ) { + ++dit; + lbusers->removeItem( user ); + } + while ( (user = ait.current()) != 0 ) { + ++ait; + lbusers->insertItem( user ); + } + kug->getUsers().commit(); + return ret; +} + + +#include "mainView.moc" diff --git a/kuser/mainView.h b/kuser/mainView.h new file mode 100644 index 0000000..5304ea3 --- /dev/null +++ b/kuser/mainView.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_MAINVIEW_H_ +#define _KU_MAINVIEW_H_ + +#include <stdlib.h> + +#include <qevent.h> +#include <qptrlist.h> +#include <qpushbutton.h> +#include <qpixmap.h> +#include <qtabwidget.h> + +#include "kuservw.h" +#include "kgroupvw.h" + +class mainView : public QTabWidget { +Q_OBJECT +public: + mainView(QWidget *parent = 0); + ~mainView(); + + void init(); + void setShowSys( bool b ) { mShowSys = b; } + + bool queryClose(); + + void clearUsers(); + void clearGroups(); + void reloadUsers(); + void reloadGroups(); + +public slots: + void slotTabChanged(); + + void userSelected(); + void groupSelected(); + + void useradd(); + void useredit(); + void userdel(); + + void grpadd(); + void grpedit(); + void grpdel(); + + void setpwd(); + +signals: + void userSelected(bool); + void groupSelected(bool); + +protected: + bool updateUsers(); + bool updateGroups(); + + KUserView *lbusers; + KGroupView *lbgroups; + bool mShowSys; +}; + +#endif // _KU_MAINVIEW_H_ diff --git a/kuser/mainWidget.cpp b/kuser/mainWidget.cpp new file mode 100644 index 0000000..91b5862 --- /dev/null +++ b/kuser/mainWidget.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qtooltip.h> +#include <qtimer.h> + +#include <ktoolbar.h> +#include <kiconloader.h> +#include <kaction.h> +#include <klocale.h> +#include <kstdaction.h> + +#include <kdebug.h> +#include <kaction.h> +#include <kstatusbar.h> +#include <kedittoolbar.h> + +#include "kglobal_.h" +#include "editDefaults.h" +#include "mainWidget.h" +#include "selectconn.h" +#include "mainView.h" + +mainWidget::mainWidget(const char *name) : KMainWindow(0,name) +{ + md = new mainView(this); + + setupActions(); + md->setShowSys( mShowSys->isChecked() ); + init(); + md->slotTabChanged(); + + statusBar()->insertItem(i18n("Reading configuration"), 0); + + setCentralWidget(md); + + setupGUI(); + + statusBar()->changeItem(i18n("Ready"), 0); +} + +mainWidget::~mainWidget() +{ + delete md; +} + +bool mainWidget::queryClose() +{ + return md->queryClose(); +} + +void mainWidget::setupActions() +{ + KStdAction::quit(this, SLOT(close()), actionCollection()); + KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection()); + + KStdAction::preferences(this, SLOT(properties()), actionCollection()); + +#define BarIconC(x) BarIcon(QString::fromLatin1(x)) + + (void) new KAction(i18n("&Add..."), QIconSet(BarIconC("add_user")), 0, md, + SLOT(useradd()), actionCollection(), "add_user"); + + (void) new KAction(i18n("&Edit..."), QIconSet(BarIconC("edit_user")), 0, md, + SLOT(useredit()), actionCollection(), "edit_user"); + + (void) new KAction(i18n("&Delete..."), QIconSet(BarIconC("delete_user")), 0, md, + SLOT(userdel()), actionCollection(), "delete_user"); + + (void) new KAction(i18n("&Set Password..."), + 0, md, SLOT(setpwd()), actionCollection(), "set_password_user"); + + (void) new KAction(i18n("&Add..."), QIconSet(BarIconC("add_group")), 0, md, + SLOT(grpadd()), actionCollection(), "add_group"); + + (void) new KAction(i18n("&Edit..."), QIconSet(BarIconC("edit_group")), 0, md, + SLOT(grpedit()), actionCollection(), "edit_group"); + + (void) new KAction(i18n("&Delete"), QIconSet(BarIconC("delete_group")), 0, md, + SLOT(grpdel()), actionCollection(), "delete_group"); + + (void) new KAction(i18n("&Reload"), QIconSet(BarIconC("reload")), 0, this, + SLOT(reload()), actionCollection(), "reload"); + +#undef BarIconC + + (void) new KAction(i18n("&Select Connection..."), + 0, this, + SLOT(selectconn()), actionCollection(), "select_conn"); + + mShowSys = new KToggleAction(i18n("Show System Users/Groups"), + 0, 0, this, + SLOT(showSys()), actionCollection(), "show_sys"); + mShowSys->setCheckedState(i18n("Hide System Users/Groups")); + mShowSys->setChecked( kug->kcfg()->showsys() ); +} + +void mainWidget::showSys() +{ + kug->kcfg()->setShowsys( mShowSys->isChecked() ); + md->setShowSys( mShowSys->isChecked() ); + md->reloadUsers(); + md->reloadGroups(); +} + +void mainWidget::properties() +{ + editDefaults *eddlg = new editDefaults( kug->kcfg(), this ); + connect(eddlg, SIGNAL(settingsChanged()), this, SLOT(slotApplySettings())); + + eddlg->show(); +} + +void mainWidget::reload() +{ + init(); +} + +void mainWidget::init() +{ + bool rw; + + md->clearUsers(); + md->clearGroups(); + kug->init(); + rw = ! ( kug->getUsers().getCaps() & KU::KUsers::Cap_ReadOnly ); + kdDebug() << "Users rw()" << rw << endl; + actionCollection()->action("add_user")->setEnabled( rw ); + actionCollection()->action("edit_user")->setEnabled( rw ); + actionCollection()->action("delete_user")->setEnabled( rw ); + actionCollection()->action("set_password_user")->setEnabled( rw ); + if ( rw ) { + connect( md, SIGNAL(userSelected(bool)), + actionCollection()->action("edit_user"), SLOT(setEnabled(bool)) ); + connect( md, SIGNAL(userSelected(bool)), + actionCollection()->action("delete_user"), SLOT(setEnabled(bool)) ); + connect( md, SIGNAL(userSelected(bool)), + actionCollection()->action("set_password_user"), SLOT(setEnabled(bool)) ); + } else { + disconnect( md, SIGNAL(userSelected(bool)), 0, 0 ); + } + + rw = ! ( kug->getGroups().getCaps() & KU::KGroups::Cap_ReadOnly ); + kdDebug() << "Groups rw()" << rw << endl; + actionCollection()->action("add_group")->setEnabled( rw ); + actionCollection()->action("edit_group")->setEnabled( rw ); + actionCollection()->action("delete_group")->setEnabled( rw ); + if ( rw ) { + connect( md, SIGNAL(groupSelected(bool)), + actionCollection()->action("edit_group"), SLOT(setEnabled(bool)) ); + connect( md, SIGNAL(groupSelected(bool)), + actionCollection()->action("delete_group"), SLOT(setEnabled(bool)) ); + } else { + disconnect( md, SIGNAL(groupSelected(bool)), 0, 0 ); + } + md->reloadUsers(); + md->reloadGroups(); + QTimer::singleShot( 0, md, SLOT(slotTabChanged()) ); +} + +void mainWidget::slotApplySettings() +{ + kdDebug() << "settings changed!" << endl; + init(); +} + +void mainWidget::slotApplyConnection() +{ + kdDebug() << "slotApplyConnection()" << endl; + QString conn = sc->connSelected(); + kug->kcfg()->setConnection( conn ); + kug->initCfg( conn ); + slotApplySettings(); +} + +void mainWidget::selectconn() +{ + sc = new SelectConn( kug->kcfg()->connection(), this, "selectconn" ); + connect( sc, SIGNAL(applyClicked()), SLOT(slotApplyConnection()) ); + connect( sc, SIGNAL(okClicked()), SLOT(slotApplyConnection()) ); + sc->show(); +} + +#include "mainWidget.moc" diff --git a/kuser/mainWidget.h b/kuser/mainWidget.h new file mode 100644 index 0000000..840ca01 --- /dev/null +++ b/kuser/mainWidget.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_MAINWIDGET_H_ +#define _KU_MAINWIDGET_H_ + +#include <kmainwindow.h> + +class SelectConn; +class mainView; +class KToggleAction; + +class mainWidget : public KMainWindow { +Q_OBJECT +public: + mainWidget(const char *name = 0); + ~mainWidget(); + bool queryClose(); + +protected: + void init(); + void setupActions(); + +protected slots: + void showSys(); + void properties(); + void slotApplySettings(); + void slotApplyConnection(); + void selectconn(); + void reload(); + +private: + KToggleAction *mShowSys; + mainView *md; + SelectConn *sc; + +}; + +#endif // _KU_MAINWIDGET_H_ diff --git a/kuser/misc.cpp b/kuser/misc.cpp new file mode 100644 index 0000000..4215c40 --- /dev/null +++ b/kuser/misc.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "globals.h" + +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_CRYPT_H +#include <crypt.h> +#endif +#include <qfile.h> + +#include <kmessagebox.h> + +#include "misc.h" +#include "kglobal_.h" + +bool backup(const QString & name) +{ + QString tmp = name + QString::fromLatin1(KU_BACKUP_EXT); + QFile::remove( tmp ); + + if (copyFile(QFile::encodeName(name), QFile::encodeName(tmp)) == -1) + { + QString str; + KMessageBox::error( 0, i18n("Can't create backup file for %1").arg(name) ); + return false; + } + return true; +} + +time_t now() { + struct timeval tv; + + gettimeofday( &tv, NULL ); + return ( tv.tv_sec ); +} + +#define BLOCK_SIZE 65536 + +int copyFile(const QString & from, const QString & to) +{ + QFile fi; + QFile fo; + char buf[BLOCK_SIZE]; + + fi.setName(from); + fo.setName(to); + + if (!fi.exists()) { + KMessageBox::error( 0, i18n("File %1 does not exist.").arg(from) ); + return (-1); + } + + if (!fi.open(IO_ReadOnly)) { + KMessageBox::error( 0, i18n("Cannot open file %1 for reading.").arg(from) ); + return (-1); + } + + if (!fo.open(IO_Raw | IO_WriteOnly | IO_Truncate)) { + KMessageBox::error( 0, i18n("Cannot open file %1 for writing.").arg(to) ); + return (-1); + } + + while (!fi.atEnd()) { + int len = fi.readBlock(buf, BLOCK_SIZE); + if (len <= 0) + break; + fo.writeBlock(buf, len); + } + + fi.close(); + fo.close(); + + return (0); +} + +QStringList readShells() +{ + QStringList shells; + + FILE *f = fopen(SHELL_FILE,"r"); + if (f) { + while (!feof(f)) { + char s[200]; + + fgets(s, 200, f); + if (feof(f)) + break; + + s[strlen(s)-1]=0; + if ((s[0])&&(s[0]!='#')) + shells.append(QFile::decodeName(s)); + } + fclose(f); + } + return shells; +} + +void addShell(const QString &shell) +{ + QStringList shells = readShells(); + if (shells.contains(shell)) + return; + + FILE *f = fopen(SHELL_FILE,"a"); + if (f) + { + fputs(QFile::encodeName(shell).data(), f); + fputc('\n', f); + } + fclose(f); +} + +QCString genSalt( int len ) +{ + QCString salt( len + 1 ); + const char * set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; + + salt[0] = set[getpid() % strlen(set)]; + for( int i = 1; i < len; i++ ) { + salt[i] = set[kapp->random() % strlen(set)]; + } + return salt; +} + +QString encryptPass( const QString &pass, bool md5 ) +{ + QCString salt; + char tmp[128]; + + if ( md5 ) { + salt = "$1$"; + salt += genSalt( 8 ); + salt += '$'; + + } else { + salt = genSalt( 2 ); + } + strcpy( tmp, crypt( QFile::encodeName( pass ), salt ) ); + return QString::fromLocal8Bit( tmp ); +} + +int timeToDays(time_t time) +{ + return time < 0 ? -1 : time/(24*60*60); +} + +time_t daysToTime(int days) +{ + return days*24*60*60; +} diff --git a/kuser/misc.h b/kuser/misc.h new file mode 100644 index 0000000..87485e6 --- /dev/null +++ b/kuser/misc.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_MISC_H_ +#define _KU_MISC_H_ + +#include <sys/time.h> + +#include <klocale.h> +#include <kapplication.h> +#include <qstring.h> +#include <qwidget.h> +#include <qlabel.h> +#include <qlineedit.h> + +class KUser; + +bool backup(const QString & name); +QCString genSalt( int len ); +QString encryptPass( const QString &pass, bool md5 ); +time_t now(); +int copyFile(const QString & from, const QString & to); +QStringList readShells(); +void addShell(const QString &shell); +int timeToDays(time_t time); +time_t daysToTime(int days); + +#endif // _KU_MISC_H_ diff --git a/kuser/passwordpolicy.ui b/kuser/passwordpolicy.ui new file mode 100644 index 0000000..03318d4 --- /dev/null +++ b/kuser/passwordpolicy.ui @@ -0,0 +1,244 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>PasswordPolicy</class> +<widget class="QWidget"> + <property name="name"> + <cstring>PasswordPolicy</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>479</width> + <height>157</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Time before password expires to issue an expire warning:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_swarn</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Time when password expires after last password change:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_smax</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>Time when account will be disabled after expiration of password:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_sinact</cstring> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>kcfg_smax</cstring> + </property> + <property name="suffix"> + <string> days</string> + </property> + <property name="specialValueText"> + <string>Never</string> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + <property name="minValue"> + <number>-1</number> + </property> + </widget> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>kcfg_sinact</cstring> + </property> + <property name="suffix"> + <string> days</string> + </property> + <property name="specialValueText"> + <string>Never</string> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + <property name="minValue"> + <number>-1</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Time before password may not be changed after last password change:</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="buddy" stdset="0"> + <cstring>kcfg_smin</cstring> + </property> + </widget> + <widget class="QSpinBox" row="2" column="1"> + <property name="name"> + <cstring>kcfg_swarn</cstring> + </property> + <property name="suffix"> + <string> days</string> + </property> + <property name="specialValueText"> + <string>Never</string> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + <property name="minValue"> + <number>-1</number> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>kcfg_smin</cstring> + </property> + <property name="suffix"> + <string> days</string> + </property> + <property name="specialValueText"> + <string></string> + </property> + <property name="maxValue"> + <number>99999</number> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Account will expire on:</string> + </property> + </widget> + <widget class="KDateTimeWidget"> + <property name="name"> + <cstring>kcfg_sexpire</cstring> + </property> + <property name="dateTime"> + <datetime> + <year>2000</year> + <month>1</month> + <day>1</day> + <hour>0</hour> + <minute>0</minute> + <second>0</second> + </datetime> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_sneverexpire</cstring> + </property> + <property name="text"> + <string>Never</string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_sneverexpire</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_sexpire</receiver> + <slot>setDisabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>kcfg_smin</tabstop> + <tabstop>kcfg_smax</tabstop> + <tabstop>kcfg_swarn</tabstop> + <tabstop>kcfg_sinact</tabstop> + <tabstop>kcfg_sneverexpire</tabstop> +</tabstops> +<slots> + <slot>kcfg_sneverexpire_toggled( bool )</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kdatetimewidget.h</includehint> + <includehint>kdatewidget.h</includehint> + <includehint>ktimewidget.h</includehint> +</includehints> +</UI> diff --git a/kuser/pic/Makefile.am b/kuser/pic/Makefile.am new file mode 100644 index 0000000..38d815a --- /dev/null +++ b/kuser/pic/Makefile.am @@ -0,0 +1,9 @@ + +# add here all files +pics_DATA = group.png user.png + +# this is the directory, where all datas are installed +# you have given the datas in data_DATA +picsdir = $(kde_datadir)/kuser/pics/ + +EXTRA_DIST = $(pics_DATA) diff --git a/kuser/pic/group.png b/kuser/pic/group.png Binary files differnew file mode 100644 index 0000000..e0985dc --- /dev/null +++ b/kuser/pic/group.png diff --git a/kuser/pic/user.png b/kuser/pic/user.png Binary files differnew file mode 100644 index 0000000..ceac8d1 --- /dev/null +++ b/kuser/pic/user.png diff --git a/kuser/propdlg.cpp b/kuser/propdlg.cpp new file mode 100644 index 0000000..726cec1 --- /dev/null +++ b/kuser/propdlg.cpp @@ -0,0 +1,991 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <stdio.h> +#include <stdlib.h> + +#include <qdatetime.h> +#include <qwhatsthis.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qfile.h> + +#include <kseparator.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include <qvalidator.h> + +#include "propdlg.h" +#include "pwddlg.h" +#include "kglobal_.h" +#include "misc.h" + +void propdlg::addRow(QWidget *parent, QGridLayout *layout, int row, + QWidget *widget, const QString &label, const QString &what, + bool two_column, bool nochange) +{ + QLabel *lab = new QLabel(widget, label, parent); + lab->setMinimumSize(lab->sizeHint()); + widget->setMinimumSize(widget->sizeHint()); + layout->addWidget(lab, row, 0); + if (!what.isEmpty()) + { + QWhatsThis::add(lab, what); + QWhatsThis::add(widget, what); + } + if (two_column) + layout->addMultiCellWidget(widget, row, row, 1, 2); + else + layout->addWidget(widget, row, 1); + + if ( !nochange || ro ) return; + QCheckBox *nc = new QCheckBox( i18n("Do not change"), parent ); + layout->addWidget( nc, row, 3 ); + nc->hide(); + mNoChanges[ widget ] = nc; +} + +KIntSpinBox *propdlg::addDaysGroup(QWidget *parent, QGridLayout *layout, int row, + const QString &title, bool never) +{ + KIntSpinBox *days; + + QLabel *label = new QLabel( title, parent ); + layout->addMultiCellWidget( label, row, row, 0, 1, AlignRight ); + + days = new KIntSpinBox( parent ); + label->setBuddy( days ); + days->setSuffix( i18n(" days") ); + days->setMaxValue( 99999 ); + if (never) + { + days->setMinValue( -1 ); + days->setSpecialValueText(i18n("Never")); + } + else + { + days->setMinValue( 0 ); + } + layout->addWidget( days, row, 2 ); + + connect(days, SIGNAL(valueChanged(int)), this, SLOT(changed())); + + QCheckBox *nc = new QCheckBox( i18n("Do not change"), parent ); + layout->addWidget( nc, row, 3 ); + nc->hide(); + mNoChanges[ days ] = nc; + + return days; +} + +void propdlg::initDlg() +{ + ro = kug->getUsers().getCaps() & KU::KUsers::Cap_ReadOnly; + + QString whatstr; + + // Tab 1: User Info + { + QFrame *frame = addPage(i18n("User Info")); + QGridLayout *layout = new QGridLayout(frame, 20, 4, marginHint(), spacingHint()); + int row = 0; + + frontpage = frame; + frontlayout = layout; + + lbuser = new QLabel(frame); +// whatstr = i18n("WHAT IS THIS: User login"); + addRow(frame, layout, row++, lbuser, i18n("User login:"), whatstr, false, false); + + leid = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: User Id"); + leid->setValidator(new QIntValidator(frame)); + addRow(frame, layout, row++, leid, i18n("&User ID:"), whatstr); + connect(leid, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + if ( !ro ) { + pbsetpwd = new QPushButton(i18n("Set &Password..."), frame); + layout->addWidget(pbsetpwd, 0, 2); + connect(pbsetpwd, SIGNAL(clicked()), this, SLOT(setpwd())); + } + + + lefname = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Full Name"); + addRow(frame, layout, row++, lefname, i18n("Full &name:"), whatstr); + connect(lefname, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + lefname->setFocus(); + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_InetOrg ) { + lesurname = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Surname"); + addRow(frame, layout, row++, lesurname, i18n("Surname:"), whatstr); + connect(lesurname, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + lemail = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Email"); + addRow(frame, layout, row++, lemail, i18n("Email address:"), whatstr); + connect(lemail, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + } + + leshell = new KComboBox(true, frame); + leshell->clear(); + leshell->insertItem(i18n("<Empty>")); + + QStringList shells = readShells(); + shells.sort(); + leshell->insertStringList(shells); + connect(leshell, SIGNAL(activated(const QString &)), this, SLOT(changed())); + connect(leshell, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Login Shell"); + addRow(frame, layout, row++, leshell, i18n("&Login shell:"), whatstr); + + lehome = new KLineEdit(frame); + connect(lehome, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Home Directory"); + addRow(frame, layout, row++, lehome, i18n("&Home folder:"), whatstr); + + // FreeBSD appears to use the comma separated fields in the GECOS entry + // differently than Linux. + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + leoffice = new KLineEdit(frame); + connect(leoffice, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Office"); + addRow(frame, layout, row++, leoffice, i18n("&Office:"), whatstr); + + leophone = new KLineEdit(frame); + connect(leophone, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Office Phone"); + addRow(frame, layout, row++, leophone, i18n("Offi&ce Phone:"), whatstr); + + lehphone = new KLineEdit(frame); + connect(lehphone, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Home Phone"); + addRow(frame, layout, row++, lehphone, i18n("Ho&me Phone:"), whatstr); + + leclass = new KLineEdit(frame); + connect(leclass, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Login class"); + addRow(frame, layout, row++, leclass, i18n("Login class:"), whatstr, true); + } else { + leoffice1 = new KLineEdit(frame); + connect(leoffice1, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Office1"); + addRow(frame, layout, row++, leoffice1, i18n("&Office #1:"), whatstr); + + leoffice2 = new KLineEdit(frame); + connect(leoffice2, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Office2"); + addRow(frame, layout, row++, leoffice2, i18n("O&ffice #2:"), whatstr); + + leaddress = new KLineEdit(frame); + connect(leaddress, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); +// whatstr = i18n("WHAT IS THIS: Address"); + addRow(frame, layout, row++, leaddress, i18n("&Address:"), whatstr); + } + cbdisabled = new QCheckBox(frame); + connect(cbdisabled, SIGNAL(stateChanged(int)), this, SLOT(changed())); + addRow(frame, layout, row++, cbdisabled, i18n("Account &disabled"), whatstr); + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Disable_POSIX ) { + cbposix = new QCheckBox(frame); + connect(cbposix, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(cbposix, SIGNAL(stateChanged(int)), this, SLOT(cbposixChanged())); + addRow(frame, layout, row++, cbposix, i18n("Disable &POSIX account information"), whatstr); + } else { + cbposix = 0; + } + frontrow = row; + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow || + kug->getUsers().getCaps() & KU::KUsers::Cap_Samba || + kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + + // Tab 2 : Password Management + QFrame *frame = addPage(i18n("Password Management")); + QGridLayout *layout = new QGridLayout(frame, 20, 4, marginHint(), spacingHint()); + int row = 0; + + QDateTime time; + leslstchg = new QLabel(frame); + addRow(frame, layout, row++, leslstchg, i18n("Last password change:"), QString::null, true); + + layout->addMultiCellWidget(new KSeparator(KSeparator::HLine, frame), row, row, 0, 3); + row++; + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow ) { + layout->addWidget( new QLabel( i18n("POSIX parameters:"), frame ), row++, 0 ); + lesmin = addDaysGroup(frame, layout, row++, i18n("Time before password may ¬ be changed after last password change:"), false); + lesmax = addDaysGroup(frame, layout, row++, i18n("Time when password &expires after last password change:") ); + leswarn = addDaysGroup(frame, layout, row++, i18n("Time before password expires to &issue an expire warning:")); + lesinact = addDaysGroup(frame, layout, row++, i18n("Time when account will be &disabled after expiration of password:")); + layout->addMultiCellWidget(new KSeparator(KSeparator::HLine, frame), row, row, 0, 3); + row++; + } + /* + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + layout->addWidget( new QLabel( "SAMBA parameters:", frame ), row++, 0 ); + layout->addMultiCellWidget(new KSeparator(KSeparator::HLine, frame), row, row, 0, 3); + row++; + } + */ + QLabel *label = new QLabel( i18n("&Account will expire on:"), frame ); + layout->addWidget( label, row, 0 ); + lesexpire = new KDateTimeWidget( frame ); + label->setBuddy( lesexpire ); + layout->addMultiCellWidget( lesexpire, row, row, 1, 2); + + cbexpire = new QCheckBox( i18n("Never"), frame ); + layout->addWidget( cbexpire, row++, 3 ); + + connect( lesexpire, SIGNAL(valueChanged(const QDateTime&)), this, SLOT(changed()) ); + connect( cbexpire, SIGNAL(stateChanged(int)), this, SLOT(changed()) ); + connect( cbexpire, SIGNAL(toggled(bool)), lesexpire, SLOT(setDisabled(bool)) ); + } + + // Tab 3: Samba + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + QFrame *frame = addPage(i18n("Samba")); + QGridLayout *layout = new QGridLayout(frame, 10, 4, marginHint(), spacingHint()); + int row = 0; + + lerid = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Rid"); + lerid->setValidator(new QIntValidator(frame)); + addRow(frame, layout, row++, lerid, i18n("RID:"), whatstr); + connect(lerid, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + leliscript = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, leliscript, i18n("Login script:"), whatstr); + connect(leliscript, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + leprofile = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, leprofile, i18n("Profile path:"), whatstr); + connect(leprofile, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + lehomedrive = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, lehomedrive, i18n("Home drive:"), whatstr); + connect(lehomedrive, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + lehomepath = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, lehomepath, i18n("Home path:"), whatstr); + connect(lehomepath, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + leworkstations = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, leworkstations, i18n("User workstations:"), whatstr); + connect(leworkstations, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + ledomain = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, ledomain, i18n("Domain name:"), whatstr); + connect(ledomain, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + ledomsid = new KLineEdit(frame); +// whatstr = i18n("WHAT IS THIS: Login script"); + addRow(frame, layout, row++, ledomsid, i18n("Domain SID:"), whatstr); + connect(ledomsid, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); + + cbsamba = new QCheckBox(frame); + connect(cbsamba, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(cbsamba, SIGNAL(stateChanged(int)), this, SLOT(cbsambaChanged())); + addRow(frame, layout, row++, cbsamba, i18n("Disable &Samba account information"), whatstr); + } + + // Tab 4: Groups + { + QFrame *frame = addPage(i18n("Groups")); + QGridLayout *layout = new QGridLayout(frame, 2, 2, marginHint(), spacingHint()); + + lstgrp = new KListView(frame); + lstgrp->setFullWidth(true); // Single column, full widget width. + lstgrp->addColumn( i18n("Groups") ); + if ( ro ) lstgrp->setSelectionMode( QListView::NoSelection ); +// QString whatstr = i18n("Select the groups that this user belongs to."); + QWhatsThis::add(lstgrp, whatstr); + layout->addMultiCellWidget(lstgrp, 0, 0, 0, 1); + leprigr = new QLabel( i18n("Primary group: "), frame ); + layout->addWidget( leprigr, 1, 0 ); + if ( !ro ) { + pbprigr = new QPushButton( i18n("Set as Primary"), frame ); + layout->addWidget( pbprigr, 1, 1 ); + connect( pbprigr, SIGNAL(clicked()), this, SLOT(setpgroup()) ); + } + connect( lstgrp, SIGNAL(clicked(QListViewItem *)), this, SLOT(gchanged()) ); + } + +} + +propdlg::propdlg( const QPtrList<KU::KUser> &users, + QWidget *parent, const char *name ) : + KDialogBase(Tabbed, i18n("User Properties"), Ok | Cancel, Ok, parent, name, true) + +{ + mUsers = users; + if ( mUsers.getFirst() != mUsers.getLast() ) + setCaption( i18n("User Properties - %1 Selected Users").arg( mUsers.count() ) ); + initDlg(); + loadgroups( false ); + selectuser(); + ischanged = false; + isgchanged = false; +} + +propdlg::propdlg( KU::KUser *AUser, bool fixedprivgroup, + QWidget *parent, const char *name ) : + KDialogBase(Tabbed, i18n("User Properties"), Ok | Cancel, Ok, parent, name, true) + +{ + mUsers.append( AUser ); + initDlg(); + loadgroups( fixedprivgroup ); + selectuser(); + ischanged = false; + isgchanged = false; +} + +propdlg::~propdlg() +{ +} + +void propdlg::cbposixChanged() +{ + bool posix = !( cbposix->state() == QButton::On ); + leid->setEnabled( posix & ( mUsers.getFirst() == mUsers.getLast() ) ); + leshell->setEnabled( posix ); + lehome->setEnabled( posix ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow ) { + lesmin->setEnabled( posix ); + lesmax->setEnabled( posix ); + leswarn->setEnabled( posix ); + lesinact->setEnabled( posix ); + } +} + +void propdlg::cbsambaChanged() +{ + bool samba = !( cbsamba->state() == QButton::On ); + lerid->setEnabled( samba & ( mUsers.getFirst() == mUsers.getLast() ) ); + leliscript->setEnabled( samba ); + leprofile->setEnabled( samba ); + lehomedrive->setEnabled( samba ); + lehomepath->setEnabled( samba ); + leworkstations->setEnabled( samba ); + ledomain->setEnabled( samba ); + ledomsid->setEnabled( samba ); +} + +void propdlg::setLE( KLineEdit *le, const QString &val, bool first ) +{ + if ( first ) { + le->setText( val ); + if ( ro ) le->setReadOnly( true ); + return; + } + if ( val.isEmpty() && le->text().isEmpty() ) return; + if ( le->text() != val ) { + le->setText( "" ); + if ( !ro && mNoChanges.contains( le ) ) { + mNoChanges[ le ]->show(); + mNoChanges[ le ]->setChecked( true ); + } + } +} + +void propdlg::setCB( QCheckBox *cb, bool val, bool first ) +{ + if ( first ) { + cb->setChecked( val ); + if ( ro ) cb->setEnabled( false ); + return; + } + if ( cb->isChecked() != val ) { + cb->setTristate(); + cb->setNoChange(); + } +} + +void propdlg::setSB( KIntSpinBox *sb, int val, bool first ) +{ + if ( first ) { + sb->setValue( val ); + if ( ro ) sb->setEnabled( false ); + return; + } + if ( sb->value() != val ) { + sb->setValue( 0 ); + if ( !ro && mNoChanges.contains( sb ) ) { + mNoChanges[ sb ]->show(); + mNoChanges[ sb ]->setChecked( true ); + } + } +} + +void propdlg::selectuser() +{ + KU::KUser *user; + bool first = true, one = ( mUsers.getFirst() == mUsers.getLast() ); + + ismoreshells = false; + user = mUsers.first(); + olduid = user->getUID(); + oldrid = user->getSID().getRID(); + oldshell = user->getShell(); + lstchg = user->getLastChange(); + QDateTime datetime; + datetime.setTime_t( lstchg ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow || + kug->getUsers().getCaps() & KU::KUsers::Cap_Samba || + kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + + leslstchg->setText( KGlobal::locale()->formatDateTime( datetime, false ) ); + } + + if ( one ) { + lbuser->setText( user->getName() ); + leid->setText( QString::number( user->getUID() ) ); + if ( ro ) leid->setReadOnly( true ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + lerid->setText( QString::number( user->getSID().getRID() ) ); + if ( ro ) lerid->setReadOnly( true ); + } + } else { + leid->setEnabled( false ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + lerid->setEnabled( false ); + } + } + if ( ro ) leshell->setEditable( false ); + + while ( user ) { + + setLE( lefname, user->getFullName(), first ); + QString home; + home = user->getHomeDir(); + if ( !one ) home.replace( user->getName(), "%U" ); + setLE( lehome, home, first ); + + QString shell = user->getShell(); + if ( first ) { + if ( !shell.isEmpty() ) { + bool tested = false; + for ( int i=0; i<leshell->count(); i++ ) + if ( leshell->text(i) == shell ) { + tested = true; + leshell->setCurrentItem(i); + break; + } + if ( !tested ) { + leshell->insertItem( shell ); + leshell->setCurrentItem( leshell->count()-1 ); + } + } else + leshell->setCurrentItem(0); + } else { + if ( leshell->currentText() != shell ) { + if ( !ismoreshells ) { + leshell->insertItem( i18n("Do Not Change"), 0 ); + ismoreshells = true; + } + leshell->setCurrentItem( 0 ); + } + } + + setCB( cbdisabled, user->getDisabled(), first ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Disable_POSIX ) { + setCB( cbposix, !(user->getCaps() & KU::KUser::Cap_POSIX), first ); + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + setLE( leliscript, user->getLoginScript(), first ); + QString profile; + profile = user->getProfilePath(); + if ( !one ) profile.replace( user->getName(), "%U" ); + setLE( leprofile, profile, first ); + setLE( lehomedrive, user->getHomeDrive(), first ); + home = user->getHomePath(); + if ( !one ) home.replace( user->getName(), "%U" ); + setLE( lehomepath, home, first ); + setLE( leworkstations, user->getWorkstations(), first ); + setLE( ledomain, user->getDomain(), first ); + setLE( ledomsid, user->getSID().getDOM(), first ); + setCB( cbsamba, !(user->getCaps() & KU::KUser::Cap_Samba), first ); + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow || + kug->getUsers().getCaps() & KU::KUsers::Cap_Samba || + kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + + if ( user->getLastChange() != lstchg ) { + leslstchg->setText( "" ); + lstchg = 0; + } + + QDateTime expire; + expire.setTime_t( user->getExpire() ); + kdDebug() << "expiration: " << user->getExpire() << endl; + setCB( cbexpire, (int) expire.toTime_t() == -1, first ); + if ( (int) expire.toTime_t() == -1 ) expire.setTime_t( 0 ); + if ( first ) { + lesexpire->setDateTime( expire ); + } else { + if ( lesexpire->dateTime() != expire ) { + expire.setTime_t( 0 ); + lesexpire->setDateTime( expire ); + } + } + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow ) { + setSB( lesmin, user->getMin(), first ); + setSB( lesmax, user->getMax(), first ); + setSB( leswarn, user->getWarn(), first ); + setSB( lesinact, user->getInactive(), first ); + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_InetOrg ) { + setLE( lesurname, user->getSurname(), first ); + setLE( lemail, user->getEmail(), first ); + } + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + setLE( leoffice, user->getOffice(), first ); + setLE( leophone, user->getWorkPhone(), first ); + setLE( lehphone, user->getHomePhone(), first ); + setLE( leclass, user->getClass(), first ); + } else { + setLE( leoffice1, user->getOffice1(), first ); + setLE( leoffice2, user->getOffice2(), first ); + setLE( leaddress, user->getAddress(), first ); + } + + first = false; + user = mUsers.next(); + } +} + +void propdlg::loadgroups( bool fixedprivgroup ) +{ + bool wasprivgr = false; + + primaryGroupWasOn = false; + + KU::KGroup *group = kug->getGroups().first(); + while ( group ) { + QString groupName = group->getName(); + QCheckListItem *item = new QCheckListItem(lstgrp, groupName, QCheckListItem::CheckBox); + KU::KUser *user = mUsers.first(); + while ( user ) { + bool prigr = + ( !fixedprivgroup && group->getGID() == user->getGID() ) || + ( fixedprivgroup && groupName == user->getName() ); + bool on = group->lookup_user( user->getName() ) || prigr; + + if ( prigr ) { + item->setEnabled( false ); + if ( !wasprivgr ) + primaryGroup = groupName; + else + if ( primaryGroup != groupName ) primaryGroup = ""; +// primaryGroupWasOn = group->lookup_user(user->getName()); + wasprivgr = true; + } + + if ( mUsers.getFirst() == user ) + item->setOn( on ); + else + if ( item->isOn() != on ) { + item->setTristate( true ); + item->setState( QCheckListItem::NoChange ); + } + user = mUsers.next(); + } + group = kug->getGroups().next(); + } + + if ( fixedprivgroup ) { + KU::KUser *user = mUsers.first(); + kdDebug() << "privgroup: " << user->getName() << endl; + if ( !wasprivgr ) { + QCheckListItem *item = new QCheckListItem(lstgrp, user->getName(), QCheckListItem::CheckBox); + item->setOn(true); + item->setEnabled(false); + primaryGroup = user->getName(); + } + } + leprigr->setText( i18n("Primary group: ") + primaryGroup ); +} + +void propdlg::setpgroup() +{ + isgchanged = true; + QCheckListItem *item; + item = (QCheckListItem *) lstgrp->selectedItem(); + if ( item == 0 || item->text() == primaryGroup ) + return; + + bool prevPrimaryGroupWasOn = primaryGroupWasOn; + primaryGroup = ((QCheckListItem *) lstgrp->selectedItem())->text(); + + item = (QCheckListItem *) lstgrp->firstChild(); + + while(item) + { + QString groupName = item->text(); + if ( !item->isEnabled() ) + { + item->setEnabled(true); + item->setOn(prevPrimaryGroupWasOn); + item->repaint(); + } + if ( groupName == primaryGroup ) + { + primaryGroupWasOn = item->isOn(); + item->setEnabled(false); + item->setOn(true); + item->repaint(); + } + + item = (QCheckListItem *) item->nextSibling(); + } + leprigr->setText( i18n("Primary group: ") + primaryGroup ); +} + +void propdlg::changed() +{ + QWidget *widget = (QWidget*) sender(); + if ( mNoChanges.contains( widget ) ) mNoChanges[ widget ]->setChecked( false ); + ischanged = true; + kdDebug() << "changed" << endl; +} + +void propdlg::gchanged() +{ + isgchanged = true; +} + +QString propdlg::mergeLE( KLineEdit *le, const QString &val, bool one ) +{ + QCheckBox *cb = 0; + if ( mNoChanges.contains( le ) ) cb = mNoChanges[ le ]; + return ( one || ( cb && !cb->isChecked() ) ) ? le->text() : val; +} + +int propdlg::mergeSB( KIntSpinBox *sb, int val, bool one ) +{ + QCheckBox *cb = 0; + if ( mNoChanges.contains( sb ) ) cb = mNoChanges[ sb ]; + return ( one || ( cb && !cb->isChecked() ) ) ? sb->value() : val; +} + +void propdlg::mergeUser( KU::KUser *user, KU::KUser *newuser ) +{ + QDateTime epoch ; + epoch.setTime_t(0); + bool one = ( mUsers.getFirst() == mUsers.getLast() ); + bool posix, samba = false; + + newuser->copy( user ); + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Disable_POSIX && cbposix->state() != QButton::NoChange ) { + if ( cbposix->isChecked() ) + newuser->setCaps( newuser->getCaps() & ~KU::KUser::Cap_POSIX ); + else + newuser->setCaps( newuser->getCaps() | KU::KUser::Cap_POSIX ); + } + posix = newuser->getCaps() & KU::KUser::Cap_POSIX; + kdDebug() << "posix: " << posix << endl; + if ( one ) { +// newuser->setName( leuser->text() ); + newuser->setUID( posix ? leid->text().toInt() : 0 ); + } + if ( !newpass.isNull() ) { + kug->getUsers().createPassword( newuser, newpass ); + newuser->setLastChange( lstchg ); + } + newuser->setFullName( mergeLE( lefname, user->getFullName(), one ) ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + if ( cbsamba->state() != QButton::NoChange ) { + if ( cbsamba->isChecked() ) + newuser->setCaps( newuser->getCaps() & ~KU::KUser::Cap_Samba ); + else + newuser->setCaps( newuser->getCaps() | KU::KUser::Cap_Samba ); + } + samba = newuser->getCaps() & KU::KUser::Cap_Samba; + kdDebug() << "user : " << newuser->getName() << " caps: " << newuser->getCaps() << " samba: " << samba << endl; + + SID sid; + if ( samba ) { + sid.setRID( one ? lerid->text().toUInt() : user->getSID().getRID() ); + sid.setDOM( mergeLE( ledomsid, user->getSID().getDOM(), one ) ); + } + newuser->setSID( sid ); + newuser->setLoginScript( samba ? + mergeLE( leliscript, user->getLoginScript(), one ) : QString::null ); + newuser->setProfilePath( samba ? + mergeLE( leprofile, user->getProfilePath(), one ).replace( "%U", newuser->getName() ) : QString::null ); + newuser->setHomeDrive( samba ? + mergeLE( lehomedrive, user->getHomeDrive(), one ) : QString::null ); + newuser->setHomePath( samba ? + mergeLE( lehomepath, user->getHomePath(), one ).replace( "%U", newuser->getName() ) : QString::null ); + newuser->setWorkstations( samba ? + mergeLE( leworkstations, user->getWorkstations(), one ) : QString::null ); + newuser->setDomain( samba ? + mergeLE( ledomain, user->getDomain(), one ) : QString::null ); + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + newuser->setOffice( mergeLE( leoffice, user->getOffice(), one ) ); + newuser->setWorkPhone( mergeLE( leophone, user->getWorkPhone(), one ) ); + newuser->setHomePhone( mergeLE( lehphone, user->getHomePhone(), one ) ); + newuser->setClass( mergeLE( leclass, user->getClass(), one ) ); + } else { + newuser->setOffice1( mergeLE( leoffice1, user->getOffice1(), one ) ); + newuser->setOffice2( mergeLE( leoffice2, user->getOffice2(), one ) ); + newuser->setAddress( mergeLE( leaddress, user->getAddress(), one ) ); + } + + newuser->setHomeDir( posix ? + mergeLE( lehome, user->getHomeDir(), one ).replace( "%U", newuser->getName() ) : + QString::null ); + if ( posix ) { + if ( leshell->currentItem() == 0 && ismoreshells ) { + newuser->setShell( user->getShell() ); + } else if ( + ( leshell->currentItem() == 0 && !ismoreshells ) || + ( leshell->currentItem() == 1 && ismoreshells ) ) { + + newuser->setShell( QString::null ); + } else { + // TODO: Check shell. + newuser->setShell( leshell->currentText() ); + } + } else + newuser->setShell( QString::null ); + + newuser->setDisabled( (cbdisabled->state() == QButton::NoChange) ? user->getDisabled() : cbdisabled->isChecked() ); + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_InetOrg ) { + newuser->setSurname( mergeLE( lesurname, user->getSurname(), one ) ); + newuser->setEmail( mergeLE( lemail, user->getEmail(), one ) ); + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow ) { + newuser->setMin( posix ? mergeSB( lesmin, user->getMin(), one ) : 0 ); + newuser->setMax( posix ? mergeSB( lesmax, user->getMax(), one ) : 0 ); + newuser->setWarn( posix ? mergeSB( leswarn, user->getWarn(), one ) : 0 ); + newuser->setInactive( posix ? mergeSB( lesinact, user->getInactive(), one ) : 0 ); + } + + if ( ( (kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow) && posix ) || + ( (kug->getUsers().getCaps() & KU::KUsers::Cap_Samba) && samba ) || + ( (kug->getUsers().getCaps() & KU::KUsers::Cap_BSD) && posix ) ) { + + switch ( cbexpire->state() ) { + case QButton::NoChange: + newuser->setExpire( user->getExpire() ); + break; + case QButton::On: + newuser->setExpire( -1 ); + break; + case QButton::Off: + newuser->setExpire( !one && lesexpire->dateTime().toTime_t() == 0 ? + user->getExpire() : lesexpire->dateTime().toTime_t() ); + break; + } + } else { + newuser->setExpire( -1 ); + } + + if ( !primaryGroup.isEmpty() ) { + KU::KGroup *group = kug->getGroups().lookup( primaryGroup ); + if ( group ) { + newuser->setGID( group->getGID() ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + newuser->setPGSID( group->getSID() ); + } + } + } +} + +bool propdlg::saveg() +{ + if ( !isgchanged ) return true; + + QCheckListItem *item = (QCheckListItem *) lstgrp->firstChild(); + KU::KGroup *group; + + while(item) + { + kdDebug() << "saveg: group name: " << item->text() << endl; + group = kug->getGroups().lookup(item->text()); + if ( group && item->state() != QCheckListItem::NoChange ) { + + KU::KGroup newgroup( group ); + bool mod = false; + bool on = item->isOn(); + KU::KUser *user = mUsers.first(); + + while ( user ) { + if ( on && (( !primaryGroup.isEmpty() && primaryGroup != group->getName() ) || + ( primaryGroup.isEmpty() && user->getGID() != group->getGID() )) ) { + if ( newgroup.addUser( user->getName() ) ) mod = true; + } else { + if ( newgroup.removeUser( user->getName() ) ) mod = true; + } + user = mUsers.next(); + } + + if ( mod ) kug->getGroups().mod( group, newgroup ); + } + item = (QCheckListItem *) item->nextSibling(); + } + return true; +} + +bool propdlg::checkShell(const QString &shell) +{ + if (shell.isEmpty()) + return true; + QStringList shells = readShells(); + return shells.contains(shell); +} + +bool propdlg::check() +{ + bool one = ( mUsers.getFirst() == mUsers.getLast() ); + bool posix = !( kug->getUsers().getCaps() & KU::KUsers::Cap_Disable_POSIX ) || !( cbposix->isChecked() ); + + if ( one && posix && leid->text().isEmpty() ) { + KMessageBox::sorry( 0, i18n("You need to specify an UID.") ); + return false; + } + + if ( one && posix && lehome->text().isEmpty() ) { + KMessageBox::sorry( 0, i18n("You must specify a home directory.") ); + return false; + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_InetOrg ) { + if ( one && lesurname->text().isEmpty() ) { + KMessageBox::sorry( 0, i18n("You must fill the surname field.") ); + return false; + } + } + + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) { + if ( one && lerid->text().isEmpty() && !( cbsamba->isChecked() ) ) { + KMessageBox::sorry( 0, i18n("You need to specify a samba RID.") ); + return false; + } + } + + return true; +} + +void propdlg::setpwd() +{ + pwddlg pd( this ); + + if ( pd.exec() == QDialog::Accepted ) { + ischanged = true; + newpass = pd.getPassword(); + lstchg = now(); + QDateTime datetime; + datetime.setTime_t( lstchg ); + if ( kug->getUsers().getCaps() & KU::KUsers::Cap_Shadow || + kug->getUsers().getCaps() & KU::KUsers::Cap_Samba || + kug->getUsers().getCaps() & KU::KUsers::Cap_BSD ) { + + leslstchg->setText( KGlobal::locale()->formatDateTime( datetime, false ) ); + } + cbdisabled->setChecked( false ); + } +} + +void propdlg::slotOk() +{ + if ( ro ) { + reject(); + return; + } + + bool one = ( mUsers.getFirst() == mUsers.getLast() ); + + uid_t newuid = leid->text().toULong(); + + if ( one && ( !( kug->getUsers().getCaps() & KU::KUsers::Cap_Disable_POSIX ) || !cbposix->isChecked() ) + && olduid != newuid ) + { + if (kug->getUsers().lookup(newuid)) { + KMessageBox::sorry( 0, + i18n("User with UID %1 already exists").arg(newuid) ); + return; + } + } + + if ( one && ( kug->getUsers().getCaps() & KU::KUsers::Cap_Samba ) && !cbsamba->isChecked() ) { + uint newrid = lerid->text().toInt(); + if ( oldrid != newrid ) { + if (kug->getUsers().lookup_sam(newrid)) { + KMessageBox::sorry( 0, + i18n("User with RID %1 already exists").arg(newrid) ); + return; + } + } + } + + QString newshell; + if (leshell->currentItem() != 0) + newshell = leshell->currentText(); + + if (oldshell != newshell) + { + if (!checkShell(newshell)) { + int result = KMessageBox::warningYesNoCancel( 0, + i18n("<p>The shell %1 is not yet listed in the file %2. " + "In order to use this shell you must add it to " + "this file first." + "<p>Do you want to add it now?").arg(newshell).arg(QFile::decodeName(SHELL_FILE)), + i18n("Unlisted Shell"), + i18n("&Add Shell"), + i18n("Do &Not Add")); + if (result == KMessageBox::Cancel) + return; + + if (result == KMessageBox::Yes) + addShell(newshell); + } + } + + if ( !ischanged && !isgchanged ) { + reject(); + } else if ( check() ) { + saveg(); + accept(); + } +} + +#include "propdlg.moc" diff --git a/kuser/propdlg.h b/kuser/propdlg.h new file mode 100644 index 0000000..2832574 --- /dev/null +++ b/kuser/propdlg.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_PROPDLG_H_ +#define _KU_PROPDLG_H_ + +#include <qlabel.h> +#include <qpushbutton.h> +#include <qwidget.h> +#include <qlistbox.h> +#include <qtooltip.h> +#include <qcheckbox.h> +#include <qlayout.h> +#include <qmap.h> + +#include <klineedit.h> +#include <kdatetimewidget.h> +#include <knuminput.h> +#include <kdialogbase.h> +#include <klistview.h> +#include <kcombobox.h> + +#include "kuser.h" + +class propdlg : public KDialogBase +{ + Q_OBJECT + +public: + propdlg( const QPtrList<KU::KUser> &users, + QWidget *parent = 0, const char *name = 0 ); + propdlg( KU::KUser *AUser, bool fixedprivgroup, + QWidget *parent = 0, const char *name = 0 ); + ~propdlg(); + + void mergeUser( KU::KUser *user, KU::KUser *newuser ); + +protected slots: + virtual void slotOk(); + void setpwd(); + void changed(); // Change to misc settings + void cbposixChanged(); // Change to diaable POSIX account info + void cbsambaChanged(); // Change to diaable POSIX account info + void gchanged(); // Change to group settings + void setpgroup(); // Change in primary group + +protected: + void initDlg(); + void selectuser(); + void save(); + bool saveg(); + bool check(); + void loadgroups( bool fixedprivgroup ); + bool checkShell(const QString &shell); + void addRow( QWidget *parent, QGridLayout *layout, int row, + QWidget *widget, const QString &label, const QString &what, + bool two_column=true, bool nochange=true ); + void setLE( KLineEdit *le, const QString &val, bool first ); + void setCB( QCheckBox *cb, bool val, bool first ); + void setSB( KIntSpinBox *sb, int val, bool first ); + QString mergeLE( KLineEdit *le, const QString &val, bool one ); + int mergeSB( KIntSpinBox *sb, int val, bool one ); + + KIntSpinBox *addDaysGroup( QWidget *parent, QGridLayout *layout, int row, + const QString &title, bool never=true ); + + QFrame *frontpage; + QGridLayout *frontlayout; + int frontrow; + + QPtrList<KU::KUser> mUsers; + QMap<QWidget*, QCheckBox*> mNoChanges; + bool ismoreshells; + bool ischanged; + bool isgchanged; + uid_t olduid; + uint oldrid; + QString oldshell; + QString primaryGroup; + bool primaryGroupWasOn; + bool ro; + + QString newpass; + time_t lstchg; + + KListView *lstgrp; + + QPushButton *pbsetpwd; + + QLabel *lbuser; + KLineEdit *leid; + KLineEdit *lefname; + KLineEdit *lesurname; + KLineEdit *lemail; + + KComboBox *leshell; + KLineEdit *lehome; + + KLineEdit *leoffice; + KLineEdit *leophone; + KLineEdit *lehphone; + KLineEdit *leclass; + + KLineEdit *leoffice1; + KLineEdit *leoffice2; + KLineEdit *leaddress; + + QCheckBox *cbdisabled; + QCheckBox *cbposix; + QCheckBox *cbsamba; + QLabel *leprigr; + QPushButton *pbprigr; + + QLabel *leslstchg; + KIntSpinBox *lesmin; + KIntSpinBox *lesmax; + KIntSpinBox *leswarn; + KIntSpinBox *lesinact; + KDateTimeWidget *lesexpire; + QCheckBox *cbexpire; + +//samba specific: + KLineEdit *lerid; + KLineEdit *leliscript; + KLineEdit *leprofile; + KLineEdit *lehomedrive; + KLineEdit *lehomepath; + KLineEdit *leworkstations; + KLineEdit *ledomain; + KLineEdit *ledomsid; +}; + +#endif // _KU_PROPDLG_H_ + diff --git a/kuser/pwddlg.cpp b/kuser/pwddlg.cpp new file mode 100644 index 0000000..3c8f9cd --- /dev/null +++ b/kuser/pwddlg.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Former maintainer: Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qgrid.h> + +#include <kmessagebox.h> + +#include "pwddlg.h" +#include "misc.h" + +pwddlg::pwddlg( QWidget* parent, const char* name ) + : KDialogBase(parent, name, true, i18n("Enter Password"), Ok | Cancel, Ok, true) +{ + QGrid *page = makeGridMainWidget(2, QGrid::Horizontal); + + QLabel* lb1 = new QLabel(page, "lb1"); + lb1->setText(i18n("Password:")); + lb1->setMinimumSize(lb1->sizeHint()); + lb1->setAlignment(AlignRight|AlignVCenter); + + lepw1 = new KLineEdit(page, "LineEdit_1"); + + // ensure it fits at least 12 characters + lepw1->setText( "XXXXXXXXXXXX" ); + lepw1->setMinimumSize(lepw1->sizeHint()); + + // clear text + lepw1->clear(); + lepw1->setFocus(); + lepw1->setEchoMode(KLineEdit::Password); + + QLabel* lb2 = new QLabel(page, "lb2"); + lb2->setText(i18n("Verify:")); + lb2->setMinimumSize(lb2->sizeHint()); + lb2->setAlignment(AlignRight|AlignVCenter); + + lepw2 = new KLineEdit(page, "LineEdit_2"); + + // ensure it fits at least 12 characters + lepw2->setText( "XXXXXXXXXXXX" ); + lepw2->setMinimumSize(lepw2->sizeHint()); + + // clear text + lepw2->clear(); + lepw2->setEchoMode(KLineEdit::Password); +} + +pwddlg::~pwddlg() +{ + delete lepw1; + delete lepw2; +} + +void pwddlg::slotOk() +{ + if ( lepw1->text() != lepw2->text() ) { + KMessageBox::sorry( 0, i18n("Passwords are not identical.\nTry again.") ); + lepw1->clear(); + lepw2->clear(); + lepw1->setFocus(); + } else { + accept(); + } +} + +QString pwddlg::getPassword() const +{ + return lepw1->text(); +} + +#include "pwddlg.moc" diff --git a/kuser/pwddlg.h b/kuser/pwddlg.h new file mode 100644 index 0000000..485a806 --- /dev/null +++ b/kuser/pwddlg.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998 Denis Perchine <dyp@perchine.com> + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * Maintained by Adriaan de Groot <groot@kde.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_PWDDLG_H_ +#define _KU_PWDDLG_H_ + +#include <qstring.h> +#include <klineedit.h> +#include <kdialogbase.h> + +class pwddlg : public KDialogBase { + Q_OBJECT + +public: + pwddlg( QWidget* parent = NULL, const char* name = NULL ); + ~pwddlg(); + + QString getPassword() const; +protected slots: + void slotOk(); + +private: + KLineEdit *lepw1; + KLineEdit *lepw2; +}; + +#endif // _KU_PWDDLG_H_ diff --git a/kuser/selectconn.cpp b/kuser/selectconn.cpp new file mode 100644 index 0000000..f5a6385 --- /dev/null +++ b/kuser/selectconn.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include <qpixmap.h> +#include <qlayout.h> + +#include <qlabel.h> +#include <qgrid.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <kapplication.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kinputdialog.h> + +#include "kglobal_.h" +#include "selectconn.h" +#include "editDefaults.h" + +SelectConn::SelectConn(const QString &selected, QWidget* parent, const char * name) : + KDialogBase( Plain, WStyle_DialogBorder, parent, name, true, + i18n("Connection Selection"), Ok | Apply | Cancel | User1 | User2 | User3 ) +{ + QStringList conns; + + setButtonText( User3, i18n("&New...") ); + setButtonText( User2, i18n("&Edit") ); + setButtonText( User1, i18n("&Delete") ); + + QFrame *page = plainPage(); + QVBoxLayout *topLayout = new QVBoxLayout( page, 0, KDialog::spacingHint() ); + QLabel *label = new QLabel( i18n("Defined connections:"), page ); + mCombo = new KComboBox( page ); + mSelected = selected; + kdDebug() << "selected item: " << mSelected << endl; + + conns = kapp->sharedConfig()->groupList(); + QStringList::iterator it = conns.begin(); + int i = 0, sel = 0; + while ( it != conns.end() ) { + if ( (*it).startsWith( "connection-" ) ) { + (*it).remove( QRegExp("^connection-") ); + if ( (*it) == mSelected ) sel = i; + i++; + it++; + } else + it = conns.remove( it ); + } + mCombo->insertStringList( conns ); + if ( mCombo->count() == 0 ) mCombo->insertItem( "default" ); + mCombo->setCurrentItem( sel ); + mSelected = connSelected(); + topLayout->addWidget( label ); + topLayout->addWidget( mCombo ); +} + +QString SelectConn::connSelected() +{ + return mCombo->currentText(); +} + +void SelectConn::slotUser3() +{ + newconn = KInputDialog::getText( QString::null, + i18n("Please type the name of the new connection:") ); + if ( newconn.isEmpty() ) return; + if ( kapp->sharedConfig()->groupList().contains( "connection-" + newconn ) ) { + KMessageBox::sorry( 0, i18n("A connection with this name already exists.") ); + return; + } + + KUserPrefsBase kcfg( kapp->sharedConfig(), newconn ); + + editDefaults eddlg( &kcfg, this ); + connect(&eddlg, SIGNAL(settingsChanged()), this, SLOT(slotNewApplySettings())); + eddlg.exec(); + + if ( newconn.isEmpty() ) + emit( applyClicked() ); +} + +void SelectConn::slotNewApplySettings() +{ + if ( !newconn.isEmpty() ) { + mCombo->insertItem( newconn ); + mCombo->setCurrentItem( mCombo->count()-1 ); + mSelected = newconn; + } +} + +void SelectConn::slotUser2() +{ + kdDebug() << "slotUser2: " << connSelected() << endl; + KUserPrefsBase kcfg( kapp->sharedConfig(), connSelected() ); + kcfg.readConfig(); + + editDefaults eddlg( &kcfg, this ); + connect( &eddlg, SIGNAL(settingsChanged()), this, SLOT(slotApplySettings()) ); + + eddlg.exec(); +} + +void SelectConn::slotUser1() +{ + QString conn = connSelected(); + if ( KMessageBox::warningContinueCancel( 0, i18n("Do you really want to delete the connection '%1'?"). + arg( conn ),i18n("Delete Connection"),KStdGuiItem::del() ) == KMessageBox::Cancel ) return; + + kapp->sharedConfig()->deleteGroup( "connection-" + conn, true ); + kapp->sharedConfig()->sync(); + mCombo->removeItem( mCombo->currentItem() ); + if ( mCombo->count() == 0 ) { + mCombo->insertItem( "default" ); + mCombo->setCurrentItem( 0 ); + } + kdDebug() << "slotUser1: " << conn << " " << mSelected << endl; + if ( mSelected == conn ) + emit( applyClicked() ); +} + +void SelectConn::slotApply() +{ + kdDebug() << "slotApply()" << endl; + if ( connSelected() != mSelected ) { + mSelected = connSelected(); + emit( applyClicked() ); + } +} + +void SelectConn::slotApplySettings() +{ + kdDebug() << "slotApplySettings()" << endl; + if ( connSelected() == mSelected ) + emit( applyClicked() ); +} + +#include "selectconn.moc" diff --git a/kuser/selectconn.h b/kuser/selectconn.h new file mode 100644 index 0000000..674e148 --- /dev/null +++ b/kuser/selectconn.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2004 Szombathelyi György <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _KU_SELECTCONN_H_ +#define _KU_SELECTCONN_H_ + +#include <kdialogbase.h> +#include <kcombobox.h> + +class SelectConn : public KDialogBase { + Q_OBJECT +public: + SelectConn( const QString &selected, QWidget* parent, const char * name); + QString connSelected(); +protected slots: + void slotUser1(); + void slotUser2(); + void slotUser3(); + void slotNewApplySettings(); + void slotApplySettings(); + void slotApply(); + +protected: + KComboBox *mCombo; + QString conn, newconn, mSelected; +}; + +#endif // _KU_SELECTCONN_H_ diff --git a/kuser/sha1.cpp b/kuser/sha1.cpp new file mode 100644 index 0000000..6d8a1f0 --- /dev/null +++ b/kuser/sha1.cpp @@ -0,0 +1,179 @@ +/* + * Cryptographic API. + * + * SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. Originally based on the public domain + * implementation written by Steve Reid. + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> + * + * 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. + * + */ + +#include <config.h> + +#include <string.h> + +#include "sha1.h" + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_HMAC_BLOCK_SIZE 64 + +static inline Q_UINT32 rol(Q_UINT32 value, Q_UINT32 bits) +{ + return (((value) << (bits)) | ((value) >> (32 - (bits)))); +} + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +# define blk0(i) block32[i] + +#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \ + ^block32[(i+2)&15]^block32[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \ + w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \ + w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \ + w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +static void sha1_transform(Q_UINT32 *state, const Q_UINT8 *in) +{ + Q_UINT32 a, b, c, d, e; + Q_UINT32 block32[16]; + + /* convert/copy data to workspace */ + for (a = 0; a < sizeof(block32)/sizeof(Q_UINT32); a++) +#ifdef WORDS_BIGENDIAN + block32[a] = ((const Q_UINT32 *)in)[a]; +#else + block32[a] = ((const Q_UINT32 *)in)[a] >> 24 | + (((const Q_UINT32 *)in)[a] >> 8 & 0x0000ff00) | + (((const Q_UINT32 *)in)[a] << 8 & 0x00ff0000) | + (((const Q_UINT32 *)in)[a] << 24); +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variabes */ + a = b = c = d = e = 0; + memset (block32, 0x00, sizeof block32); +} + +void sha1_init(void *ctx) +{ + struct sha1_ctx *sctx = (sha1_ctx*) ctx; + static const struct sha1_ctx initstate = { + 0, + { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, + { 0, } + }; + + *sctx = initstate; +} + +void sha1_update(void *ctx, const Q_UINT8 *data, unsigned int len) +{ + struct sha1_ctx *sctx = (sha1_ctx*) ctx; + unsigned int i, j; + + j = (sctx->count >> 3) & 0x3f; + sctx->count += len << 3; + + if ((j + len) > 63) { + memcpy(&sctx->buffer[j], data, (i = 64-j)); + sha1_transform(sctx->state, sctx->buffer); + for ( ; i + 63 < len; i += 64) { + sha1_transform(sctx->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&sctx->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ +void sha1_final(void* ctx, Q_UINT8 *out) +{ + struct sha1_ctx *sctx = (sha1_ctx*) ctx; + Q_UINT32 i, j, index, padlen; + Q_UINT64 t; + Q_UINT8 bits[8] = { 0, }; + static const Q_UINT8 padding[64] = { 0x80, }; + + t = sctx->count; + bits[7] = 0xff & t; t>>=8; + bits[6] = 0xff & t; t>>=8; + bits[5] = 0xff & t; t>>=8; + bits[4] = 0xff & t; t>>=8; + bits[3] = 0xff & t; t>>=8; + bits[2] = 0xff & t; t>>=8; + bits[1] = 0xff & t; t>>=8; + bits[0] = 0xff & t; + + /* Pad out to 56 mod 64 */ + index = (sctx->count >> 3) & 0x3f; + padlen = (index < 56) ? (56 - index) : ((64+56) - index); + sha1_update(sctx, padding, padlen); + + /* Append length */ + sha1_update(sctx, bits, sizeof bits); + + /* Store state in digest */ + for (i = j = 0; i < 5; i++, j += 4) { + Q_UINT32 t2 = sctx->state[i]; + out[j+3] = t2 & 0xff; t2>>=8; + out[j+2] = t2 & 0xff; t2>>=8; + out[j+1] = t2 & 0xff; t2>>=8; + out[j ] = t2 & 0xff; + } + + /* Wipe context */ + memset(sctx, 0, sizeof *sctx); +} + diff --git a/kuser/sha1.h b/kuser/sha1.h new file mode 100644 index 0000000..d6b62ad --- /dev/null +++ b/kuser/sha1.h @@ -0,0 +1,36 @@ +/* + * Cryptographic API. + * + * SHA1 Secure Hash Algorithm. + * + * Derived from cryptoapi implementation, adapted for in-place + * scatterlist interface. Originally based on the public domain + * implementation written by Steve Reid. + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> + * + * 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. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#include <qglobal.h> + +struct sha1_ctx { + Q_UINT64 count; + Q_UINT32 state[5]; + Q_UINT8 buffer[64]; +}; + +void sha1_init(void *ctx); +void sha1_update(void *ctx, const Q_UINT8 *data, unsigned int len); +void sha1_final(void* ctx, Q_UINT8 *out); + +#endif diff --git a/kuser/sid.cpp b/kuser/sid.cpp new file mode 100644 index 0000000..e1080c6 --- /dev/null +++ b/kuser/sid.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2004 Szombathelyi Gyrgy <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#include "sid.h" +#include <kdebug.h> +//From Samba +/* Take the bottom bit. */ +#define RID_MULTIPLIER 2 + +/* The two common types. */ +#define USER_RID_TYPE 0 +#define GROUP_RID_TYPE 1 + +uint SID::mAlgRidBase = 1000; + +SID::SID() +{ + mRid = 0; mSid = QString::null; mDom = QString::null; +} + +SID::SID( const SID &sid ) +{ + setSID( sid.getSID() ); +} + +SID::SID( const QString &sid ) +{ + setSID( sid ); +} + +SID::~SID() +{ +} + +uint SID::uid2rid( uint uid ) +{ + return( (( uid*RID_MULTIPLIER ) + mAlgRidBase ) | USER_RID_TYPE ); +} + +uint SID::gid2rid( uint gid ) +{ + return( (( gid*RID_MULTIPLIER ) + mAlgRidBase ) | GROUP_RID_TYPE ); +} + +bool SID::operator == ( const SID &sid ) const +{ + return ( mSid == sid.mSid && mDom == sid.mDom ); +} + +bool SID::operator != ( const SID&sid ) const +{ + return ( mSid != sid.mSid || mDom != sid.mDom ); +} + +bool SID::isEmpty() const +{ + return ( ( mSid.isEmpty() || mRid == 0 ) && mDom.isEmpty() ); +} + +void SID::updateSID() +{ + mSid = mDom + QString::fromLatin1("-") + QString::number( mRid ); +} + +void SID::setSID( const QString &sid ) +{ + int pos; + QString rid; + + mSid = sid; + pos = sid.findRev( '-' ); + mDom = sid.left( pos ); + rid = sid.right( sid.length() - pos - 1 ); + mRid = rid.toUInt(); +} + +void SID::setRID( const QString &rid ) +{ + mRid = rid.toUInt(); + updateSID(); +} + +void SID::setRID( uint rid ) +{ + mRid = rid; + updateSID(); +} + +void SID::setDOM( const QString &dom ) +{ + mDom = dom; + updateSID(); +} + +const QString& SID::getSID() const +{ + return mSid; +} + +uint SID::getRID() const +{ + return mRid; +} + +const QString& SID::getDOM() const +{ + return mDom; +} diff --git a/kuser/sid.h b/kuser/sid.h new file mode 100644 index 0000000..e856b77 --- /dev/null +++ b/kuser/sid.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004 Szombathelyi Gyrgy <gyurco@freemail.hu> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#ifndef _SID_H_ +#define _SID_H_ + +#include <qstring.h> + +class SID { + +public: + SID(); + SID( const QString &sid ); + SID( const SID &sid ); + ~SID(); + + bool operator== ( const SID &sid ) const; + bool operator!= ( const SID &sid ) const; + bool isEmpty() const; + void setSID( const QString &sid ); + void setRID( const QString &rid ); + void setRID( uint rid ); + void setDOM( const QString &dom ); + const QString &getSID() const; + uint getRID() const ; + const QString &getDOM() const; + + static uint uid2rid( uint uid ); + static uint gid2rid( uint gid ); + static void setAlgRidBase( uint base ) { mAlgRidBase = base; }; + static uint getAlgRidBase() { return mAlgRidBase; }; +private: + void updateSID(); + QString mSid, mDom; + uint mRid; + static uint mAlgRidBase; +}; + +#endif //_SID_H_ diff --git a/kuser/stamp-h.in b/kuser/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/kuser/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/kuser/toolbar/Makefile.am b/kuser/toolbar/Makefile.am new file mode 100644 index 0000000..acee0fe --- /dev/null +++ b/kuser/toolbar/Makefile.am @@ -0,0 +1,2 @@ +kusericonsdir = $(kde_datadir)/kuser/icons +kusericons_ICON = AUTO diff --git a/kuser/toolbar/cr22-action-add_group.png b/kuser/toolbar/cr22-action-add_group.png Binary files differnew file mode 100644 index 0000000..8260a89 --- /dev/null +++ b/kuser/toolbar/cr22-action-add_group.png diff --git a/kuser/toolbar/cr22-action-add_user.png b/kuser/toolbar/cr22-action-add_user.png Binary files differnew file mode 100644 index 0000000..ec800f4 --- /dev/null +++ b/kuser/toolbar/cr22-action-add_user.png diff --git a/kuser/toolbar/cr22-action-delete_group.png b/kuser/toolbar/cr22-action-delete_group.png Binary files differnew file mode 100644 index 0000000..41984a9 --- /dev/null +++ b/kuser/toolbar/cr22-action-delete_group.png diff --git a/kuser/toolbar/cr22-action-delete_user.png b/kuser/toolbar/cr22-action-delete_user.png Binary files differnew file mode 100644 index 0000000..73fb036 --- /dev/null +++ b/kuser/toolbar/cr22-action-delete_user.png diff --git a/kuser/toolbar/cr22-action-edit_group.png b/kuser/toolbar/cr22-action-edit_group.png Binary files differnew file mode 100644 index 0000000..490404c --- /dev/null +++ b/kuser/toolbar/cr22-action-edit_group.png diff --git a/kuser/toolbar/cr22-action-edit_user.png b/kuser/toolbar/cr22-action-edit_user.png Binary files differnew file mode 100644 index 0000000..5c9e727 --- /dev/null +++ b/kuser/toolbar/cr22-action-edit_user.png |