source: src-qt4/pc-usermanager/usermanagerback.cpp @ 1620346

9.1-release9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 1620346 was 1620346, checked in by Kris Moore <kris@…>, 12 months ago

Initial import of PC-BSD /current/ SVN repo

  • Property mode set to 100755
File size: 15.2 KB
Line 
1/***************************************************************************
2 *   Copyright (C) 2005, 2012 by Tim McCormick   *
3 *   tim@pcbsd.org   *
4 *                                                                         *
5 *   Permission is hereby granted, free of charge, to any person obtaining *
6 *   a copy of this software and associated documentation files (the       *
7 *   "Software"), to deal in the Software without restriction, including   *
8 *   without limitation the rights to use, copy, modify, merge, publish,   *
9 *   distribute, sublicense, and/or sell copies of the Software, and to    *
10 *   permit persons to whom the Software is furnished to do so, subject to *
11 *   the following conditions:                                             *
12 *                                                                         *
13 *   The above copyright notice and this permission notice shall be        *
14 *   included in all copies or substantial portions of the Software.       *
15 *                                                                         *
16 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
17 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
18 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
20 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
21 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
22 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
23 ***************************************************************************/
24
25#include "usermanagerback.h"
26#include <qtextstream.h>
27#include <QDebug>
28#include <QUrl>
29#include <QFileInfo>
30
31UserManagerBackend::UserManagerBackend(QString dir) {
32    chroot = dir;
33    programInit();
34}
35
36void UserManagerBackend::programInit() {
37    fullnameRegExp.setPattern("([:!@])+");
38    homeLocRegExp.setPattern("^(/usr)?/home/?");
39    usernameRegExp.setPattern("([a-z]*[A-Z]*[0-9]*[_]*)+");
40    passwordRegExp.setPattern("([a-z]*[A-Z]*[0-9]*[!\"£$%^&*()_+=¬#'`@~:?<>|{}\\-.]*)+");
41    groupnameRegExp.setPattern("([a-z]*[A-Z]*[0-9]*[_]*)+");
42}
43
44QStringList UserManagerBackend::getAllUsers(int minId, int maxId) {
45    if (userList.empty()) { refreshUsers(); }
46   
47    qDebug() << "Generating new user list for UI...";
48
49    QStringList result;
50    QMap<QString, User>::Iterator it;
51
52    for ( it = userList.begin(); it != userList.end(); ++it ) {
53        if ((! it->getDeleted()) && (((it->getUid() >= minId) || (minId == -1)) && (it->getUid() <= maxId) || (maxId == -1) || (it->getUid() < 0))) {
54            result.append(it->getUsername());
55        }
56    }
57   
58    qDebug() << "Done Generating new user list for UI...";
59    return result;
60}
61
62void UserManagerBackend::refreshUsers() {
63    qDebug() << "Refreshing user list...";
64    userList.clear();
65    QFile userFile(chroot + "/etc/passwd");
66    if ( userFile.open(QIODevice::ReadOnly) ) {
67        QTextStream stream(&userFile);
68        stream.setCodec("UTF-8");
69        QString line;
70       
71        while ( !stream.atEnd() ) {
72            line = stream.readLine();
73           
74            if ((line.indexOf("#") != 0) && (! line.isEmpty())) { //Make sure it isn't a comment or blank
75                QString username = line.section(":",0,0);
76                int uid = line.section(":",2,2).toInt();
77                int gid = line.section(":",3,3).toInt();
78                QString home = line.section(":",5,5);
79                QString shell = line.section(":",6,6);
80                QString fullname = line.section(":",4,4);
81               
82                userList[username] = User(username, uid, gid, home, shell, fullname);
83            }
84        }
85    }
86    else {
87        //Unable to open file error
88        qWarning("Error! Unable to open /etc/passwd");
89    }
90}
91
92User* UserManagerBackend::getUser(const QString &user) {
93    return &userList.find(user).value();
94}
95
96QStringList UserManagerBackend::getShells() {
97    QStringList result;
98    QFile shellFile(chroot + "/etc/shells");
99    if ( shellFile.open(QIODevice::ReadOnly) ) {
100        QTextStream stream(&shellFile);
101        stream.setCodec("UTF-8");
102
103        QString line;
104       
105        while ( !stream.atEnd() ) {
106            line = stream.readLine();
107           
108            if ((line.indexOf("#") != 0) && (! line.isEmpty())) { //Make sure it isn't a comment or blank
109                result.append(line);
110            }
111        }
112    }
113    else {
114        //Unable to open file error
115        qWarning("Error! Unable to open /etc/shells");
116    }
117   
118    // Add /sbin/nologin as well
119    result.append("/sbin/nologin");
120
121    return result;
122}
123
124QStringList UserManagerBackend::getAllGroups(int minId, int maxId) {
125    if (groupList.empty()) { refreshGroups(); }
126   
127    QStringList result;
128    QMap<int, Group>::Iterator it;
129   
130    qDebug() << "Generating new group list for UI...";
131
132    for ( it = groupList.begin(); it != groupList.end(); ++it ) {
133        if ((! it->getDeleted()) && (((it->getGid() >= minId) || (minId == -1) ) && ((it->getGid() <= maxId) || (maxId == -1 )))) {
134            result.append(it->getGroupname());
135        }
136    }
137
138    qDebug() << "Done Generating new group list for UI...";
139    return result;
140}
141
142void UserManagerBackend::refreshGroups() {
143    qDebug() << "Refreshing group list...";
144    groupList.clear();
145    QFile groupFile(chroot + "/etc/group");
146    if ( groupFile.open(QIODevice::ReadOnly) ) {
147        QTextStream stream(&groupFile);
148        stream.setCodec("UTF-8");
149
150        QString line;
151       
152        while ( !stream.atEnd() ) {
153            line = stream.readLine();
154           
155            if ((line.indexOf("#") != 0) && (! line.isEmpty())) { //Make sure it isn't a comment or blank
156                QString groupname = line.section(":",0,0);
157                int gid = line.section(":",2,2).toInt();
158                QString memberString = line.section(":",3,3);
159                QStringList members = memberString.split(",");
160               
161                groupList[gid] = Group(groupname, gid, members);
162            }
163        }
164    }
165    else {
166        //Unable to open file error
167        qWarning("Error! Unable to open /etc/group");
168    }
169}
170
171Group* UserManagerBackend::getGroup(int gid) {
172    return &groupList.find(gid).value();
173}
174
175Group* UserManagerBackend::getGroup(QString groupname) {
176    Group *result = new Group();
177    QMap<int, Group>::Iterator it;
178   
179    for ( it = groupList.begin(); it != groupList.end(); ++it ) {
180        if (it->getGroupname() == groupname) {
181            result = &it.value();
182        }
183    }
184   
185    return result;
186}
187
188int UserManagerBackend::validatePassword(QString password, QString confirmPassword) {
189    int result = 0;
190    if (password != confirmPassword) {
191        result = 2;
192    }
193    if ((password == "") || (confirmPassword == "")) {
194        result = 1;
195    }
196    if ((! passwordRegExp.exactMatch(password)) && (password != "")) {
197        result = 3;
198    }
199    return result;
200}
201
202void UserManagerBackend::changePassword(QString username, QString password)
203{
204    qDebug() << "running changePassword()";
205    userList[username].setPassword(password);
206    emit usersChanged();
207}
208
209int UserManagerBackend::validateFullname(QString fullname) {
210    int result = 0;
211   
212    if ((fullname.contains(fullnameRegExp) != 0) && (fullname != "")) {
213        result = 2;
214    }
215    if (fullname == "") {
216        result = 1;
217    }
218   
219    return result;
220}
221
222int UserManagerBackend::validateHome(QString home) {
223    int result = 0;
224    QFileInfo homeDir(home);
225    QUrl *homePath = new QUrl(home);
226    if (home == "") {
227        result = 1;
228    }
229    if ((! homeDir.isDir()) && (home != "")) {
230        result = 3;
231    }
232    if ((homeLocRegExp.indexIn(home) == -1) && (home != "")) {
233        result = 4;
234    }   
235    if ((homeDir.isFile()) && (home != "")) {
236        result = 5;
237    }
238    if ((! homePath->isValid()) && (home != "")) {
239        result = 2;
240    }
241   
242    return result;
243}
244
245void UserManagerBackend::deleteUser(QString username)
246{
247    userList[username].setDeleted();
248    emit usersChanged();
249}
250
251int UserManagerBackend::validateUsername(QString username) {
252    //0 = OK, 1 = Empty, 2 = Invalid input, 3 = Username already in use
253    int result = 0;
254   
255    if ((userList.contains(username) == true) && (username != "")) {
256        result = 3;
257    }
258    if ((! usernameRegExp.exactMatch(username)) && (username != "")) {
259        result = 2;
260    }
261    if (username == "") {
262        result = 1;
263    }
264   
265    return result;
266}
267
268void UserManagerBackend::addUser(QString username, QString fullname, QString home, QString shell, QString group, QString password)
269{
270    qDebug() << "Starting addUser " << username;
271    int gid = -1;
272    QMap<int, Group>::Iterator it;
273   
274    for ( it = groupList.begin(); it != groupList.end(); ++it )
275    {
276        if (it->getGroupname() == group)
277        {
278            gid = it->getGid();
279            break;
280        }
281    }
282    userList[username] = User(username, home, shell, fullname, password, gid);
283   
284    emit usersChanged();
285    qDebug() << "Finished addUser: " << username;
286}
287
288void UserManagerBackend::deleteGroup(QString groupname)
289{
290    getGroup(groupname)->setDeleted();
291    emit groupsChanged();
292}
293
294void UserManagerBackend::addGroup(QString groupname)
295{
296    //Find free, invalid id
297    int gid = -1;
298    while (groupList[gid].getStatus() != -1) { gid--; }
299    groupList[gid] = Group(groupname, -1, QStringList(), true);
300    emit groupsChanged();
301}
302
303int UserManagerBackend::validateGroupname(QString groupname) {
304    //0 = OK, 1 = Empty, 2 = Invalid input, 3 = Groupname already in use
305    int result = 0;
306    QMap<int, Group>::Iterator it;
307   
308    for ( it = groupList.begin(); it != groupList.end(); ++it ) {
309        if (it->getGroupname() == groupname) {
310            result = 3;
311        }
312    }
313    if ((! groupnameRegExp.exactMatch(groupname)) && (groupname != "")) {
314        result = 2;
315    }
316    if (groupname == "") {
317        result = 1;
318    }
319   
320    return result;
321}
322
323void UserManagerBackend::addUserToGroup(QString user, QString groupname)
324{
325    Group *group = getGroup(groupname);
326    group->addMember(user);
327    group->setChanges();
328    emit groupsChanged();
329}
330
331void UserManagerBackend::removeUserFromGroup(QString user, QString groupname)
332{
333    Group *group = getGroup(groupname);
334    group->removeMember(user);
335    group->setChanges();
336    emit groupsChanged();
337}
338
339bool UserManagerBackend::commit()
340{
341   
342    //Process users
343    QMap<QString, User>::Iterator userIt;
344
345    QStringList args;
346   
347    for ( userIt = userList.begin(); userIt != userList.end(); ++userIt )
348    {
349        args.clear();
350        switch(userIt->getStatus())
351        {
352            case 1:
353                //Modify User
354                qDebug() << "Modifying user " << userIt->getUsername();
355                if ( ! chroot.isEmpty() )
356                   args << chroot << "pw";
357                args << "usermod";
358                args << userIt->getUsername();
359                args << "-d";
360                args << userIt->getHome();
361                args << "-s";
362                args << userIt->getShell();
363                args << "-c";
364                args << userIt->getFullname();
365                if ( ! chroot.isEmpty() )
366                   QProcess::execute("chroot", args);
367                else
368                   QProcess::execute("pw", args);
369               
370                if (userIt->getPassword() != "")
371                {
372                    args.clear();
373                    if ( ! chroot.isEmpty() )
374                       args << chroot << "chpass";
375                    args << "-p";
376                    args << userIt->getPassword();
377                    args << userIt->getUsername();
378                    if ( ! chroot.isEmpty() )
379                      QProcess::execute("chroot", args);
380                    else 
381                      QProcess::execute("chpass", args);
382                }
383                break;
384            case 2:
385                //Add User
386                qDebug() << "Adding user " << userIt->getUsername();
387                // Create the new home-directory
388                if ( chroot.isEmpty() )
389                   system("/usr/local/share/pcbsd/scripts/mkzfsdir.sh " + userIt->getHome().toLatin1() );
390                else {
391                   system("mkdir -p " + chroot.toLatin1() + "/" + userIt->getHome().toLatin1() + " 2>/dev/null" );
392                   system("chroot " + chroot.toLatin1() + " ln -s /usr/home /home 2>/dev/null" );
393                }
394
395                if ( ! chroot.isEmpty() )
396                   args << chroot << "pw";
397                args << "useradd";
398                args << userIt->getUsername();
399                args << "-c";
400                args << userIt->getFullname();
401                args << "-d";
402                args << userIt->getHome();
403                args << "-s";
404                args << userIt->getShell();
405                if (userIt->getGid() != -1)
406                {
407                    args << "-g";
408                    args << QString::number(userIt->getGid());
409                }
410                args << "-G";
411                args << "operator";
412                args << "-m";
413                if ( ! chroot.isEmpty() )
414                   QProcess::execute("chroot", args);
415                else
416                   QProcess::execute("pw", args);
417               
418                args.clear();
419                if ( ! chroot.isEmpty() )
420                   args << chroot << "chpass";
421                args << "-p";
422                args << userIt->getPassword();
423                args << userIt->getUsername();
424                if ( ! chroot.isEmpty() )
425                   QProcess::execute("chroot", args);
426                else
427                   QProcess::execute("chpass", args);
428
429                if ( chroot.isEmpty() ) {
430                   qDebug() << "Enabling Flash Plugin for " << userIt->getUsername();
431                   QString flashCmd = "su -m " + userIt->getUsername() + " -c \"flashpluginctl on\"";
432                   system(flashCmd.toLatin1());
433                }
434
435                // Set permissions
436                if ( chroot.isEmpty() )
437                   system("chown -R " + userIt->getUsername().toLatin1() +":" + userIt->getUsername().toLatin1() + " "  + userIt->getHome().toLatin1() );
438                else
439                   system("chroot " + chroot.toLatin1() + " chown -R " + userIt->getUsername().toLatin1() +":" + userIt->getUsername().toLatin1() + " "  + userIt->getHome().toLatin1() );
440
441                break;
442            case 3:
443                //Delete User
444                qDebug() << "Deleting user " << userIt->getUsername();
445                if ( ! chroot.isEmpty() )
446                   args << chroot << "pw";
447                args << "userdel";
448                args << userIt->getUsername();
449                if(userIt->getDeleteHome()) {
450                        args << "-r";
451                        system("/usr/local/share/pcbsd/scripts/rmzfsdir.sh " + userIt->getHome().toLatin1() );
452                }
453                if ( ! chroot.isEmpty() )
454                   QProcess::execute("chroot", args);
455                else
456                   QProcess::execute("pw", args);
457                break;
458        }
459    }
460    refreshUsers();
461   
462    //Process groups
463    QMap<int, Group>::Iterator groupIt;
464 
465    for ( groupIt = groupList.begin(); groupIt != groupList.end(); ++groupIt )
466    {
467        args.clear();
468        switch(groupIt->getStatus())
469        {
470            case 1:
471                //Modify Group
472                qDebug() << "Modifying group " << groupIt->getGroupname();
473                if ( ! chroot.isEmpty() )
474                   args << chroot << "pw";
475                args << "groupmod";
476                args << groupIt->getGroupname();
477                args << "-M";
478                args << groupIt->getMembers().join(",");
479                if ( ! chroot.isEmpty() )
480                   QProcess::execute("chroot", args);
481                else
482                   QProcess::execute("pw", args);
483                break;
484            case 2:
485                //Add Group
486                qDebug() << "Adding group " << groupIt->getGroupname();
487                if ( ! chroot.isEmpty() )
488                   args << chroot << "pw";
489                args << "groupadd";
490                args << groupIt->getGroupname();
491                args << "-M";
492                args << groupIt->getMembers().join(",");
493                if ( ! chroot.isEmpty() )
494                   QProcess::execute("chroot", args);
495                else
496                   QProcess::execute("pw", args);
497                break;
498            case 3:
499                //Delete Group
500                qDebug() << "Deleting group " << groupIt->getGroupname();
501                if ( ! chroot.isEmpty() )
502                   args << chroot << "pw";
503                args << "groupdel";
504                args << groupIt->getGroupname();
505                if ( ! chroot.isEmpty() )
506                   QProcess::execute("chroot", args);
507                else
508                   QProcess::execute("pw", args);
509                break;
510        }
511    }
512    refreshGroups();
513    emit groupsChanged();
514    emit usersChanged();
515   
516    return true;
517}
518
Note: See TracBrowser for help on using the repository browser.