--- kdebase-workspace-4.7.0/kdm/CMakeLists.txt 2011-05-20 22:32:06.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/CMakeLists.txt 2011-08-22 19:12:45.365000004 +0200 @@ -33,6 +33,11 @@ ${CMAKE_CURRENT_SOURCE_DIR}/kcm/background/bgsettings.cpp ) +set(kdmminmaxuidlib_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/kdm-minmaxuid.c + ${CMAKE_CURRENT_SOURCE_DIR}/kdm-minmaxuid.h +) + # after confci is defined add_subdirectory(backend) add_subdirectory(kfrontend) --- kdebase-workspace-4.7.0/kdm/config.def 2011-05-20 22:32:06.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/config.def 2011-08-22 18:40:31.706000005 +0200 @@ -2287,9 +2287,13 @@ Update: upd_minshowuid Comment: Special case of HiddenUsers: users with a non-zero UID less than this number - will not be shown as well. + will not be shown as well. Setting this to -1 means that the limit should be + determined in a platform-specific way (by reading /etc/login.defs or using a + compiled-in default). Description: - See <option>ShowUsers</option>. + See <option>ShowUsers</option>. Setting this to -1 means that the limit + should be determined in a platform-specific way (by reading + <filename>/etc/login.defs</filename> or using a compiled-in default). Key: MaxShowUID Type: int @@ -2300,9 +2304,11 @@ Update: upd_maxshowuid Comment: Complement to MinShowUID: users with a UID greater than this number will - not be shown as well. + not be shown as well. Unlike MinShowUID, the special value -1 is not + supported. Description: - See <option>ShowUsers</option>. + See <option>ShowUsers</option>. Unlike <option>MinShowUID</option>, the + special value -1 is not supported. Key: SortUsers Type: bool --- kdebase-workspace-4.7.0/kdm/kcm/CMakeLists.txt 2011-05-20 22:32:06.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/kcm/CMakeLists.txt 2011-08-22 19:13:23.857000013 +0200 @@ -15,6 +15,7 @@ background/bgadvanced_ui.ui) set(kcm_kdm_PART_SRCS ${kcmbackgroundlib_SRCS} ${backgroundlib_SRCS} + ${kdmminmaxuidlib_SRCS} background.cpp kdm-gen.cpp kdm-dlg.cpp --- kdebase-workspace-4.7.0/kdm/kcm/kdm-users.cpp 2011-06-22 16:29:18.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/kcm/kdm-users.cpp 2011-08-23 17:41:46.453999890 +0200 @@ -58,6 +58,9 @@ #include <unistd.h> #include <pwd.h> +#include "../kdm-minmaxuid.h" + + extern KConfig *config; extern int handleActionReply(QWidget *parent, const KAuth::ActionReply &reply); @@ -80,28 +83,11 @@ KDMUsersWidget::KDMUsersWidget(QWidget *parent) : QWidget(parent) { -#ifdef __linux__ - struct stat st; - if (!stat("/etc/debian_version", &st)) { /* debian */ - defminuid = "1000"; - defmaxuid = "29999"; - } else if (!stat("/usr/portage", &st)) { /* gentoo */ - defminuid = "1000"; - defmaxuid = "65000"; - } else if (!stat("/etc/mandrake-release", &st)) { /* mandrake - check before redhat! */ - defminuid = "500"; - defmaxuid = "65000"; - } else if (!stat("/etc/redhat-release", &st)) { /* redhat */ - defminuid = "100"; - defmaxuid = "65000"; - } else /* if (!stat("/etc/SuSE-release", &st)) */ { /* suse */ - defminuid = "500"; - defmaxuid = "65000"; - } -#else - defminuid = "1000"; - defmaxuid = "65000"; -#endif + int minUid, maxUid; + + getDefaultMinMaxUids(&minUid, &maxUid); + defminuid = QString::number(minUid); + defmaxuid = QString::number(maxUid); m_userPixDir = config->group("X-*-Greeter").readEntry("FaceDir", QString(KStandardDirs::installPath("data") + "kdm/faces" + '/')); @@ -119,21 +105,25 @@ "Users with a UID (numerical user identification) outside this range " "will not be listed by KDM and this setup dialog. " "Note that users with the UID 0 (typically root) are not affected by " - "this and must be explicitly excluded in \"Inverse selection\" mode.")); + "this and must be explicitly excluded in \"Inverse selection\" mode. " + "Setting the minimum to -1 means that the minimum should be determined " + "in a platform-specific way (by reading /etc/login.defs or using a " + "compiled-in default.)")); QSizePolicy sp_ign_fix(QSizePolicy::Ignored, QSizePolicy::Fixed); - QValidator *valid = new QIntValidator(0, INT_MAX, minGroup); + QValidator *minvalid = new QIntValidator(-1, INT_MAX, minGroup); QLabel *minlab = new QLabel(i18nc("UIDs", "Below:"), minGroup); leminuid = new KLineEdit(minGroup); minlab->setBuddy(leminuid); leminuid->setSizePolicy(sp_ign_fix); - leminuid->setValidator(valid); + leminuid->setValidator(minvalid); connect(leminuid, SIGNAL(textChanged(const QString &)), SIGNAL(changed())); connect(leminuid, SIGNAL(textChanged(const QString &)), SLOT(slotMinMaxChanged())); + QValidator *maxvalid = new QIntValidator(0, INT_MAX, minGroup); QLabel *maxlab = new QLabel(i18nc("UIDs", "Above:"), minGroup); lemaxuid = new KLineEdit(minGroup); maxlab->setBuddy(lemaxuid); lemaxuid->setSizePolicy(sp_ign_fix); - lemaxuid->setValidator(valid); + lemaxuid->setValidator(maxvalid); connect(lemaxuid, SIGNAL(textChanged(const QString &)), SIGNAL(changed())); connect(lemaxuid, SIGNAL(textChanged(const QString &)), SLOT(slotMinMaxChanged())); QGridLayout *grid = new QGridLayout(minGroup); --- kdebase-workspace-4.7.0/kdm/kcm/main.cpp 2011-05-20 22:32:07.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/kcm/main.cpp 2011-08-23 19:23:10.750998887 +0200 @@ -59,6 +59,7 @@ #include <pwd.h> #include <grp.h> +#include "../kdm-minmaxuid.h" K_PLUGIN_FACTORY(KDMFactory, registerPlugin<KDModule>();) K_EXPORT_PLUGIN(KDMFactory("kdmconfig")) @@ -393,13 +394,14 @@ { groupmap.clear(); emit clearUsers(); + int realminuid = interpretMinUid(minshowuid); QMap<QString, int> lusers; QMap<QString, QPair<int, QStringList> >::const_iterator it; QStringList::ConstIterator jt; QMap<QString, int>::Iterator gmapi; for (it = usermap.constBegin(); it != usermap.constEnd(); ++it) { int uid = it.value().first; - if (!uid || (uid >= minshowuid && uid <= maxshowuid)) { + if (!uid || (uid >= realminuid && uid <= maxshowuid)) { lusers[it.key()] = uid; for (jt = it.value().second.begin(); jt != it.value().second.end(); ++jt) if ((gmapi = groupmap.find(*jt)) == groupmap.end()) { @@ -415,6 +417,8 @@ void KDModule::slotMinMaxUID(int min, int max) { + int oldrealmin = interpretMinUid(minshowuid); + int newrealmin = interpretMinUid(min); if (updateOK) { QMap<QString, int> alusers, dlusers; QMap<QString, QPair<int, QStringList> >::const_iterator it; @@ -424,8 +428,8 @@ int uid = it.value().first; if (!uid) continue; - if ((uid >= minshowuid && uid <= maxshowuid) && - !(uid >= min && uid <= max)) { + if ((uid >= oldrealmin && uid <= maxshowuid) && + !(uid >= newrealmin && uid <= max)) { dlusers[it.key()] = uid; for (jt = it.value().second.begin(); jt != it.value().second.end(); ++jt) { @@ -435,8 +439,8 @@ dlusers['@' + *jt] = -uid; } } - } else if ((uid >= min && uid <= max) && - !(uid >= minshowuid && uid <= maxshowuid)) { + } else if ((uid >= newrealmin && uid <= max) && + !(uid >= oldrealmin && uid <= maxshowuid)) { alusers[it.key()] = uid; for (jt = it.value().second.begin(); jt != it.value().second.end(); ++jt) --- kdebase-workspace-4.7.0/kdm/kdm-minmaxuid.c 1970-01-01 01:00:00.000000000 +0100 +++ kdebase-workspace-4.7.0/kdm/kdm-minmaxuid.c 2011-08-23 18:35:05.011997103 +0200 @@ -0,0 +1,152 @@ +/* + * Utilities for handling the UID range allocated for non-system user + */ + +#include <stdio.h> +#include <sys/stat.h> +#ifdef __linux__ +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <regex.h> +#include <stdlib.h> +#include <string.h> +#endif + +#include "kdm-minmaxuid.h" + +static void internalMinMaxUids(int *minUid, int *maxUid, int staticValues) +{ + struct stat st; + +#ifdef __linux__ + if (!stat("/etc/debian_version", &st)) { /* debian */ + *minUid = 1000; + *maxUid = 29999; + } else if (!stat("/usr/portage", &st)) { /* gentoo */ + *minUid = 1000; + *maxUid = 65000; + } else if (!stat("/etc/mandrake-release", &st)) { /* mandrake - check before redhat! */ + *minUid = 500; + *maxUid = 65000; + } else if (!stat("/etc/redhat-release", &st)) { /* redhat */ + if (!staticValues && !stat("/etc/login.defs", &st)) + *minUid = -1; + else + *minUid = 100; + *maxUid = 65000; + } else /* if (!stat("/etc/SuSE-release", &st)) */ { /* suse */ + *minUid = 500; + *maxUid = 65000; + } +#else + *minUid = 1000; + *maxUid = 65000; +#endif +} + +void getDefaultMinMaxUids(int *minUid, int *maxUid) +{ + internalMinMaxUids(minUid, maxUid, 0); +} + +#ifdef __linux__ +static int getLoginDefsMinUid(void) +{ + int res; + char *buf; + size_t buf_size; + ssize_t line_len; + regex_t re; + FILE *f; + + f = fopen("/etc/login.defs", "r"); + if (f == NULL) + return -1; + + /* No, this is not particularly nice, but "compatible" is more important + than "beautiful". */ + if (regcomp(&re, + "^[ \t]*" /* Initial whitespace */ + "([^ \t]+)" /* Variable name */ + "[ \t][ \t\"]*" /* Separator - yes, may have multiple "s */ + "(" + "([^\"]*)\".*" /* Value, case 1 - terminated by " */ + /* Value, case 2 - only drop trailing [[:space:]] */ + "|([^\"]*[^[:space:]])?[[:space:]]*" + ")$", REG_EXTENDED) != 0) + abort(); + + buf = NULL; + buf_size = 0; + res = -1; + while ((line_len = getline(&buf, &buf_size, f)) > 0) { + regmatch_t match[5]; + const char *name, *value; + + if (line_len > 0 && buf[line_len - 1] == '\n') + buf[line_len - 1] = '\0'; + + if (regexec(&re, buf, sizeof(match) / sizeof(*match), match, 0) != 0) + continue; + + assert(match[1].rm_so != -1); + name = buf + match[1].rm_so; + if (*name == '#') + continue; + /* The "separator" is at least one character long, so we can safely + overwrite it with '\0'. */ + buf[match[1].rm_eo] = '\0'; + + if (match[3].rm_so != -1) { + value = buf + match[3].rm_so; + buf[match[3].rm_eo] = '\0'; + } else if (match[4].rm_so != -1) { + value = buf + match[4].rm_so; + buf[match[4].rm_eo] = '\0'; + } else + value = ""; + + /* fprintf(stderr, "\tMatched: %s = %s!\n", name, value); */ + + if (strcmp(name, "UID_MIN") == 0) { + intmax_t imax; + char *p; + + errno = 0; + imax = strtoimax(value, &p, 10); + if (errno == 0 && *p == '\0' && p != value && (uid_t)imax == imax) + res = imax; + } + } + free(buf); + + regfree(&re); + fclose(f); + + return res; +} +#endif + +int interpretMinUid(int minUid) +{ + int res, dummy; + + if (minUid != -1) + return minUid; +#ifdef __linux__ + res = getLoginDefsMinUid(); + if (res != -1) + return res; +#endif + internalMinMaxUids(&res, &dummy, 1); + return res; +} + +#ifdef TESTING +int main(void) +{ + printf("interpretMinUid returns %d\n", interpretMinUid(-1)); + return 0; +} +#endif --- kdebase-workspace-4.7.0/kdm/kdm-minmaxuid.h 1970-01-01 01:00:00.000000000 +0100 +++ kdebase-workspace-4.7.0/kdm/kdm-minmaxuid.h 2011-08-23 18:37:22.494007452 +0200 @@ -0,0 +1,25 @@ +/* + * Utilities for handling the UID range allocated for non-system user + */ + +#ifndef KDM_MINMAXUID_H +#define KDM_MINMAXUID_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Get platform-specific defaults for minShowUID and maxShowUID. + Never fails. */ +void getDefaultMinMaxUids(int *minUid, int *maxUid); + +/* Return the lower limit of user UIDs, based on supplied minShowUID value + (i.e. interpret the value -1). */ +int interpretMinUid(int minUid); + +#ifdef __cplusplus +} +#endif + + +#endif --- kdebase-workspace-4.7.0/kdm/kfrontend/CMakeLists.txt 2011-05-20 22:32:07.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/kfrontend/CMakeLists.txt 2011-08-23 18:54:46.308000002 +0200 @@ -52,6 +52,7 @@ utils.cpp utils.h ${kdmthemer_SRCS} + ${kdmminmaxuidlib_SRCS} ) if (XDMCP) @@ -93,7 +94,7 @@ target_link_libraries(krootimage ${KDE4_KDEUI_LIBS} ${X11_X11_LIB} ${QIMAGEBLITZ_LIBRARIES}) install(TARGETS krootimage DESTINATION ${LIBEXEC_INSTALL_DIR}) -set(genkdmconf_SRCS genkdmconf.c) +set(genkdmconf_SRCS genkdmconf.c ${kdmminmaxuidlib_SRCS}) macro_add_file_dependencies(genkdmconf.c ${confci}) kde4_add_executable(genkdmconf NOGUI ${genkdmconf_SRCS}) macro_add_compile_flags(genkdmconf -U_REENTRANT) --- kdebase-workspace-4.7.0/kdm/kfrontend/genkdmconf.c 2011-05-20 22:32:07.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/kfrontend/genkdmconf.c 2011-08-23 18:35:44.653000001 +0200 @@ -48,6 +48,7 @@ #ifdef BSD # include <utmp.h> #endif +#include "../kdm-minmaxuid.h" #define WANT_CONF_GEN #include <config.ci> @@ -1999,7 +2000,7 @@ } } -static const char *defminuid, *defmaxuid; +static char defminuid[64], defmaxuid[64]; static void upd_minshowuid(Entry *ce, Section *cs ATTR_UNUSED) @@ -2025,16 +2026,18 @@ char *nv; const char *msu, *pt, *et; struct passwd *pw; - unsigned minuid, maxuid; + int minuid, maxuid; char nbuf[128]; if (!ce->active) return; msu = getFqVal(cs->name, "MinShowUID", "0"); - sscanf(msu, "%u", &minuid); + sscanf(msu, "%d", &minuid); msu = getFqVal(cs->name, "MaxShowUID", "65535"); - sscanf(msu, "%u", &maxuid); + sscanf(msu, "%d", &maxuid); + + minuid = interpretMinUid(minuid); nv = 0; pt = ce->value; @@ -2048,7 +2051,7 @@ } if ((pw = getpwnam(nbuf))) { if (!pw->pw_uid || - (pw->pw_uid >= minuid && pw->pw_uid <= maxuid)) + (pw->pw_uid >= (uid_t)minuid && pw->pw_uid <= (uid_t)maxuid)) { if (nv) strCat(&nv, ",%s", nbuf); @@ -2991,7 +2994,7 @@ StrList *fp; Section *cs; Entry *ce, **cep; - int i, ap, locals, foreigns; + int i, ap, locals, foreigns, minuid, maxuid; int no_old_xdm = 0, no_old_kde = 0; struct stat st; @@ -3230,27 +3233,9 @@ } } } -#ifdef __linux__ - if (!stat("/etc/debian_version", &st)) { /* debian */ - defminuid = "1000"; - defmaxuid = "29999"; - } else if (!stat("/usr/portage", &st)) { /* gentoo */ - defminuid = "1000"; - defmaxuid = "65000"; - } else if (!stat("/etc/mandrake-release", &st)) { /* mandrake - check before redhat! */ - defminuid = "500"; - defmaxuid = "65000"; - } else if (!stat("/etc/redhat-release", &st)) { /* redhat */ - defminuid = "100"; - defmaxuid = "65000"; - } else /* if (!stat("/etc/SuSE-release", &st)) */ { /* suse */ - defminuid = "500"; - defmaxuid = "65000"; - } -#else - defminuid = "1000"; - defmaxuid = "65000"; -#endif + getDefaultMinMaxUids(&minuid, &maxuid); + sprintf(defminuid, "%d", minuid); + sprintf(defmaxuid, "%d", maxuid); for (i = 0; i <= CONF_MAX_PRIO; i++) for (cs = config; cs; cs = cs->next) for (ce = cs->ents; ce; ce = ce->next) --- kdebase-workspace-4.7.0/kdm/kfrontend/kgreeter.cpp 2011-05-20 22:32:07.000000000 +0200 +++ kdebase-workspace-4.7.0/kdm/kfrontend/kgreeter.cpp 2011-08-23 18:55:40.350999999 +0200 @@ -66,6 +66,8 @@ #include <X11/Xlib.h> #include <fixx11h.h> +#include "../kdm-minmaxuid.h" + class UserListView : public QListWidget { public: UserListView(QWidget *parent = 0) @@ -389,12 +391,13 @@ default_pix.fill(0); } } + int realLowUserId = interpretMinUid(_lowUserId); if (_showUsers == SHOW_ALL) { UserList noUsers(_noUsers); QSet<QString> dupes; for (setpwent(); (ps = getpwent()) != 0;) { if (*ps->pw_dir && *ps->pw_shell && - (ps->pw_uid >= (unsigned)_lowUserId || + (ps->pw_uid >= (unsigned)realLowUserId || (!ps->pw_uid && _showRoot)) && ps->pw_uid <= (unsigned)_highUserId && !noUsers.hasUser(ps->pw_name) && @@ -413,7 +416,7 @@ QSet<QString> dupes; for (setpwent(); (ps = getpwent()) != 0;) { if (*ps->pw_dir && *ps->pw_shell && - (ps->pw_uid >= (unsigned)_lowUserId || + (ps->pw_uid >= (unsigned)realLowUserId || (!ps->pw_uid && _showRoot)) && ps->pw_uid <= (unsigned)_highUserId && (users.hasUser(ps->pw_name) ||