├── .travis.yml ├── About.cpp ├── About.h ├── Blowfish.cpp ├── Blowfish.h ├── HashEncode.cpp ├── HashEncode.h ├── HashingAlgorithm.cpp ├── HashingAlgorithm.h ├── HashingFactory.cpp ├── HashingFactory.h ├── IHashing.h ├── InputDialogValidator.cpp ├── InputDialogValidator.h ├── LICENSE ├── MainWindow.cpp ├── MainWindow.h ├── Makefile ├── Md5.cpp ├── Md5.h ├── README.md ├── Settings.cpp ├── Settings.h ├── UserManager ├── UserManager.pro ├── editProperties.cpp ├── editProperties.h ├── exp.sh ├── groupProperties.cpp ├── groupProperties.h ├── groups.cpp ├── groups.h ├── images └── Untitled2.gif ├── install_and_run.sh ├── language ├── el.qm └── el.ts ├── main.cpp ├── models.cpp ├── models.h ├── move.sh ├── myLibb.cpp ├── myLibb.h ├── other ├── exp.sh └── usermanager.conf ├── pathfile.h ├── resources ├── images.qrc └── images │ ├── .directory │ ├── CD.png │ ├── UserManager.gif │ ├── about.png │ ├── add.png │ ├── addgr.jpeg │ ├── addgr.png │ ├── addgroup.jpeg │ ├── addgroup2.jpeg │ ├── adduser.jpeg │ ├── admin.png │ ├── apply.png │ ├── backup.png │ ├── bottom.png │ ├── browse.png │ ├── cancel.png │ ├── clear.png │ ├── contexthelp.png │ ├── copy.png │ ├── deleteuser.jpeg │ ├── deleteuser1.jpeg │ ├── deleteuser2.jpeg │ ├── dialout.png │ ├── down.png │ ├── edit.png │ ├── editGroup.png │ ├── editUser.png │ ├── enabled.jpeg │ ├── enter.png │ ├── fax.png │ ├── floppy.png │ ├── general.png │ ├── greek.jpeg │ ├── group.jpeg │ ├── group.png │ ├── group_add.png │ ├── group_remove.png │ ├── grub_entries.png │ ├── grub_settings.png │ ├── keys.png │ ├── language.png │ ├── loading.gif │ ├── lock.png │ ├── log.png │ ├── ok.png │ ├── p.jpeg │ ├── path.png │ ├── preview.png │ ├── profile_edit.png │ ├── qgrubeditor.png │ ├── qt.png │ ├── quit.png │ ├── refresh.png │ ├── reload.png │ ├── remove.png │ ├── restore.png │ ├── restore_default.png │ ├── scan.png │ ├── scanner.png │ ├── search.jpg │ ├── search.png │ ├── searchuser.jpeg │ ├── settings.png │ ├── splash.png │ ├── storage.png │ ├── top.png │ ├── uk.jpeg │ ├── up.png │ ├── user.jpeg │ ├── user.png │ ├── user_add.png │ ├── user_lock.png │ ├── user_remove.png │ ├── user_unlock.png │ └── view.png ├── sha256.cpp ├── sha256.h ├── sha512.cpp ├── sha512.h ├── spc.cpp ├── spc.h ├── ui ├── About.ui ├── EditProperties.ui ├── GroupProperties.ui ├── HashingAlgorithm.ui ├── Settings.ui ├── UserProperties.ui └── mainwindow.ui ├── userproperties.cpp ├── userproperties.h ├── users.cpp └── users.h /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - gcc 5 | 6 | os: 7 | - linux 8 | 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | #ppa:chris-lea/redis-server 14 | packages: 15 | #- redis-tools 16 | #- redis-server 17 | - gcc-7 18 | - g++-7 19 | 20 | sudo: required 21 | dist: xenial 22 | 23 | env: 24 | - QT_BASE=51 25 | #- QT_BASE=52 26 | #- QT_BASE=53 27 | #- QT_BASE=54 28 | #- QT_BASE=55 29 | #- QT_BASE=56 30 | 31 | before_install: 32 | - if [ "$QT_BASE" = "51" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.12.0-xenial -y; fi 33 | #- if [ "$QT_BASE" = "52" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.21.0-xenial -y; fi 34 | #- if [ "$QT_BASE" = "53" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.32.0-xenial -y; fi 35 | #- if [ "$QT_BASE" = "54" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.42.0-xenial -y; fi 36 | #- if [ "$QT_BASE" = "55" ]; then sudo add-apt-repository ppa:beineri/opt-qt-5.51.0-xenial -y; fi 37 | #- if [ "$QT_BASE" = "56" ]; then sudo add-apt-repository ppa:beineri/opt-qt56-xenial -y; fi 38 | - sudo apt-get update -qq 39 | - sudo apt-get install qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev 40 | - sudo apt-get install qt5-default qttools5-dev-tools 41 | 42 | install: 43 | - if [ "$QT_BASE" = "51" ]; then sudo apt-get install -qq qt512base; source /opt/qt512/bin/qt512-env.sh; fi 44 | #- if [ "$QT_BASE" = "52" ]; then sudo apt-get install -qq qt512base; source /opt/qt521/bin/qt521-env.sh; fi 45 | #- if [ "$QT_BASE" = "53" ]; then sudo apt-get install -qq qt53base; source /opt/qt532/bin/qt532-env.sh; fi 46 | #- if [ "$QT_BASE" = "54" ]; then sudo apt-get install -qq qt54base; source /opt/qt542/bin/qt542-env.sh; fi 47 | #- if [ "$QT_BASE" = "55" ]; then sudo apt-get install -qq qt55base; source /opt/qt551/bin/qt551-env.sh; fi 48 | #- if [ "$QT_BASE" = "56" ]; then sudo apt-get install -qq qt56base; source /opt/qt56/bin/qt560-env.sh; fi 49 | 50 | script: 51 | - qmake -r 52 | - make 53 | # Check that everything built correctly: 54 | - make check 55 | # Now lets execute the app to see that it runs ok: 56 | # pwd 57 | # ./UserManager 58 | 59 | branches: 60 | only: 61 | - master 62 | 63 | notifications: 64 | email: false 65 | -------------------------------------------------------------------------------- /About.cpp: -------------------------------------------------------------------------------- 1 | #include "About.h" 2 | 3 | using namespace std; 4 | 5 | About::About ( QWidget * parent ) : QDialog ( parent ) 6 | { 7 | 8 | setupUi ( this ); 9 | textEdit_2->setReadOnly(false); 10 | //connect( OK, SIGNAL( pressed() ), this, SLOT( close() ) ); 11 | }; 12 | -------------------------------------------------------------------------------- /About.h: -------------------------------------------------------------------------------- 1 | #ifndef ABOUT_H 2 | #define ABOUT_H 3 | 4 | #include "ui_About.h" 5 | 6 | class About : public QDialog, public Ui::About 7 | { 8 | 9 | Q_OBJECT 10 | 11 | public: 12 | About( QWidget *parent = 0 ); 13 | 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /Blowfish.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * blowfish.cpp 3 | * 4 | * Created on: Aug 24, 2017 5 | * Author: xvas 6 | */ 7 | 8 | 9 | 10 | /* 11 | * The glibc2 version of crypt(3) function supports additional encryption 12 | algorithms. 13 | 14 | If salt or seed in this case is a character string starting with the characters "$id$" 15 | followed by a string terminated by "$": 16 | 17 | $id$salt$encrypted 18 | 19 | then instead of using the DES machine, id identifies the encryption 20 | method used and this then determines how the rest of the password 21 | string is interpreted. 22 | 23 | The following values of id are supported: 24 | 25 | ID | Method 26 | ───────────────────────────────────────────────────────── 27 | 1 | MD5 28 | 2a | Blowfish (not in mainline glibc; added in some 29 | | Linux distributions) 30 | 5 | SHA-256 (since glibc 2.7) 31 | 6 | SHA-512 (since glibc 2.7) 32 | 33 | in this case $1$salt$encrypted is an MD5 encoded one. 34 | 35 | The characters in "salt" (seed) and "encrypted" are drawn from the set 36 | [a-zA-Z0-9./]. In the MD5 and SHA implementations the entire key is 37 | significant. 38 | 39 | salt or seed in this case is a two-character string chosen from the set [a-zA-Z0-9./]. 40 | This string is used to perturb the algorithm in one of 4096 different 41 | ways. 42 | 43 | Security Concerns 44 | ------------------ 45 | 46 | Warning: the key space consists of 2**56 equal 7.2e16 possible 47 | values. Exhaustive searches of this key space are possible using 48 | massively parallel computers. 49 | 50 | Software, such as crack(1), is available which will search the portion of this key space that is 51 | generally used by humans for passwords. Hence, password selection should, at minimum, avoid common words and names. The use of a 52 | passwd(1) program that checks for crackable passwords during the selection process is recommended. 53 | 54 | MD5 algorithm should not be choosed because is vulnerable to colission attacks 55 | 56 | */ 57 | 58 | 59 | #include "Blowfish.h" 60 | #include 61 | #include 62 | #include 63 | 64 | 65 | IHashing *Blowfish::Create() 66 | { 67 | return new Blowfish(); 68 | } 69 | 70 | void Blowfish::Free() 71 | { 72 | delete this; 73 | } 74 | 75 | /* Hashing */ 76 | 77 | char *Blowfish::encryptpass( QString passwd) const 78 | { 79 | HashEncode *hEnc = new HashEncode(); 80 | //το seed είναι το αναγνωριστικό του αλγόριθμου blowfish($2a$) 81 | static char seed[7]; 82 | seed[0] = '$'; 83 | seed[1] = '2'; 84 | seed[2] = 'a'; 85 | seed[3] = '$'; 86 | //παράγει διαφορετικά σετ απο ψευδοτυχαίους αριθμούς κάθε φορά που το πρόγραμμα τρέχει 87 | //Στη συνέχεια η random επιστρέφει τυχαίους αριθμούς ανάλογα με το σετ που έχει δημιουργηθεί απο τη srandom 88 | srandom ( ( int ) time ( ( time_t * ) NULL ) ); 89 | hEnc->into64 ( &seed[4], random(),saltLength ); 90 | hEnc->into64 ( &seed[saltLength],random(),4 ); 91 | seed[saltLength+4] = '$'; 92 | 93 | if (hEnc != nullptr ) 94 | {delete hEnc; 95 | hEnc = nullptr;} 96 | 97 | char *buf = ( char * )calloc ( 512, sizeof(*buf) ); 98 | char *password = passwd.toLatin1().data(); 99 | memcpy ( buf,password,strlen(password)); 100 | 101 | /* 102 | * The crypt_r function does the same thing as crypt, but takes an extra parameter 103 | * which includes space for its result (among other things), so it can be reentrant. 104 | * data->initialized must be cleared to zero before the first time crypt_r is called 105 | */ 106 | 107 | struct crypt_data data; 108 | data.initialized = 0; 109 | 110 | char *pass = crypt_r ( buf,seed, &data); 111 | 112 | if ( pass == NULL ) 113 | QMessageBox::critical ( 0,QObject::tr ( "User Manager" ),QObject::tr ( "%1" ).arg ( ENOSYS ) ); 114 | if (buf!=NULL)free(buf); 115 | return strdup ( pass ); 116 | } 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Blowfish.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "HashEncode.h" 4 | #include "IHashing.h" 5 | 6 | class Blowfish : public IHashing 7 | { 8 | public: 9 | static const int saltLength = 2; 10 | char* encryptpass(QString passwd) const; 11 | void Free(); 12 | static IHashing* Create(); 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /HashEncode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * HashEncode.cpp 3 | * 4 | * Created on: Aug 16, 2017 5 | * Author: root 6 | */ 7 | /** 8 | * 9 | * The function below creates a random 64bit encoded code 10 | */ 11 | 12 | #include "HashEncode.h" 13 | 14 | 15 | HashEncode::HashEncode() 16 | {} 17 | 18 | HashEncode::~HashEncode() 19 | {} 20 | 21 | void HashEncode::into64 ( char *s, long int v, int n ) const 22 | { 23 | static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // 0 ... 63 => ascii - 64 24 | while ( --n >= 0 ) 25 | { 26 | //64 bit integer into string conversion 27 | *s++ = itoa64[v&0x3f]; 28 | v >>= 6; // right shifting 6 bits 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /HashEncode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HashEncode.h 3 | * 4 | * Created on: Aug 16, 2017 5 | * Author: root 6 | */ 7 | 8 | #ifndef HASHENCODE_H_ 9 | #define HASHENCODE_H_ 10 | 11 | class HashEncode 12 | { 13 | 14 | public : 15 | HashEncode(); 16 | ~HashEncode(); 17 | void into64 ( char *s, long int v, int n ) const; 18 | }; 19 | 20 | 21 | #endif /* HASHENCODE_H_ */ 22 | -------------------------------------------------------------------------------- /HashingAlgorithm.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "HashingAlgorithm.h" 3 | #include "MainWindow.h" 4 | #include "HashingFactory.h" 5 | #include "userproperties.h" 6 | #include 7 | 8 | /** 9 | * Constructor with connections, signals and slots 10 | */ 11 | 12 | HashingAlgorithm::HashingAlgorithm ( QWidget * parent ) : QDialog ( parent ) 13 | { 14 | setupUi ( this ); 15 | setModal ( true ); 16 | Sha512rdb->setChecked( true ); 17 | UserNameLabel->setVisible( true ); 18 | NameLabelHidden->setVisible ( false ); 19 | Blowfishrdb->setEnabled( false ); 20 | pass->setEchoMode(QLineEdit::Password); 21 | pass2->setEchoMode(QLineEdit::Password); 22 | connect( Save, SIGNAL( clicked() ), this, SLOT( setHashingAlgorithm() ) ); 23 | connect( Sha256rdb, SIGNAL( clicked() ), this, SLOT( getSha256IsChecked() ) ); 24 | connect( Sha512rdb, SIGNAL( clicked() ), this, SLOT( getSha512IsChecked() ) ); 25 | connect( MD5rdb, SIGNAL( clicked() ), this, SLOT( getMd5IsChecked() ) ); 26 | connect( Blowfishrdb, SIGNAL( clicked() ), this, SLOT( getBlowIsChecked() ) ); 27 | 28 | } 29 | 30 | HashingAlgorithm::~HashingAlgorithm() 31 | {} 32 | 33 | void HashingAlgorithm::storePassShadow(QString name, QString passhash) 34 | { 35 | std::unique_ptr fchk(new MyLibb); 36 | struct spwd spd; 37 | MainWindow main; 38 | int curdays = time ( NULL ) / ( 60 * 60 * 24 ); 39 | spd = *getspnam(name.toLatin1().data()); 40 | spd.sp_lstchg = curdays; 41 | spd.sp_pwdp = passhash.toLatin1().data(); 42 | 43 | fchk->setspnam(&spd); 44 | main.reloadUsersAndGroups(); 45 | } 46 | 47 | bool HashingAlgorithm::getBlowIsChecked() 48 | { 49 | return this->Blowfishrdb->isChecked(); 50 | 51 | } 52 | 53 | bool HashingAlgorithm::getSha256IsChecked() 54 | { 55 | return this->Sha256rdb->isChecked(); 56 | } 57 | 58 | bool HashingAlgorithm::getSha512IsChecked() 59 | { 60 | return this->Sha512rdb->isChecked(); 61 | } 62 | 63 | bool HashingAlgorithm::getMd5IsChecked() 64 | { 65 | return this->MD5rdb->isChecked(); 66 | } 67 | 68 | void HashingAlgorithm::setHashingAlgorithm() 69 | { 70 | 71 | 72 | int res = this->setPassword( NameLabelHidden->text() ); 73 | 74 | if ( res == 0 ) 75 | { 76 | QMessageBox::information( 0,tr ( "User Manager" ),tr ( "Password inserted successfully" ) ); 77 | QWidget::close(); 78 | } 79 | 80 | } 81 | 82 | /** 83 | * 84 | * This function is used to create a user password. 85 | * A form is used in order to insert a new password. 86 | * Using IHashing interface, it calls encryptpass function which is implemented in classes sha256, sha512, blowfish 87 | * and MD5 depending on the selected hashing algorithm. 88 | * The formated result is encrypted and saved inside the global variable passhash for further processing. 89 | * 90 | */ 91 | int HashingAlgorithm::setPassword(QString name) 92 | { 93 | 94 | QString passhash; 95 | QString verify = this->pass2->text(); 96 | QString passwd = this->pass->text(); 97 | 98 | bool sha256Checked = this->getSha256IsChecked(); 99 | bool sha512Checked = this->getSha512IsChecked(); 100 | bool md5Checked = this->getMd5IsChecked(); 101 | bool blowfishChecked = this->getBlowIsChecked(); 102 | 103 | if ( this->Save && sha256Checked ) 104 | { 105 | if (this->Save && (this->pass->text().toStdString() == "" || this->pass2->text().toStdString() == "" )) 106 | { 107 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Empty field. Please fill in with the new password" ) ); 108 | return 1; 109 | } 110 | 111 | if (this->Save && strncmp(passwd.toLatin1().data(), verify.toLatin1().data(), strlen(passwd.toLatin1().data())) != 0) 112 | { 113 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Passwords do not match!" ) ); 114 | return 1; 115 | } 116 | 117 | /* Choose SHA-256 Algorithm */ 118 | IHashing *psha256 = HashingFactory::Get()->CreateAlgorithm("SHA-256"); 119 | if (psha256) 120 | { 121 | passhash = psha256->encryptpass ( passwd ); 122 | this->storePassShadow(name, passhash); 123 | psha256->Free(); 124 | psha256 = NULL; 125 | } 126 | } 127 | 128 | if ( this->Save && sha512Checked ) 129 | { 130 | if (this->Save && (this->pass->text().toStdString() == "" || this->pass2->text().toStdString() == "" )) 131 | { 132 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Empty field. Please fill in with the new password" ) ); 133 | return 1; 134 | } 135 | 136 | if (this->Save && strncmp(passwd.toLatin1().data(), verify.toLatin1().data(), strlen(passwd.toLatin1().data())) != 0) 137 | { 138 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Passwords do not match!" ) ); 139 | return 1; 140 | } 141 | 142 | /* Choose SHA-512 Algorithm */ 143 | IHashing *psha512 = HashingFactory::Get()->CreateAlgorithm("SHA-512"); 144 | if (psha512) 145 | { 146 | passhash = psha512->encryptpass ( passwd ); 147 | this->storePassShadow(name, passhash); 148 | psha512->Free(); 149 | psha512 = NULL; 150 | } 151 | } 152 | 153 | if ( this->Save && blowfishChecked ) 154 | { 155 | if (this->Save && (this->pass->text().toStdString() == "" || this->pass2->text().toStdString() == "" )) 156 | { 157 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Empty field. Please fill in with the new password" ) ); 158 | return 1; 159 | } 160 | 161 | if (this->Save && strncmp(passwd.toLatin1().data(), verify.toLatin1().data(), strlen(passwd.toLatin1().data())) != 0) 162 | { 163 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Passwords do not match!" ) ); 164 | return 1; 165 | } 166 | 167 | /* Choose blowfish Algorithm */ 168 | IHashing *pblow = HashingFactory::Get()->CreateAlgorithm("blowfish"); 169 | if (pblow) 170 | { 171 | passhash = pblow->encryptpass ( passwd ); 172 | this->storePassShadow(name, passhash); 173 | pblow->Free(); 174 | pblow = NULL; 175 | } 176 | } 177 | 178 | if ( this->Save && md5Checked ) 179 | { 180 | if (this->Save && (this->pass->text().toStdString() == "" || this->pass2->text().toStdString() == "" )) 181 | { 182 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Empty field. Please fill in with the new password" ) ); 183 | return 1; 184 | } 185 | 186 | if (this->Save && strncmp(passwd.toLatin1().data(), verify.toLatin1().data(), strlen(passwd.toLatin1().data())) != 0) 187 | { 188 | QMessageBox::warning( 0,tr ( "User Manager" ),tr ( "Passwords do not match!" ) ); 189 | return 1; 190 | } 191 | 192 | /* Choose MD5 Algorithm */ 193 | IHashing *pmd5 = HashingFactory::Get()->CreateAlgorithm("MD5"); 194 | if (pmd5) 195 | { 196 | passhash = pmd5->encryptpass ( passwd ); 197 | this->storePassShadow(name, passhash); 198 | pmd5->Free(); 199 | pmd5 = NULL; 200 | } 201 | 202 | } 203 | return 0; 204 | } 205 | 206 | 207 | -------------------------------------------------------------------------------- /HashingAlgorithm.h: -------------------------------------------------------------------------------- 1 | #include "ui_HashingAlgorithm.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "myLibb.h" 8 | 9 | using namespace std; 10 | 11 | class HashingAlgorithm : public QDialog , public Ui::HashingAlgorithm 12 | { 13 | 14 | Q_OBJECT 15 | 16 | public: 17 | HashingAlgorithm( QWidget *parent = 0 ); 18 | ~HashingAlgorithm(); 19 | int setPassword(QString name); 20 | 21 | 22 | private: 23 | void storePassShadow(QString name, QString passhash); 24 | 25 | private slots: 26 | void setHashingAlgorithm(); 27 | bool getSha256IsChecked(); 28 | bool getSha512IsChecked(); 29 | bool getMd5IsChecked(); 30 | bool getBlowIsChecked(); 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /HashingFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "HashingFactory.h" 2 | #include "sha256.h" 3 | #include "sha512.h" 4 | #include "Md5.h" 5 | #include "Blowfish.h" 6 | 7 | 8 | HashingFactory::HashingFactory() 9 | { 10 | Register("SHA-256", &sha256::Create); 11 | Register("SHA-512", &sha512::Create); 12 | Register("MD5", &Md5::Create); 13 | Register("blowfish", &Blowfish::Create); 14 | } 15 | 16 | /* 17 | * Register hashing algorithms. 18 | */ 19 | void HashingFactory::Register(const std::string &HashingFactory, CreateHash pfnCreate) 20 | { 21 | m_FactoryMap[HashingFactory] = pfnCreate; 22 | } 23 | 24 | /* 25 | * this function is used in order to search for the requested hashing algorithm. 26 | */ 27 | IHashing *HashingFactory::CreateAlgorithm(const string &hashName) 28 | { 29 | 30 | FactoryMap::iterator it = m_FactoryMap.find(hashName); 31 | if ( it != m_FactoryMap.end()) 32 | return it->second(); 33 | return NULL; 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /HashingFactory.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "IHashing.h" 6 | 7 | using namespace std ; 8 | 9 | class HashingFactory 10 | { 11 | private: 12 | HashingFactory(); 13 | HashingFactory(const HashingFactory& ){} 14 | HashingFactory &operator=(const HashingFactory&){ return *this;} 15 | typedef map FactoryMap; 16 | FactoryMap m_FactoryMap; 17 | public: 18 | ~HashingFactory() {m_FactoryMap.clear();} 19 | static HashingFactory *Get() 20 | { 21 | static HashingFactory instance; 22 | return &instance; 23 | } 24 | void Register(const std::string &HashingFactory, CreateHash pfnCreate); 25 | IHashing *CreateAlgorithm(const string &hashName); 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /IHashing.h: -------------------------------------------------------------------------------- 1 | #ifndef IHASHING_H_ 2 | #define IHASHING_H_ 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | class IHashing 9 | { 10 | public: 11 | virtual ~IHashing(){}; 12 | virtual char* encryptpass(QString passwd) const = 0; 13 | virtual void Free() = 0; 14 | }; 15 | 16 | 17 | //create function pointer 18 | typedef IHashing* (*CreateHash)(void); 19 | 20 | #endif /* IHASHING_H_ */ 21 | -------------------------------------------------------------------------------- /InputDialogValidator.cpp: -------------------------------------------------------------------------------- 1 | #include "InputDialogValidator.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | InputDialogValidator::InputDialogValidator(QWidget *parent, Qt::WindowFlags flags) : QDialog(parent) 10 | { 11 | 12 | this->setAttribute(Qt::WA_QuitOnClose, false); 13 | 14 | if(flags!=0) setWindowFlags(flags); 15 | 16 | QVBoxLayout *l=new QVBoxLayout(this); 17 | 18 | label=new QLabel(this); 19 | 20 | // Security Fix : Whitelisted characters digits and symbols 21 | QRegExp regExp("^[a-zA-Z0-9-_]+$"); 22 | //regExp=QRegExp("^[a-zA-Z0-9-_]{0,12}$"); 23 | 24 | validator=new QRegExpValidator(regExp); 25 | 26 | text=new QLineEdit(this); 27 | 28 | text->setValidator(validator); 29 | 30 | connect(text, SIGNAL(textChanged(QString)), this, SLOT(checkValid(QString))); 31 | 32 | buttonBox=new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, Qt::Horizontal, this); 33 | 34 | connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 35 | connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 36 | 37 | l->addWidget(label); 38 | l->addWidget(text); 39 | l->addWidget(buttonBox); 40 | } 41 | 42 | InputDialogValidator::~InputDialogValidator() 43 | { 44 | 45 | } 46 | 47 | void InputDialogValidator::setTitle(const QString &title){ 48 | setWindowTitle(title); 49 | } 50 | 51 | void InputDialogValidator::setLabelText(const QString &label){ 52 | this->label->setText(label); 53 | } 54 | 55 | void InputDialogValidator::setText(const QString &text) 56 | { 57 | this->text->setText(text); 58 | } 59 | 60 | void InputDialogValidator::setRegExp(const QRegExp ®Exp){ 61 | validator->setRegExp(regExp); 62 | checkValid(text->text()); 63 | } 64 | 65 | QString InputDialogValidator::getLabelText(){ 66 | return label->text(); 67 | } 68 | 69 | QString InputDialogValidator::getText(){ 70 | return text->text(); 71 | } 72 | 73 | void InputDialogValidator::checkValid(const QString &text) 74 | { 75 | QString _text=QString(text); 76 | int pos=0; 77 | bool valid=validator->validate(_text, pos)==QRegExpValidator::Acceptable; 78 | buttonBox->button(QDialogButtonBox::Ok); 79 | buttonBox->setEnabled(valid); 80 | } 81 | 82 | QString InputDialogValidator::getText(QWidget *parent, const QString &title, const QString &label, const QString &text, const QRegExp ®Exp, bool *ok, Qt::WindowFlags flags) 83 | { 84 | InputDialogValidator *r = new InputDialogValidator(parent, flags); 85 | 86 | r->setTitle(title); 87 | r->setLabelText(label); 88 | r->setText(text); 89 | r->setRegExp(regExp); 90 | 91 | *ok = r->exec()==QDialog::Accepted; 92 | 93 | if(*ok) 94 | return r->getText(); 95 | else 96 | return QString(); 97 | } 98 | 99 | -------------------------------------------------------------------------------- /InputDialogValidator.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUTDIALOGVALIDATOR_H 2 | #define INPUTDIALOGVALIDATOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class InputDialogValidator : public QDialog{ 11 | 12 | Q_OBJECT 13 | public: 14 | InputDialogValidator(QWidget *parent, Qt::WindowFlags flags); 15 | ~InputDialogValidator(); 16 | void setTitle(const QString &title); 17 | void setLabelText(const QString &label); 18 | void setText(const QString &text); 19 | void setRegExp(const QRegExp ®Exp); 20 | 21 | QString getLabelText(); 22 | QString getText(); 23 | 24 | static QString getText(QWidget *parent, const QString &title, const QString &label, const QString &text, const QRegExp ®Exp, bool *ok, Qt::WindowFlags flags=0); 25 | 26 | signals: 27 | 28 | private slots: 29 | void checkValid(const QString &text); 30 | 31 | private: 32 | QLabel *label; 33 | QLineEdit *text; 34 | QDialogButtonBox *buttonBox; 35 | QRegExp regExp; 36 | QRegExpValidator *validator; 37 | }; 38 | 39 | #endif // INPUTDIALOGVALIDATOR_H 40 | -------------------------------------------------------------------------------- /MainWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | // 4 | #include "ui_mainwindow.h" 5 | #include "ui_UserProperties.h" 6 | #include "ui_EditProperties.h" 7 | #include "ui_GroupProperties.h" 8 | #include "ui_Settings.h" 9 | #include "ui_About.h" 10 | #include "userproperties.h" 11 | #include "editProperties.h" 12 | #include "groupProperties.h" 13 | #include "Settings.h" 14 | #include "About.h" 15 | #include "users.h" 16 | #include "myLibb.h" 17 | #include "groups.h" 18 | #include "models.h" 19 | #include "pathfile.h" 20 | #include 21 | /** 22 | * Η MainWindow είναι η κλάση ορίου-διεπαφής στην οποία βρίσκεται η αρχική φόρμα που εμφανίζεται στο πρόγραμμα. Σε αυτήν την φόρμα εμφανίζονται και οι βασικές πληροφορίες για τους χρήστες και τις ομάδες του συστήματος. Οι περισσότερες ενέργειες του προγράμματος ξεκινάνε από την MainWindow,ανάμεσα τους και οι ενέργειες της εισαγωγής,διαγραφής,επεξεργασίας,αναζήτησης χρηστών και ομάδων. Επικοινωνεί με όλες τις κλάσεις του προγράμματος για να είναι εφικτή η δημιουργία αντικειμένων από αυτές. Οι περισσότερες συναρτήσεις της αντιστοιχούν στις ενέργειες που μπορεί να εκτελέσει ο διαχειριστής από την αρχική φόρμα. Για κάθε ενέργεια που ξεκινάει από την φόρμα,υπάρχει και μια σύνδεση στον constructor της κλάσης που συνδέει το κάθε signal-ενέργεια με την αντίστοιχη slot-υλοποίηση και είναι της μορφής : 23 | 24 | connect( addUserBtn,SIGNAL( clicked() ),this,SLOT( addUserBtnClicked() ) ); 25 | 26 | Στο παραπάνω παράδειγμα αντιστοιχίζεται το 'κλικ' στο κουμπί της εισαγωγής νέου χρήστη με την συνάρτηση addUserBtnClicked().Έτσι μόλις πατηθεί το κουμπί για την εισαγωγή το πρόγραμμα θα υλοποιήσει τον κώδικα που βρίσκεται μέσα στην addUserBtnClicked(). 27 | */ 28 | 29 | class MainWindow : public QMainWindow, public Ui::MainWindow 30 | { 31 | Q_OBJECT 32 | public: 33 | MainWindow( QWidget * parent = 0, Qt::WindowFlags f = 0 ); 34 | ~MainWindow(); 35 | 36 | 37 | protected: 38 | bool eventFilter(QObject* obj , QEvent* e); 39 | 40 | public slots: 41 | void reloadUsersAndGroups(); 42 | 43 | private: 44 | 45 | QStandardItemModel *userModel; 46 | QStandardItemModel *groupModel; 47 | QStandardItemModel *foundedUserModel; 48 | QStandardItemModel *foundedGroupModel; 49 | QString log; 50 | QString fnam; 51 | QString office1 ; 52 | QString office2 ; 53 | QString address ; 54 | QString dir; 55 | QString ui; 56 | QStringList shell; 57 | struct passwd *users_info; 58 | struct group *groups_info; 59 | void loadUsersAndGroups( ); 60 | void initialize(); 61 | Spc *spc; 62 | 63 | private slots: 64 | void tabChanged( int tab ); 65 | void aboutUserManager(); 66 | void folderSizeCheckBoxClicked(); 67 | void addGroupBtnClicked(); 68 | void setPassMenu(); 69 | void searchUserBtnClicked(); 70 | void addUserBtnClicked(); 71 | void searchGroupBtnClicked(); 72 | void UserDetails(); 73 | void GroupDetails(const QModelIndex &index ); 74 | void beautyTree( QTreeView *tree, int columns ); 75 | void getSelectedUserInfo( const QModelIndex &index ); 76 | void getSelectedGroupInfo( const QModelIndex &index ); 77 | void clearEditBoxes(); 78 | void calculateFolderSize(); 79 | void deleteUser(); 80 | int deleteGroup(); 81 | void EditUser(); 82 | void editGroup(); 83 | void getEditDetails(const QModelIndex&); 84 | void openSettings(); 85 | void createBackup(); 86 | 87 | }; 88 | #endif 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /Md5.cpp: -------------------------------------------------------------------------------- 1 | #include "Md5.h" 2 | #include 3 | #include 4 | #include 5 | 6 | IHashing *Md5::Create() 7 | { 8 | return new Md5(); 9 | } 10 | 11 | void Md5::Free() 12 | { 13 | delete this; 14 | } 15 | 16 | /* Hashing */ 17 | 18 | char *Md5::encryptpass( QString passwd) const 19 | { 20 | HashEncode *hEnc = new HashEncode(); 21 | static char seed[12]; 22 | seed[0] = '$'; 23 | seed[1] = '1'; 24 | seed[2] = '$'; 25 | /* 26 | * it produces different sets with pseudorandom numbers everytime the programm runs 27 | * To continue, the srandom function returns random numbers in relation with the set of numbers being created from srandom 28 | */ 29 | srandom ( ( int ) time ( ( time_t * ) NULL ) ); 30 | hEnc->into64 ( &seed[3], random(),saltLength ); 31 | hEnc->into64 ( &seed[saltLength],random(),3 ); 32 | seed[saltLength+3] = '$'; 33 | 34 | if (hEnc != nullptr ) 35 | {delete hEnc; 36 | hEnc = nullptr;} 37 | 38 | char *buf = ( char * )calloc ( 512, sizeof(*buf) ); 39 | char *password = passwd.toLatin1().data(); 40 | memcpy ( buf,password,strlen(password)); 41 | 42 | /* 43 | * The crypt_r function does the same thing as crypt, 44 | * but takes an extra parameter which includes space for its result (among other things), 45 | * so it can be reentrant. data->initialized must be cleared to zero before the first time crypt_r is called 46 | */ 47 | struct crypt_data data; 48 | data.initialized = 0; 49 | 50 | char *pass = crypt_r ( buf,seed, &data); 51 | 52 | if ( pass == NULL ) 53 | QMessageBox::critical ( 0,QObject::tr ( "User Manager" ),QObject::tr ( "%1" ).arg ( ENOSYS ) ); 54 | if (buf!=NULL)free(buf); 55 | return strdup ( pass ); 56 | } 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Md5.h 3 | * 4 | * Created on: Aug 16, 2017 5 | * Author: root 6 | */ 7 | 8 | #ifndef MD5_H_ 9 | #define MD5_H_ 10 | 11 | #include 12 | #include 13 | #include "HashEncode.h" 14 | #include "IHashing.h" 15 | 16 | class Md5 : public IHashing 17 | { 18 | public: 19 | static const int saltLength = 8; 20 | char* encryptpass(QString passwd) const; 21 | void Free(); 22 | static IHashing* Create(); 23 | }; 24 | 25 | 26 | 27 | #endif /* MD5_H_ */ 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # ![UserManager](https://user-images.githubusercontent.com/12726776/80515471-b3028380-898a-11ea-9aac-f1d0e44628b5.gif) UserManager 5 | 6 | 7 | ![Language](https://img.shields.io/badge/Language-C%2FC%2B%2B-yellow) ![license](https://img.shields.io/github/license/xvass/UserManager) ![openissues](https://img.shields.io/github/issues/xvass/UserManager) ![closedissues](https://img.shields.io/github/issues-closed-raw/xvass/UserManager) ![forks](https://img.shields.io/github/forks/xvass/UserManager) ![stars](https://img.shields.io/github/stars/xvass/UserManager) ![version](https://img.shields.io/badge/version-1.0.75-brightgreen) ![last_commit](https://img.shields.io/github/last-commit/xvass/UserManager) ![beta](https://img.shields.io/badge/status-beta-lightgrey) ![counter](https://enisjijudcevtuq.m.pipedream.net) 8 | 9 | | Branch | Linux Build | 10 | |--------|:----------------:| 11 | | master | [![Build Status](https://travis-ci.com/xvass/UserManager.svg?branch=master)](https://travis-ci.com/xvass/UserManager) | 12 | 13 | --- 14 | 15 | # !!! This project is no longer maintained !!! 16 | 17 | --- 18 | 19 | ### General Information 20 | 21 | ---------------------- 22 | 23 |

24 | UserManager is a software tool developed using C/C++ and Qt framework. It has been designed to provide Linux systems administration assistance regarding the managment of user accounts and groups. This application was part of an assignment many years ago since 2006 when i was still at University. Im still contributing to this project because it is a great resource that helps me develop and maintain my skills in C/C++. Nevertheless it certainly needs functional improvements, as well as security focused improvements. 25 |

26 | 27 |
28 |

29 | The UserManager application has a friendly dashboard and offers the following functionality 30 |

31 | 32 | * add,edit,delete user accounts and groups 33 | * add users to groups 34 | * search users 35 | * search groups 36 | * remove users from groups 37 | * set primary groups 38 | * add members to groups 39 | * remove members from groups 40 | * add individual groups 41 | * show and edit user information 42 | * set UIDs and GIDs 43 | * set users passwords 44 | * set working directories 45 | * passwords aging 46 | * set account expiration 47 | * enable or disable user accounts 48 | * show disk usage 49 | * set working shells 50 | 51 | TODO : 52 | 53 | * Application usage from low privileged users ( High Priority ) 54 | * Implement password generator 55 | * Implement password strength checks 56 | * Implement password suggestions 57 | * Send an email to the users in case their passwords are about to be expired 58 | 59 | ------------------ 60 | 61 | 62 | ### Installation Info 63 | 64 | * This application has been tested in 64bit Linux Debian and Ubuntu distributions. 65 | 66 | 67 | ### Succesfully tested in the following architectures 68 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 | - Linux 5.3.0-kali2-amd64 #1 SMP Debian 5.3.9-3kali1 (2019-11-20) x86_64 GNU/Linux 70 | 71 | - Linux 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux 72 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | 74 | ------------------ 75 | 76 | ### Installation prerequisites ( optional ) 77 | 78 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 79 | sudo apt install libcanberra-gtk-module libcanberra-gtk3-module 80 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 81 | 82 | ### Installation 83 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 | git clone https://github.com/xvass/UserManager.git 85 | cd UserManager 86 | chmod +x install_and_run.sh 87 | ./install_and_run.sh 88 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 89 | 90 | ### UserManager Main View 91 | ------------------------ 92 | 93 |

94 | 95 |

96 | 97 | ### User Properties 98 | ------------------ 99 | 100 |

101 | 102 |

103 | 104 | ### Disk Quota 105 | -------------- 106 | 107 |

108 | 109 |

110 | 111 | ### User Groups 112 | -------------- 113 | 114 |

115 | 116 |

117 | 118 | ### Modify Groups 119 | -------------- 120 | 121 |

122 | 123 |

124 | 125 | ### Password Manager 126 | ------------------- 127 | 128 |

129 | 130 |

131 | 132 | ### Groups 133 | ----------- 134 | 135 |

136 | 137 |

138 | 139 | ### Set Password 140 | ---------------- 141 | 142 |

143 | 144 |

145 | 146 | ### Group Privileges 147 | -------------------- 148 | 149 |

150 | 151 |

152 | -------------------------------------------------------------------------------- /Settings.cpp: -------------------------------------------------------------------------------- 1 | #include "MainWindow.h" 2 | using namespace std; 3 | 4 | /** 5 | * Components Initialization 6 | */ 7 | Settings::Settings ( QWidget * parent ) : QDialog ( parent ) 8 | { 9 | 10 | setupUi ( this ); 11 | QValidator *validator = new QIntValidator ( 1, 65535, this );//to validator pernei orisma mono int apo 1-65536 kai dhlwnei oti dexetai mono mono kapoia timh apo ayto to eyros 12 | minGidEdit->setValidator ( validator );//ta editboxes pernoun ton validator wste na mhn mpainei text alla mono int apo 1-65536 sto pedio tou edit 13 | minUidEdit->setValidator ( validator ); 14 | 15 | 16 | connect ( warnCheckBox, SIGNAL ( clicked() ), this, SLOT ( sendMail() ) ); 17 | connect ( okSetBtn, SIGNAL ( clicked() ), this, SLOT ( applySettings() ) ); 18 | connect ( okSetBtn, SIGNAL ( clicked() ), this, SLOT ( close() ) ); 19 | 20 | initialSettings(); 21 | } 22 | 23 | /** 24 | * Destructor 25 | */ 26 | Settings::~Settings() 27 | {} 28 | 29 | 30 | void Settings::initialSettings() 31 | { 32 | //edw pairnoume tis arxikes ry8miseis thn stigmh pou anougetai h settings kai tis apo8hkeyoume stis metavlhtes wste na elegxoume otan kleisei to para8yro twn ry8misewn poies exoun alaxtei 33 | //gia to mail den xreiazetai na elegxoume an einai checked h oxi giati analoga me poio ap ta 2 8a epilexei o xrhsths enhmerwnetai kai to conf kai to checkbox mesa sthn sendMail 34 | //oi metavlhtes einai dhlwmene sto .h 35 | minUIDprop=this->getconf ( "MINIMUM_GID" ).c_str(); 36 | minGIDprop=this->getconf ( "MINIMUM_UID" ).c_str(); 37 | //dinoume sta checkbox kai editbox tis ry8miseis tou conf 38 | std::string warn; 39 | warn=this->getconf ( "WARN_USER" ); 40 | if ( warn=="yes" ) 41 | warnCheckBox->setChecked ( true ); 42 | else 43 | warnCheckBox->setChecked ( false ); 44 | 45 | minGidEdit->setText ( getconf ( "MINIMUM_GID" ).c_str() ); 46 | minUidEdit->setText ( getconf ( "MINIMUM_UID" ).c_str() ); 47 | 48 | 49 | languageCombo->addItem("Greek"); 50 | languageCombo->addItem("English"); 51 | languageCombo->setItemIcon(0,QIcon("/usr/share/apps/UserManager/pics/greek.jpeg")); 52 | languageCombo->setItemIcon(1,QIcon("/usr/share/apps/UserManager/pics/uk.jpeg")); 53 | if(getconf("LANGUAGE")=="English") 54 | languageCombo->setCurrentIndex(1); 55 | else 56 | languageCombo->setCurrentIndex(0); 57 | } 58 | /** 59 | * Η συνάρτηση διαβάζει μια ρύθμιση από το usermanager.conf 60 | παιρνάμε σαν όρισμα τον τίτλο της ρύθμισης που θέλουμε και μας επιστρέφει το string της ρύθμισης 61 | π.χ η κλήση getconf("LANGUAGE") θα μας επιστρέψει ένα string το οποίο θα είναι ή "GREEK" ή "ENGLISH" 62 | */ 63 | std::string Settings::getconf ( std::string setting ) 64 | { 65 | string line; 66 | size_t found=' '; 67 | size_t pos=' '; 68 | 69 | fstream conf ( "/usr/share/apps/UserManager/other/usermanager.conf",ios::in ); 70 | conf.seekg ( 0 );//metaferei ton deikth sthn arxh tou arxeiou.xreiazetai an den exei ginei swsto close tou arxeiou apo prohgoumenh anazhthsh 71 | if ( !conf.is_open() ) 72 | return ""; 73 | while ( getline ( conf,line ) ) 74 | if ( ( found = line.find ( setting,0 ) ) != string::npos ) //vre8hke h ry8mish 75 | { 76 | pos=line.find ( "=",0 ); //psaxnei th 8esh pou yparxei to = pou diaxwrizei ton titlo ths ru8mishs ap thn ry8mish 77 | line.erase ( 0,pos+1 ); //svhnei apo thn arxh mexri kai to = (to = einai sto pos+1) kai sthn line menei h telikh ry8mish pou 8eloume 78 | break; 79 | } 80 | 81 | conf.close(); 82 | return line; 83 | 84 | } 85 | /** 86 | * Η συνάρτηση αλλάζει μια ρύθμιση στο usermanager.conf.παίρνοντας τον τίτλο της ρύθμισης προς αλλαγή και την τιμή της ρύθμισης. 87 | Αν θέλουμε να αλλάξουμε την γλώσσα θα καλέσουμε setconf("LANGUAGE","ENGLISH") 88 | */ 89 | void Settings::setConf ( QString title, QString setting ) 90 | { 91 | //allazei mia ry8mish sto conf.txt.px an 8eloume na allaxoume to MINIMUM_UID=1000 se MINIMUM_UID=2000 pername thn setconf("MINIMUM_UID","2000") 92 | char *cmd; 93 | 94 | // TO-DO 95 | // 96 | // Consider Security issues here ! 97 | 98 | // Security fix : change system with execve or execl and sanitize input ane env 99 | // 100 | 101 | QString command="sed -i '/"+ title +"/s/=.*/="+setting+"/g' /usr/share/apps/UserManager/other/usermanager.conf"; 102 | cmd=command.toLatin1().data(); 103 | system ( cmd ); 104 | 105 | } 106 | 107 | /* 108 | ************************************************************************************* 109 | * Ενέργεια αποστολής mail σε χρήστες των οποίων ο κωδικός είναι προς λήξη. 110 | Δημιουργεί αν δεν υπάρχει ένα αρχείο cron στον φάκελο /var/spool/cron/crontabs για τον root τον οποίο περιέχει εντολή ώστε να τρέχει το 111 | script κελύφους exp.sh.Το συγκεκριμένο script διαβάζει το αρχείο /etc/shadow και ψάχνει λογαριασμούς χρηστών οι οποίοι λήγουν μέσα στις 112 | επόμενες 7 μέρες.Αν βρεθεί χρήστης το script τον ενημερώνει στέλνοντάς του mail μέσω του συστήματος. Ο daemon crond του κάθε συστήματος ψάχνει ανά κάποιο χρονικό διάστημα (2-4 ώρες) τον φάκελο crontabs για τις προγραμματισμένες εργασίες χρηστών, οπότε υπάρχει μια μικρή καθυστέρηση μέχρι να δει την κάθε προγραμματισένη εργασία. 113 | Η γραμμή "echo 0x1A | echo '01 * * * * sh /usr/share/apps/UserManager/other/exp.sh' | crontab - -u root" περιλαμβάνει 3 ενέργειες. 114 | Πρώτα η "crontab - -u root" δημιουργεί ένα αρχείο με το όνομα root μέσα στο φάκελο /var/spool/cron/crontabs/ 115 | Με την εντολή "echo '* 01 * * * sh /usr/share/apps/UserManager/other/exp.sh'" εισάγεται η γραμμή στο αρχείο η οποία ουστιαστικά σημαίνει 116 | ότι το σύστημα θα πρέπει να τρέχει την παραπάνω εντολή κάθε πρώτη ώρα της μέρας 117 | Με την εντολή "echo 0x1A" δηλώνουμε στο κέλυφος ότι έχουμε τελειώσει την εγγραφή στο αρχείο root.Το 0x1A ισοδυναμεί με Ctrl+D. 118 | Ετσι καταφέρνουμε να τρέχει το script exp.sh μία φορά τη μέρα ανεξάρτητα από το ποιος χρήστης είναι logged in στο σύστημα,γιατί το 119 | cron ενεργεί ακόμα και αν ο χρήστης root δεν έχει μπει στο σύστημα. 120 | Το mail προειδοποίησης που λαμβάνει ο χρήστης έχει την παρακάτω μορφή: 121 | 122 | ****************************************************8 123 | fts@Debian:~$ mail 124 | 125 | "/var/mail/fts": 1 message 1 new 126 | 127 | >N 1 root Τετ Οκτ 22 15/486 Password Expiration 128 | 129 | & 1 130 | 131 | Subject: Password Expiration 132 | 133 | To: 134 | 135 | From: root 136 | 137 | Date: Wed, 22 Oct 2008 14:45:08 +0300 138 | 139 | Your password on Debian will be expired in 1 days 140 | 141 | & 142 | ************************************************************************************** 143 | */ 144 | 145 | 146 | /** 147 | * 148 | * Considering a Security issue here 149 | * Change debian mail with email 150 | * 151 | * TO-DO 152 | * 153 | */ 154 | void Settings::sendMail ( ) 155 | { 156 | std::string command="exp.sh"; 157 | string line; 158 | bool done=false; 159 | size_t found=' '; 160 | ifstream file("/var/spool/cron/crontabs/root",ios::out); 161 | if (!file) 162 | { 163 | system("echo 0x1A | echo '01 * * * * sh /usr/share/apps/UserManager/other/exp.sh' | crontab - -u root");//0x1A=EOF/CTRL+D 164 | file.close(); 165 | } 166 | else 167 | { 168 | fstream file ( "/var/spool/cron/crontabs/root",ios::in|ios::out ); 169 | file.seekg ( 0 ); 170 | while ( getline ( file,line ) ) 171 | { 172 | if ( ( found = line.find ( command,0 ) ) != string::npos ) 173 | { 174 | done=true; 175 | // Security fix : sanitize env 176 | // 177 | //TODO 178 | system ( "sed -i '/exp.sh/d' /var/spool/cron/crontabs/root" ); // delete exp.sh 179 | setConf("WARN_USER","no"); //update conf 180 | break; 181 | } 182 | } 183 | file.close(); 184 | if ( !done ) 185 | { 186 | system("echo '01 * * * * sh /usr/share/apps/UserManager/other/exp.sh' >> /var/spool/cron/crontabs/root"); 187 | setConf("WARN_USER","yes"); //update conf 188 | } 189 | 190 | 191 | } 192 | } 193 | 194 | 195 | /** 196 | *Αποθηκεύει τις νέες ρυθμίσεις που θα επιλέξει ο διαχειριστής στο usermanager.conf 197 | ελέγχει αν οι ρυθμίσεις που εισήχθησαν στην φόρμα είναι ίδιες με αυτές του αρχείου.Άν δεν είναι τις αλλάζει μέσα στο usermanager.conf μέσω της συνάρτησης setconf(..) 198 | */ 199 | void Settings::applySettings() 200 | { 201 | //edw molis path8ei to ok ths formas ginetai o elegxos an exei alaxtei kamia ry8mish kai analoga enhmerwnoume to conf. 202 | if (minUIDprop!=minUidEdit->text()) 203 | setConf("MINIMUM_UID",minUidEdit->text()); 204 | if (minGIDprop!=minGidEdit->text()) 205 | setConf("MINIMUM_GID",minGidEdit->text()); 206 | QString ax1,ax2; 207 | ax1=languageCombo->currentText(); 208 | ax2=getconf("LANGUAGE").c_str(); 209 | if (languageCombo->currentText().toStdString()!=getconf("LANGUAGE"))//an to conf symfwnei me to text ap to combo sthn forma 210 | { 211 | setConf("LANGUAGE",languageCombo->currentText()); 212 | QMessageBox::information ( 0,tr ( "User Manager" ),tr ( "Language will change after program restarts" ) ); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /Settings.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_H 2 | #define SETTINGS_H 3 | #include "ui_Settings.h" 4 | #include 5 | 6 | 7 | 8 | 9 | /* 10 | 8a ftiaxoume ena arxeio usermanager.conf(to kana conf.txt dokimastika) to opoio 8a exei oles tis ry8miseis kai 8a einai ths morfhs 11 | WARN_USER:yes 12 | MINIMUM_UID:1000 13 | MINIMUN_GID:1000 kok.. mia seira gia ka8e ry8mish 14 | 8a mpei mia synarthsh edw ston constructor pou 8a pairnei oles tis ry8miseis apo to arxeio ry8misewn kai analoga 15 | 8a kanei arxikopoihsh ola ta checkbox/editboxes h otidhpote xreiazetai sthn forma ry8misewn 16 | h synarthsh pou 8a diavazei tis ry8miseis(h getconf("string")) mia mia 8a pernei san orisma ton titlo tis ry8mishs pou 8eloume na diavasoume kai 8a epistrefei oti yparxei meta to : tou titlou 17 | 8a psaxnei px to text WARN_USER sto arxeio kai 8a vriskei poia einai h ry8mish tou ..ara ypoti8etai 8a epistrepsei yes h no h an dwsoume MINIMUM_GID 8a epistrepsei 1000 px. 18 | an YES to checkbox warnCheckbox sth forma 8a einai checked alliws unchecked 19 | */ 20 | 21 | 22 | 23 | 24 | /** 25 | Κλάση αποθήκευσης βασικών ρυθμίσεων της εφαρμογής σε ένα αρχείο usermanager.conf .Το usermanager.conf έχει την μορφή; 26 | WARN_USER:yes 27 | MINIMUM_UID:1000 28 | MINIMUN_GID:1000 κοκ 29 | και κάθε μια γραμμή αντιστοιχεί και σε μια διαφορετική ρύθμιση για το πρόγραμμα.Διατηρώντας αυτό το αρχείο σε έναν φάκελο μπορούμε να 30 | αποθηκεύσουμε ρυθμίσεις οι οποίες δεν θα σβήνονται κάθε φορά που κλείνει το πρόγραμμα. Μέσω των συναρτήσεων setConf(..) και getconf(..) 31 | αποθηκεύουμε μια ρύθμιση ή την διαβάζουμε αντίστοιχα. 32 | */ 33 | /** 34 | * Κλάση αποθήκευσης βασικών ρυθμίσεων της εφαρμογής σε ένα αρχείο usermanager.conf 35 | */ 36 | class Settings : public QDialog , public Ui::Settings 37 | { 38 | Q_OBJECT 39 | public: 40 | 41 | Settings ( QWidget *parent = 0 ); 42 | ~Settings(); 43 | void setConf ( QString title, QString setting ); 44 | std::string getconf ( std::string setting ); 45 | 46 | 47 | private: 48 | QString minUIDprop,minGIDprop; 49 | void initialSettings(); 50 | 51 | 52 | private slots: 53 | void sendMail(); 54 | void applySettings(); 55 | 56 | }; 57 | #endif 58 | -------------------------------------------------------------------------------- /UserManager: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/UserManager -------------------------------------------------------------------------------- /UserManager.pro: -------------------------------------------------------------------------------- 1 | ###################################################################### 2 | # Automatically generated by qmake (3.1) Wed Mar 31 19:43:06 2021 3 | ###################################################################### 4 | 5 | TEMPLATE = app 6 | TARGET = UserManager 7 | INCLUDEPATH += . 8 | 9 | # The following define makes your compiler warn you if you use any 10 | # feature of Qt which has been marked as deprecated (the exact warnings 11 | # depend on your compiler). Please consult the documentation of the 12 | # deprecated API in order to know how to port your code away from it. 13 | DEFINES += QT_DEPRECATED_WARNINGS 14 | 15 | # You can also make your code fail to compile if you use deprecated APIs. 16 | # In order to do so, uncomment the following line. 17 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 18 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 19 | 20 | # Input 21 | HEADERS += About.h \ 22 | Blowfish.h \ 23 | editProperties.h \ 24 | groupProperties.h \ 25 | groups.h \ 26 | HashEncode.h \ 27 | HashingAlgorithm.h \ 28 | HashingFactory.h \ 29 | IHashing.h \ 30 | InputDialogValidator.h \ 31 | MainWindow.h \ 32 | Md5.h \ 33 | models.h \ 34 | myLibb.h \ 35 | pathfile.h \ 36 | Settings.h \ 37 | sha256.h \ 38 | sha512.h \ 39 | spc.h \ 40 | userproperties.h \ 41 | users.h 42 | FORMS += ui/About.ui \ 43 | ui/EditProperties.ui \ 44 | ui/GroupProperties.ui \ 45 | ui/HashingAlgorithm.ui \ 46 | ui/mainwindow.ui \ 47 | ui/Settings.ui \ 48 | ui/UserProperties.ui 49 | SOURCES += About.cpp \ 50 | Blowfish.cpp \ 51 | editProperties.cpp \ 52 | groupProperties.cpp \ 53 | groups.cpp \ 54 | HashEncode.cpp \ 55 | HashingAlgorithm.cpp \ 56 | HashingFactory.cpp \ 57 | InputDialogValidator.cpp \ 58 | main.cpp \ 59 | MainWindow.cpp \ 60 | Md5.cpp \ 61 | models.cpp \ 62 | myLibb.cpp \ 63 | Settings.cpp \ 64 | sha256.cpp \ 65 | sha512.cpp \ 66 | spc.cpp \ 67 | userproperties.cpp \ 68 | users.cpp 69 | RESOURCES += resources/images.qrc 70 | TRANSLATIONS += language/el.ts 71 | QMAKE_CXXFLAGS += -std=c++11 -O2 -fstack-protector-all -Wformat -Werror=format-security 72 | QMAKE_CPPFLAGS += -Wdate-time -D_FORTIFY_SOURCE=2 73 | QMAKE_CFLAGS += -O2 -fstack-protector-all -Wformat -Werror=format-security 74 | LDFLAGS += -Wl,-z,relro 75 | CONFIG += qt debug 76 | QMAKE_LIBS += -lcrypt 77 | QT += widgets 78 | # installation 79 | installfiles.files += usermanager 80 | installfiles.path += /usr/bin/ 81 | INSTALLS += installfiles 82 | -------------------------------------------------------------------------------- /editProperties.h: -------------------------------------------------------------------------------- 1 | #ifndef EDITPROPERTIES_H 2 | #define EDITPROPERTIES_H 3 | #include "ui_EditProperties.h" 4 | #include "ui_HashingAlgorithm.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "userproperties.h" 13 | #include "myLibb.h" 14 | 15 | /** 16 | * Σε αυτήν την φόρμα εμφανίζονται όλες οι πληροφορίες του χρήστη που έχει επιλεχθεί για επεξεργασία. 17 | * Από αυτήν ξεκινάνε όλες οι ενέργειες επεξεργασίας που μπορούν να γίνουν σε ένα λογαριασμό, 18 | * ανάμεσα τους η επεξεργασία ονόματος και προσωπικών στοιχείων του χρήστη,ενεργοποίηση/απενεργοποίηση του λογαριασμού,εισαγωγή/διαγραφή του χρήστη από ομάδες, 19 | * αλλαγή κύριας ομάδας του χρήστη,ορισμός κωδικών,και δυνατότητες για την διάρκεια που θα είναι ενεργός ο λογαριασμός. 20 | */ 21 | class EditProperties : public QDialog , public Ui::EditProperties 22 | { 23 | Q_OBJECT 24 | public: 25 | void setOldUsername (const QString oldUsername ); 26 | QString getOldUsername(); 27 | EditProperties( QWidget *parent = 0 ); 28 | ~EditProperties(); 29 | void comboShell(); 30 | void acct_shadow(struct spwd spw); 31 | int set_password(QString nam); 32 | int set_shad_expire(QString months,int days_value,int years_value); 33 | 34 | private: 35 | void set_account(bool set); 36 | QString oldUsername_; 37 | 38 | private slots: 39 | void set_Pass_info(); 40 | void ok_to_edit_Button(); 41 | void changeMembers(const QModelIndex &index ); 42 | void fillEasyList(); 43 | void easyCheckboxClicked(); 44 | void easyAddGroups(const QModelIndex &index); 45 | void setPrimaryGroup(); 46 | void disablechk(); 47 | void browse(); 48 | void openHashingAlgorithm(); 49 | }; 50 | #endif 51 | -------------------------------------------------------------------------------- /exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # 4 | HOST=`uname -n` 5 | 6 | email_user() { 7 | echo "Your password on $HOST will be expired in $DAYS_UNTIL_PASS_EXPIRE days!" | mail -s "Password Expiration" $USER 8 | 9 | } 10 | 11 | ## Today's date (expressed in epoch format) 12 | today=`/usr/bin/perl -e 'printf("%d\n", (time/60/60/24))'` 13 | 14 | for line in `cat /etc/shadow | egrep -v "sscop|root|NP|LK"` 15 | do 16 | USER=`echo $line | awk -F: '{print $1}'` 17 | DAY_LAST_PASS_CHANGE=`echo $line | awk -F: '{print $3}'` 18 | DAYS_PASS_VALID=`echo $line | awk -F: '{print $5}'` 19 | DAYS_SINCE_LAST_PASS_CHANGE=`expr $today - $DAY_LAST_PASS_CHANGE` 20 | DAYS_UNTIL_PASS_EXPIRE=`expr $DAYS_PASS_VALID - $DAYS_SINCE_LAST_PASS_CHANGE` 21 | 22 | 23 | if [ $DAYS_UNTIL_PASS_EXPIRE -lt "8" ]; then 24 | 25 | 26 | email_user $DAYS_UNTIL_PASS_EXPIRE 27 | fi 28 | 29 | done -------------------------------------------------------------------------------- /groupProperties.cpp: -------------------------------------------------------------------------------- 1 | #include "MainWindow.h" 2 | #include 3 | #include "myLibb.h" 4 | #include "spc.h" 5 | 6 | /** 7 | * Constructor κλάσης/φόρμας 8 | */ 9 | 10 | GroupProperties::GroupProperties ( QWidget * parent ) : QDialog ( parent ) 11 | { 12 | setupUi ( this ); 13 | setModal ( true ); 14 | QValidator *validator = new QIntValidator(1, 65535, this); 15 | GIDEdit->setValidator(validator); 16 | connect ( addBtn, SIGNAL ( clicked( ) ), this, SLOT ( addMembers( ) ) ); 17 | connect ( removeBtn, SIGNAL ( clicked( ) ), this, SLOT ( removeMembers( ) ) ); 18 | connect ( groupNameEdit, SIGNAL ( textEdited ( const QString & ) ), this, SLOT ( checkGroupname ( const QString & ) ) ); 19 | connect ( GIDEdit, SIGNAL ( textEdited ( const QString & ) ), this, SLOT ( checkGID ( const QString & ) ) ); 20 | connect ( okBtn, SIGNAL ( clicked() ), this, SLOT ( renameGroup() ) ); 21 | connect ( okBtn, SIGNAL ( clicked() ), this, SLOT ( close() ) ); 22 | connect ( newGroupBtn, SIGNAL ( clicked() ), this, SLOT ( addNewGroup() ) ); 23 | } 24 | 25 | //**************************************************************************************************** 26 | /** 27 | *Destructor κλάσης/φόρμας 28 | */ 29 | GroupProperties::~GroupProperties() 30 | {} 31 | /** 32 | * Αποθηκεύει σε μια private μεταβλητή της κλάσης το όνομα της ομάδας που επιλέχθηκε για επεξεργασία. 33 | */ 34 | void GroupProperties::setOldGroupName ( QString oldGroupName ) 35 | { 36 | oldGroupName_ = oldGroupName; 37 | } 38 | /** 39 | * Συνάρτηση η οποία διαβάζει την μεταβλητή του ονόματος της ομάδας που κρατιέται στην κλάση από την συνάρτηση setOldGroupName. 40 | */ 41 | QString GroupProperties::getOldGroupName() 42 | { 43 | return oldGroupName_; 44 | } 45 | /** 46 | * This functions searches the system Groups at /etc/group in order to find the next available free Group ID - GID . 47 | */ 48 | int GroupProperties::groupSearch(gid_t uid_n) 49 | { 50 | struct group *grp = NULL; 51 | Settings settings; 52 | gid_t tmp_gid; 53 | gid_t max = 65535; 54 | const char *file = "/etc/group"; 55 | FILE *fp; 56 | int i = 0; 57 | fp = fopen ( file, "r" ); 58 | tmp_gid = atoi ( settings.getconf ( "MINIMUM_GID" ).c_str() ); 59 | setgrent(); 60 | 61 | while ( ( grp = getgrent() ) ) 62 | { 63 | if(grp->gr_gid <= max) 64 | if ( grp->gr_gid==tmp_gid ) 65 | { 66 | if(tmp_gid != uid_n && uid_n != 0) 67 | i++; 68 | 69 | tmp_gid++; 70 | endgrent(); 71 | } 72 | } 73 | fclose ( fp ); 74 | if(tmp_gid>max) 75 | QMessageBox::information( 0,tr("User Manager " ), tr ("Reached maximum number of groups")); 76 | 77 | return tmp_gid; 78 | } 79 | /** 80 | * Προσθέτει μέλη σε μια ομάδα. Εκτελείται όταν πατηθεί το κουμπί με τον τίτλο “Add” στην φόρμα των ομάδων. 81 | Για κάθε επιλεγμένο χρήστη δημιουργείται μια εντολή η οποία με κλήση της system εκτελόντας την εντολή στο κέλυφος. 82 | */ 83 | void GroupProperties::addMembers( ) 84 | { 85 | Models model; 86 | QModelIndexList indexes = notMembersList->selectionModel()->selectedIndexes(); 87 | 88 | foreach ( QModelIndex index, indexes ) 89 | { 90 | 91 | 92 | QString program = "/usr/sbin/addgroup"; 93 | QStringList arguments; 94 | 95 | arguments << index.data().toString() << getOldGroupName() ; 96 | 97 | QProcess *process = new QProcess(); 98 | process->start(program, arguments); 99 | 100 | process->waitForFinished(); 101 | arguments.clear(); 102 | 103 | } 104 | 105 | notMembersList->setModel ( model.UsersNotInGroupModel ( getOldGroupName().toLatin1().data() ) ); 106 | membersList->setModel ( model.UsersInGroupModel ( getOldGroupName().toLatin1().data() ) ); 107 | 108 | } 109 | 110 | 111 | /** 112 | * @brief GroupProperties::removeMembers 113 | * This function removes user members from a Group. 114 | * The user selects the member and then clicks on 'remove' button in order to remove the member from the group 115 | * for every user member that needs to be removed the 'remove_member' function is called from myLibb class. 116 | * After the user member removal, the setgrnam function is called from the class Group which recreates the file /etc/group with the new stracture where 117 | * the deleted user member is not included. At the end, the third party program 'sed' is called in order to clean any unwanted characters from inside 118 | * the file /etc/group 119 | */ 120 | 121 | void GroupProperties::removeMembers( ) 122 | { 123 | Groups groups; 124 | Models model; 125 | MyLibb set; 126 | 127 | size_t len = strlen(getOldGroupName().toLatin1().data()); 128 | 129 | char *gname = NULL; 130 | 131 | // bware for overflows 132 | if ( len == 0 || len > SIZE_MAX / sizeof(char)) 133 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Possible overflow due to wrong sting length: %1" ).arg(errno)); 134 | else 135 | { 136 | gname = (char*)calloc(len, sizeof(getOldGroupName().toLatin1().data())); 137 | 138 | char *username = NULL; 139 | 140 | char *ptr; 141 | 142 | username = (char*)malloc(sizeof(char)); 143 | 144 | if ( username == NULL ) 145 | { 146 | errno = ENOMEM; 147 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Could not allocate memory : %1" ).arg(errno)); 148 | } 149 | else 150 | { 151 | if ( gname != NULL ) 152 | { 153 | 154 | Spc *sec = new Spc(); 155 | 156 | memcpy(gname, getOldGroupName().toLatin1().data(), len); 157 | 158 | bool allocate = true; 159 | 160 | struct group *grs; 161 | 162 | grs=getgrnam(gname); 163 | 164 | QModelIndexList indexes = membersList->selectionModel()->selectedIndexes(); 165 | 166 | size_t index_len; 167 | 168 | foreach ( QModelIndex index, indexes ) 169 | { 170 | 171 | index_len = (size_t)strlen(index.data().toByteArray().data()); 172 | 173 | if ( len == 0 || len > SIZE_MAX / sizeof(char) ) 174 | { 175 | allocate = false ; 176 | errno = ENOMEM; 177 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Possible overflow due to wrong sting length: %1" ).arg(errno)); 178 | break; 179 | } 180 | else 181 | { 182 | 183 | ptr = (char*)realloc(username,(size_t)index_len*2); 184 | 185 | if ( ptr != NULL ) 186 | { 187 | memcpy(ptr, index.data().toByteArray().data(), index_len+1); 188 | username[index_len] = '\0'; 189 | username = ptr ; 190 | groups.remove_member(grs,username); 191 | set.setgrnam(grs); 192 | } 193 | else if ( ptr == NULL ) 194 | { 195 | if ( username != NULL ) 196 | { 197 | free(username); 198 | username = NULL; 199 | } 200 | allocate = false ; 201 | errno = ENOMEM; 202 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Could not allocate memory : %1" ).arg(errno)); 203 | break; 204 | } 205 | 206 | } 207 | } 208 | 209 | if ( allocate != false ) 210 | { 211 | sec->clenv(); // clear environment 212 | 213 | QProcess process; 214 | QString program = "sed"; 215 | QString ed = "s/,,/,/g;s/,$//g"; 216 | QString groupfile = "/etc/group"; 217 | QStringList arguments; 218 | 219 | arguments << "-i" << ed << groupfile ; 220 | process.start(program, arguments); 221 | process.waitForStarted(); 222 | process.waitForFinished(); 223 | arguments.clear(); 224 | 225 | arguments << "-i" << ed << groupfile ; 226 | process.start(program, arguments); 227 | process.waitForStarted(); 228 | process.waitForFinished(); 229 | arguments.clear(); 230 | 231 | notMembersList->setModel ( model.UsersNotInGroupModel ( getOldGroupName().toLatin1().data() ) ); 232 | membersList->setModel ( model.UsersInGroupModel ( getOldGroupName().toLatin1().data() ) ); 233 | } 234 | 235 | if ( sec != NULL ) { delete sec; sec = NULL; } 236 | if (gname != NULL) { free (gname); gname = NULL;} 237 | if (username != NULL ) { free(username); username = NULL; } 238 | } 239 | else 240 | { 241 | errno = ENOMEM; 242 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Could not allocate memory - %1" ).arg(errno)); 243 | } 244 | } 245 | } 246 | } 247 | 248 | 249 | /** 250 | * Η παραπάνω συνάρτηση χρησιμοποιείται για να αλλάξει το όνομα μιας ομάδας. 251 | Καλεί μέσω της system το εργαλείο groupmod με την παράμετρο -n το οποίο αλλάζει το όνομα της ομάδας. 252 | */ 253 | 254 | bool GroupProperties::renameGroup() 255 | { 256 | //Spc * sec = new Spc(); 257 | QRegExp rx ( "[:.'|<>?/*\\+=&*%]" ); // check out this invalid chars 258 | 259 | size_t len = strlen(groupNameEdit->text().toLatin1().data()); 260 | 261 | if ( len == 0 || len > SIZE_MAX / sizeof(char) ) 262 | { 263 | errno = ENOMEM; 264 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Could not allocate memory - %1" ).arg(errno)); 265 | return false; 266 | } 267 | else 268 | { 269 | 270 | char *groupname = (char*)calloc( 128, len); 271 | 272 | // check if memory allocated succesully to avoid undefined behaviours and potential security issues 273 | if ( groupname == NULL ) 274 | { 275 | errno = ENOMEM; 276 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Could not allocate memory - %1" ).arg(errno)); 277 | return false; 278 | } 279 | else 280 | { 281 | int res = 0 ; 282 | int count = 0; 283 | int pos = 0; 284 | 285 | memcpy(groupname, groupNameEdit->text().toLatin1().data(), strlen(groupNameEdit->text().toLatin1().data())); 286 | 287 | QString gname = QString::fromUtf8(groupname); 288 | 289 | res = rx.indexIn(gname, pos); 290 | 291 | while ( (res != -1)) 292 | { 293 | count++; 294 | pos+= rx.matchedLength(); 295 | } 296 | 297 | if ( pos == -1) 298 | { 299 | //sec->clenv(); we dont need to clear the environment since we get the full path of the groupmod program 300 | 301 | QString program = "/usr/sbin/groupmod"; 302 | QStringList arguments; 303 | 304 | arguments << "-n" << gname << getOldGroupName() ; 305 | 306 | QProcess *process = new QProcess(); 307 | process->start(program, arguments); 308 | process->waitForFinished(); 309 | arguments.clear(); 310 | 311 | } 312 | 313 | free(groupname); 314 | groupname = NULL ; 315 | } 316 | 317 | } 318 | return true; 319 | } 320 | 321 | /** 322 | * Συνάρτηση η οποία σαρώνει το αρχείο των ομάδων και ενημερώνει τον διαχειριστή για πιθανή απόπειρα προσθήκης/μετονομασίας μιας ομάδας, 323 | * με όνομα όμως το οποίο υπάρχει ήδη στο σύστημα. 324 | */ 325 | 326 | void GroupProperties::checkGroupname ( const QString &text ) 327 | { 328 | okBtn->setEnabled ( true ); 329 | existsLabel->clear(); 330 | struct group *grp; 331 | QRegExp rx ( "[:.'|<>?/*\\&;%*]" ); 332 | 333 | setgrent(); 334 | 335 | while ( ( grp = getgrent() ) ) 336 | { 337 | if ( ( grp->gr_name == text )) 338 | { 339 | groupNameEdit->setStyleSheet ( "border: 4px solid red;" ); 340 | existsLabel->setText ( tr ( "*%1 already exists*" ).arg(groupNameEdit->text()) ); 341 | newGroupBtn->setEnabled ( false ); 342 | okBtn->setEnabled ( false ); 343 | break; 344 | } 345 | else{ 346 | 347 | groupNameEdit->setStyleSheet ( " " );//den yparxei to onoma 348 | existsLabel->setText ( "" ); 349 | newGroupBtn->setEnabled ( true ); 350 | okBtn->setEnabled ( true ); 351 | } 352 | } 353 | endgrent(); 354 | if ( ( groupNameEdit->text()=="" )) 355 | { 356 | newGroupBtn->setEnabled ( false ); 357 | okBtn->setEnabled ( false ); 358 | existsLabel->clear(); 359 | groupNameEdit->setStyleSheet ( " " ); 360 | } 361 | else if (text==getOldGroupName()) 362 | { 363 | newGroupBtn->setEnabled ( false ); 364 | okBtn->setEnabled ( false ); 365 | } 366 | else if (text.contains(rx)) 367 | { 368 | newGroupBtn->setEnabled ( false ); 369 | okBtn->setEnabled ( false ); 370 | } 371 | else if (text.contains(" ")) 372 | { 373 | 374 | newGroupBtn->setEnabled ( false ); 375 | okBtn->setEnabled ( false ); 376 | } 377 | 378 | } 379 | /** 380 | * Συνάρτηση η οποία σαρώνει το αρχείο των ομάδων και ενημερώνει τον διαχειριστή στην περίπτωση που προσπαθήσει να προσθέσει στο σύστημα ομάδα με GROUP ID το οποίο είναι κατειλημμένο από άλλη ομάδα του συστήματος. 381 | 382 | */ 383 | void GroupProperties::checkGID ( const QString &text ) 384 | 385 | { 386 | struct group *grp; 387 | gid_t Gid = text.toInt(); 388 | if ( Gid<65535&&Gid>0 ) 389 | { 390 | 391 | okBtn->setEnabled ( true ); 392 | newGroupBtn->setEnabled ( true ); 393 | setgrent(); 394 | while ( ( grp = getgrent() ) ) 395 | { 396 | 397 | if ( ( grp->gr_gid != Gid ) ) //an den yparxei to gid anamesa sta gid twn group 398 | { 399 | 400 | GIDEdit->setStyleSheet ( " " );//den yparxei to onoma 401 | existsLabel->setText ( "" ); 402 | newGroupBtn->setEnabled ( true ); 403 | okBtn->setEnabled ( true ); 404 | } 405 | else //to onoma tou group yparxei hdh 406 | { 407 | GIDEdit->setStyleSheet ( "border: 4px solid red;" ); 408 | existsLabel->setText ( tr ( "GID *%1 already exists*" ).arg ( GIDEdit->text() ) ); 409 | newGroupBtn->setEnabled ( false ); 410 | okBtn->setEnabled ( false ); 411 | break; 412 | 413 | } 414 | 415 | } 416 | endgrent(); 417 | } 418 | if ( GIDEdit->text() =="" ) 419 | { 420 | GIDEdit->setStyleSheet ( "" ); 421 | existsLabel->setText ( tr ( "" ) ); 422 | } 423 | 424 | } 425 | 426 | /** 427 | * Προσθήκης νέας ομάδας στο σύστημα. 428 | Δημιουργείται η δομή προς εισαγωγή και έπειτα προστίθεται η ομάδα μέσω της putgrent(). 429 | */ 430 | 431 | int GroupProperties::addNewGroup() 432 | { 433 | MyLibb *fchk = new MyLibb(); 434 | QByteArray pass = "x"; 435 | 436 | 437 | disconnect ( okBtn, SIGNAL ( clicked() ), this, SLOT ( renameGroup() ) ); //disconnect to signal giati to rename eiani gia edit tou group kai den xreiazetai otan vazoume neo group na ginei kai rename. 438 | if (groupNameEdit->text()==NULL || GIDEdit->text()==NULL) 439 | { 440 | QMessageBox::information ( 0,tr ( "User Manager" ),tr ( "Insert Group Name" )); 441 | if (fchk != NULL) { delete fchk; fchk = NULL; } 442 | return 1; 443 | } 444 | else 445 | { 446 | 447 | gid_t groupID = GIDEdit->text().toInt(); 448 | struct group grp; 449 | grp.gr_name = groupNameEdit->text().toLatin1().data() ; 450 | grp.gr_passwd = pass.data(); 451 | grp.gr_gid = groupID ; 452 | grp.gr_mem = NULL; 453 | FILE *groupbase; 454 | 455 | const char *filename = "/etc/group"; 456 | int result = 0 ; 457 | 458 | 459 | groupbase = fchk->fopen_wrapper ( filename, "a+" ); 460 | 461 | if ( groupbase!=NULL ) 462 | { 463 | 464 | result = putgrent ( &grp, groupbase ); 465 | fclose ( groupbase ); 466 | } 467 | else 468 | { 469 | QMessageBox::critical( 0,tr ( "User Manager" ),tr ( "Could not allocate create Group - %1" ).arg(errno)); 470 | } 471 | 472 | if ( result==0 ) 473 | { 474 | Models model; 475 | 476 | QMessageBox::information ( 0,tr ( "User Manager" ),tr ( "Group %1 added" ).arg ( groupNameEdit->text() ) ); 477 | newGroupBtn->setVisible(false); 478 | notMembersList->setModel ( model.UsersNotInGroupModel ( groupNameEdit->text().toLatin1().data()) ); 479 | membersList->setModel ( model.UsersInGroupModel ( groupNameEdit->text().toLatin1().data() ) ); 480 | 481 | setOldGroupName ( groupNameEdit->text().toLatin1().data() );//prepei na dhlw8ei oti to oldgroupname einai pleon to onoma tou kainourgiou group pou valame gia na mporesei na leitourghsei h addmembers() kai h removemembers() pou exoun san orisma to onoma tou group.an den dhlw8ei edw to oldgroupname 8a einai keno epeidh otan dhmiourgh8hke h forma to name sto groupNameEdit htan keno 482 | newGroupBtn->setEnabled ( false ); 483 | addBtn->setEnabled ( true ); 484 | removeBtn->setEnabled ( true ); 485 | } 486 | if (fchk != NULL) { delete fchk; fchk = NULL; } 487 | return result; 488 | } 489 | } 490 | 491 | -------------------------------------------------------------------------------- /groupProperties.h: -------------------------------------------------------------------------------- 1 | #ifndef GROUPPROPERTIES_H 2 | #define GRPOUPROPERTIES_H 3 | #include "ui_GroupProperties.h" 4 | #include 5 | #include 6 | #include "grp.h" 7 | 8 | /** 9 | * Στην GroupProperties ανήκει η φόρμα στην οποία προβάλλονται τα χαρακτηριστικά των ομάδων. Από αυτήν μπορούμε να προσθέσουμε/αφαιρέσουμε μέλη στις ομάδες, να αλλάξουμε το όνομα τους,να τις επεξεργαστούμε, ή να κανουμε προσθήκη μιας νέας ομάδας στο σύστημα.Πολλές από τις συναρτήσεις της κλάσης αυτής συνδέονται με συναρτήσεις της κλάσης Groups οι οποίες συνεργάζονται προκειμένου να υλοποιηθούν ορισμένες ενέργειε. 10 | */ 11 | class GroupProperties : public QDialog , public Ui::GroupProperties 12 | 13 | 14 | { 15 | Q_OBJECT 16 | public: 17 | GroupProperties ( QWidget *parent = 0 ); 18 | ~GroupProperties(); 19 | int groupSearch(gid_t uid_n); 20 | virtual void setOldGroupName ( QString oldGroupName ); 21 | virtual QString getOldGroupName(); 22 | 23 | private : 24 | 25 | QString oldGroupName_; 26 | 27 | private slots: 28 | void addMembers(); 29 | void removeMembers(); 30 | void checkGroupname ( const QString &text ); 31 | void checkGID ( const QString &text ); 32 | bool renameGroup(); 33 | int addNewGroup(); 34 | 35 | }; 36 | 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /groups.cpp: -------------------------------------------------------------------------------- 1 | #include "groups.h" 2 | #include "myLibb.h" 3 | #include 4 | #include 5 | #include "spc.h" 6 | 7 | /** 8 | Constructor κλάσης 9 | */ 10 | Groups::Groups( ) 11 | { 12 | 13 | } 14 | /** 15 | *Destructor κλάσης 16 | */ 17 | Groups::~Groups( ) 18 | { 19 | 20 | } 21 | 22 | 23 | /** 24 | *Εισάγει κάθε νέο χρήστη σε σε βασικές ομάδες όπως audio (ήχο),video (χρήση βίντεο),cdrom (χρήση cdrom),floppy (χρήση δισκέτας) και plugdev (χρήση αποθηκευτικών μέσων). 25 | */ 26 | int Groups::default_groups(QString newmem) 27 | { 28 | struct group *grs; 29 | setgrent(); 30 | QString allmem = ""; 31 | while((grs = getgrent())) 32 | { 33 | if (strncmp(grs->gr_name,"video", strlen(grs->gr_name))==0 || strncmp(grs->gr_name ,"cdrom", strlen(grs->gr_name))==0 || strncmp(grs->gr_name,"floppy", strlen(grs->gr_name))==0 || strncmp(grs->gr_name ,"audio", strlen(grs->gr_name))==0 || strncmp(grs->gr_name, "plugdev", strlen(grs->gr_name))==0 ) 34 | { 35 | QString member = *grs->gr_mem; 36 | if(*grs->gr_mem == NULL) 37 | *grs->gr_mem = newmem.toLatin1().data(); 38 | else 39 | { 40 | allmem = "" + member + "," + newmem + ""; 41 | *grs->gr_mem = allmem.toLatin1().data(); 42 | } 43 | MyLibb set; 44 | if(set.setgrnam(grs) < 0)return -1; 45 | allmem = ""; 46 | } 47 | } 48 | endgrent(); 49 | return 0; 50 | } 51 | /** 52 | *Αναζήτηση μιας ομάδας στο σύστημα.Ψάχνει στο αρχείο των ομάδων και αν βρεθεί η ομάδα που αναζητούμε 53 | επιστρέφει την δομή της.Αν όχι εμφανίζει ανάλογο μήνυμα. 54 | */ 55 | struct group *Groups::searchGroup() 56 | { 57 | bool okBtn; 58 | char *groupToSearch; 59 | struct group *result = NULL; 60 | QString groupString = QInputDialog::getText( 0, QObject::tr( "Search" ), QObject::tr( "Enter Group Name:(case sensitive)" ), QLineEdit::Normal, QString( "" ), &okBtn ); 61 | 62 | if ( okBtn && groupString != " " ) 63 | { 64 | groupToSearch = groupString.toLatin1().data(); 65 | result = getgrnam( groupToSearch ); 66 | if ( result == NULL ) 67 | { 68 | QMessageBox::information( 0, QObject::tr( "User Manager" ), QObject::tr( "Group %1 not found" ).arg( groupString ) ) ; 69 | } 70 | 71 | } 72 | return result; 73 | } 74 | /** 75 | *Διαγράφει ένα μέλος από μια ομάδα.Παίρνει την δομή της ομάδας με τα μέλη της και αν βρεί τον χρήστη που 76 | θέλουμε να αφαιρέσουμε από την ομάδα (όρισμα uname),αντικαθιστά τη θέση του στα μέλη με ένα κενό.Στην συνέχεια καθαρίζει το αρχείο των ομάδων από πιθανά άχρηστα κόμματα που έμειναν μέσω του κειμενογράφου sed. 77 | Στο τέλος επιστρέφει την δομή χωρίς το μέλος που αφαιρέθηκε. 78 | */ 79 | struct group *Groups::remove_member(struct group *in,char *uname) 80 | { 81 | int i; 82 | 83 | QString memo = ""; 84 | 85 | if (in == NULL) return NULL; 86 | 87 | for (i = 0; in->gr_mem[i]; i++) 88 | { 89 | if (!strncmp(in->gr_mem[i], uname, strlen(in->gr_mem[i]))) 90 | { 91 | in->gr_mem[i] = memo.toLatin1().data(); 92 | } 93 | } 94 | 95 | usleep(1000); 96 | return in; 97 | } 98 | 99 | /** 100 | *Διαγραφή ενός χρήστη από όλες τις ομάδες που πιθανόν να ήταν μέλος.Χρησιμοποιείται αφού διαγραφεί κάποιος χρήστης από το σύστημα. 101 | */ 102 | 103 | int Groups::rm_grMember(QString log) 104 | { 105 | struct group *grs = NULL; 106 | 107 | FILE * f; 108 | MyLibb *set = new MyLibb(); 109 | f = fopen(GR_FILE,"r"); 110 | char *login = log.toLatin1().data(); 111 | setgrent(); 112 | while((grs = fgetgrent(f))) 113 | { 114 | remove_member(grs , login); 115 | if(set->setgrnam(grs)<0) 116 | { 117 | return -1; 118 | } 119 | } 120 | endgrent(); 121 | if (set != nullptr){ delete set; set = nullptr;} 122 | fclose(f); 123 | return 0; 124 | } 125 | /** 126 | *Προετοιμασία διαγραφής μια ομάδας από το σύστημα. 127 | */ 128 | int Groups::deleteGroup(QString gname) 129 | { 130 | MyLibb set; 131 | struct group *gr = NULL; 132 | char * groupname = gname.toLatin1().data(); 133 | if(set.setgrnam_r(gr,groupname)<0) 134 | { 135 | 136 | return -1; 137 | } 138 | 139 | return 0; 140 | } 141 | /** 142 | *Ελέγχει αν υπάρχει χρήστης ο οποίος έχει σαν κύρια ομάδα,την ομάδα με το GROUP ID που παίρνει σαν όρισμα. 143 | */ 144 | bool Groups::isPrimary(int gid) 145 | { 146 | gid_t gidt=gid; 147 | 148 | bool found=false; 149 | struct passwd *users; 150 | setpwent(); 151 | while (( users = getpwent() ) ) 152 | { 153 | if (users->pw_gid==gidt) 154 | { 155 | found=true; 156 | } 157 | } 158 | endpwent(); 159 | return found; 160 | 161 | } 162 | /** 163 | *Δημιουργία ενός string το οποίο περιέχει όλους τους χρήστες οι οποίοι έχουν σαν κύρια ομάδα την ομάδα με το GROUP ID που παίρνει σαν όρισμα. 164 | */ 165 | QString Groups::getPrimaryUsers(int gid) // epistrefei tous xrhstes pou exoun to group san prwteywn 166 | { 167 | gid_t gidt = gid; 168 | QString primOfUsers; 169 | struct passwd *users; 170 | setpwent(); 171 | while (( users = getpwent() ) ) 172 | { 173 | if (users->pw_gid==gidt) 174 | { 175 | primOfUsers.append(users->pw_name); 176 | primOfUsers.append(","); 177 | } 178 | } 179 | endpwent(); 180 | primOfUsers.chop(1); // cut out the last comma 181 | return primOfUsers; 182 | } 183 | -------------------------------------------------------------------------------- /groups.h: -------------------------------------------------------------------------------- 1 | #ifndef GROUPS_H 2 | #define GROUPS_H 3 | #include "pathfile.h" 4 | #include 5 | #include 6 | 7 | /** 8 | Η Κλάση αυτή περιέχει συναρτήσεις οι οποίες ενεργούν πάνω στις ομάδες ενός συστήματος. 9 | Μερικές από τις ενέργειες αυτές είναι η διαγραφή μελών απο ομάδες,η διαγραφή ομάδων από το σύστημα,η προσθήκη ενός νέου χρήστη σε προεπιλεγμένες ομάδες κ.ο.κ. 10 | */ 11 | class Groups: public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | Groups(); 16 | ~Groups(); 17 | 18 | static struct group *remove_member(struct group *in,char *uname); 19 | QString getPrimaryUsers(int gid); 20 | int deleteGroup(QString gname); 21 | bool isPrimary(int gid); 22 | static int rm_grMember(QString log); 23 | struct group *searchGroup(); 24 | int default_groups(QString newmem); 25 | 26 | private: 27 | int setgrnam(struct group *gr); 28 | Spc *spc; 29 | 30 | 31 | }; 32 | #endif 33 | -------------------------------------------------------------------------------- /images/Untitled2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/images/Untitled2.gif -------------------------------------------------------------------------------- /install_and_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################################## 4 | # 5 | # This script installs UserManager application to Debian and Ubuntu distributions 6 | # 7 | ################################################################################## 8 | 9 | MAGENTA='\033[95m' 10 | RED='\033[0;31m' 11 | GREEN='\e[92m' 12 | NC='\033[0m' # No Color 13 | BLUE='\e[96m' 14 | YELLOW='\e[33m' 15 | 16 | echo -ne "\n" 17 | echo -ne "$YELLOW" 18 | echo ' / / / /_______ _____/ |/ /___ _____ ____ _____ ____ ____ ' 19 | echo ' / / / / ___/ _ \/ ___/ /|_/ / __ `/ __ \/ __ `/ __ `/ _ \/ ___/' 20 | echo '/ /_/ (__ ) __/ / / / / / /_/ / / / / /_/ / /_/ / __/ / ' 21 | echo '\____/____/\___/_/ /_/ /_/\__,_/_/ /_/\__,_/\__, /\___/_/ ' 22 | echo ' /____/ ' 23 | echo 24 | echo 'UserManager - Linux Accounts Manager' 25 | echo 'Script Author: @xvass' 26 | echo 'Version 1.0.75' 27 | echo -ne "$NC" 28 | 29 | os=$(uname -a) 30 | nu=$(pwd | tr '/' ' ' | wc -w) 31 | num=$(($nu + 1)) 32 | directory=$(pwd | cut -d/ -f$num) 33 | usr=$(whoami) 34 | found="false" 35 | 36 | qt5=`dpkg-query -W -f='${Status} ${Version}\n' qt5*` 37 | if [[ ! `echo $qt5 | grep "install ok"` ]]; then echo "Qt5 is not installed. Exiting.."; exit 1; fi 38 | 39 | IFS=' ' # space set as delimiter 40 | 41 | read -ra ADDR <<< "$os" 42 | 43 | for i in "${ADDR[@]}"; do # access each element of array 44 | 45 | Ubuntu=`echo $i | grep "^.*Ubuntu" | cut -d- -f2` 46 | if [ "$i" = "Debian" -o "$Ubuntu" = "Ubuntu" -o "$i" = "Ubuntu" -o "$i" = "debian" ];then 47 | found="true" 48 | fi 49 | done 50 | 51 | if [ "$found" = "false" ]; then 52 | echo "this script installs UserManager at Debian and Ubuntu" 53 | exit 1; 54 | fi 55 | 56 | if [ ! -d /"$usr"/.local ]; then 57 | mkdir -p /"$usr"/.local 58 | elif [ ! -d /"$usr"/.local/share ];then 59 | mkdir -p /"$usr"/.local/share 60 | elif [ ! -d /"$usr"/.local/share/applications ]; then 61 | mkdir -p /"$usr"/.local/share/applications 62 | fi 63 | 64 | if [ ! -d /"$usr"/Pictures ]; then 65 | mkdir -p /"$usr"/Pictures 66 | fi 67 | 68 | if [ "$found" = "true" ]; then 69 | if [ ! -f /"$usr"/.local/share/applications/UserManager.desktop ]; then 70 | if [ "$directory" = "UserManager" -o "$directory" = "UserManager-master" ]; then 71 | cp ./resources/images/UserManager.gif /$usr/Pictures/UserManager.gif 72 | fi 73 | touch /"$usr"/.local/share/applications/UserManager.desktop 74 | echo "[Desktop Entry]" >> /"$usr"/.local/share/applications/UserManager.desktop 75 | echo "Type=Application" >> /"$usr"/.local/share/applications/UserManager.desktop 76 | echo "Encoding=UTF-8" >> /"$usr"/.local/share/applications/UserManager.desktop 77 | echo "Name=UserManager" >> /"$usr"/.local/share/applications/UserManager.desktop 78 | echo "Comment=provides administration support for user management" >> /"$usr"/.local/share/applications/UserManager.desktop 79 | echo "Icon=/"$usr"/Pictures/UserManager.gif" >> /"$usr"/.local/share/applications/UserManager.desktop 80 | echo "Exec=/usr/bin/UserManager" >> /"$usr"/.local/share/applications/UserManager.desktop 81 | echo "Terminal=false" >> /"$usr"/.local/share/applications/UserManager.desktop 82 | echo "Categories=Tags;Describing;Application" >> /"$usr"/.local/share/applications/UserManager.desktop 83 | fi 84 | fi 85 | 86 | if [ ! -f /usr/share/apps/UserManager/translations ]; then 87 | mkdir -p /usr/share/apps/UserManager/translations/ 88 | fi 89 | 90 | if [ ! -f /usr/share/apps/UserManager/pics ]; then 91 | mkdir -p /usr/share/apps/UserManager/pics/ 92 | iconpt=`pwd` 93 | yes | cp -rf "$iconpt"/resources/images/* /usr/share/apps/UserManager/pics/ 94 | fi 95 | 96 | if [ ! -f /usr/share/apps/UserManager/language ]; then 97 | if [ "$directory" = "UserManager" ]; then 98 | pat=`pwd` 99 | cp "$pat"/language/el.qm /usr/share/apps/UserManager/translations/ 100 | fi 101 | fi 102 | 103 | mkdir -p /usr/share/apps/UserManager/other/ 104 | if [ ! -f /usr/share/apps/UserManager/other/usermanager.conf ]; then 105 | cp -r ./other/usermanager.conf /usr/share/apps/UserManager/other/ 106 | fi 107 | 108 | echo -ne "\n$GREEN[!] $directory installation..please wait..$NC\n\n" 109 | 110 | if [ "$directory" != "UserManager" -a "$directory" != "UserManager-master" ]; then 111 | echo "$RED[!] this isnt the UserManager Directory$NC" 112 | exit 0 113 | fi 114 | 115 | make clean > make_clean.log 116 | rm -rf Makefile 2>/dev/null 117 | qmake -project 2>/dev/null 118 | qmake -o Makefile UserManager.pro 119 | 120 | echo "QMAKE_CXXFLAGS += -std=c++11 -O2 -fstack-protector-all -Wformat -Werror=format-security" >> UserManager.pro 121 | echo "QMAKE_CPPFLAGS += -Wdate-time -D_FORTIFY_SOURCE=2" >> UserManager.pro 122 | echo "QMAKE_CFLAGS += -O2 -fstack-protector-all -Wformat -Werror=format-security" >> UserManager.pro 123 | echo "LDFLAGS += -Wl,-z,relro" >> UserManager.pro 124 | echo "CONFIG += qt debug" >> UserManager.pro 125 | echo "QMAKE_LIBS += -lcrypt" >> UserManager.pro 126 | echo "QT += widgets" >> UserManager.pro 127 | echo "# installation" >> UserManager.pro 128 | echo "installfiles.files += usermanager" >> UserManager.pro 129 | echo "installfiles.path += /usr/bin/" >> UserManager.pro 130 | echo "INSTALLS += installfiles" >> UserManager.pro 131 | 132 | make > make_.log 2>&1 133 | 134 | terminated=`cat make_.log | grep "compilation\ terminated"` 135 | error=`cat make_.log | grep "Error\ 1"` 136 | error_indicator=`echo "$error" | cut -d: -f1` 137 | 138 | 139 | if [[ "$terminated" == "compilation terminated." || "$error_indicator" == "make" ]]; then 140 | echo -ne "\n$RED[x] Ooops! Installetion failed.. PLease try again!$NC\n" 141 | echo -ne "\n$RED[!] Please check at make_.log file for more information.$NC\n\n" 142 | echo '--------------Error Details------------------' 143 | echo 144 | cat make_.log 145 | echo 146 | echo '-------------End of Details------------------' 147 | echo 148 | exit 1 149 | else 150 | 151 | make install > make_install.log 2>&1 & 152 | pid=$! 153 | 154 | for ((k = 0; k <= 10 ; k++)) 155 | do 156 | if [[ ! `kill -0 $pid 2>/dev/null` ]]; then 157 | echo -ne "$MAGENTA[ " 158 | for ((i = 0 ; i <= k; i++)); do echo -n "###"; done 159 | for ((j = i ; j <= 10 ; j++)); do echo -n " "; done 160 | v=$((k * 10)) 161 | echo -ne " ]$NC " 162 | echo -ne "$YELLOW$v %$NC" $'\r' 163 | sleep 0.5 164 | fi 165 | done 166 | echo 167 | 168 | chown -R root:root UserManager 169 | chmod -R 700 /opt/UserManager 170 | chmod 700 /usr/bin/UserManager 171 | echo -ne "\n\n$YELLOW[!] UserManager Installed succesfully! enjoy :)$NC\n\n" 172 | fi 173 | 174 | -------------------------------------------------------------------------------- /language/el.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/language/el.qm -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "MainWindow.h" 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | /** 10 | *constructor της κλάσης/φόρμας. 11 | Αρχικά γίνεται ένας έλεγχος στον φάκελο /proc για να διαπιστωθεί αν το πρόγραμμα είναι ήδη ανοιχτό ώστε να βγάλει μύνημα ενημέρωσης. 12 | Την πρώτη φορά που ανοίγει δημιουργείται ένα αρχείο txt μέσα στον φάκελο tmp το οποίο περιέχει μόνο τον αριθμό της διεργασίας του User 13 | Manager 14 | Αν ανοίξει και για 2η φορά το πρόγραμμα,θα υπάρχει μέσα στον ./proc ο αριθμός που διεργασίας που αποθηκεύτηκε πριν στο usermanager.lock 15 | στον /tmp.Αρα υποθέτουμε ότι το πρόγραμμα είναι ήδη ανοιχτό. 16 | 17 | Στη συνέχεια εκτελούνται έλεγχοι για να διαπιστωθεί αν οι εγγραφές των /etc/passwd και /etc/shadow είναι σωστές. 18 | Για να είναι σωστές θα πρέπει κάθε όνομα χρήστη του /etc/passwd να υπάρχει και στο /etc/shadow και το αντίστροφο.Αν υπάρχει λάθος ο 19 | διαχειριστής ενημερώνεται για τον χρήστη του οποίου οι εγγραφές έχουν πρόβλημα. 20 | */ 21 | 22 | int main(int argc, char ** argv) 23 | { 24 | 25 | //dhmiourgei to usermanagaer.lock mesa sto opoio yparxei mono o (pid) ari8mos diergasias tou usermanager.sthn 1h if psaxnei an yparxei fakelos mesa sto /proc o opoios na xei ton ari8mo ths diergasias.an yparxei to usermanager einai anoixto 26 | //an den isxyei h 1h tote 8ewreitai oti to programma den einai anoixto kai paei sthn 2h if h opoia vazei mesa sto usermanager.lock to pid ths diergasias tou usermanager pou molis dhmiourgh8hke kalwntas thn getpid(); 27 | 28 | QApplication app( argc, argv); 29 | 30 | struct spwd *sp; 31 | struct passwd *pw; 32 | 33 | 34 | QFile lockFile( QDir::tempPath() + "/usermanager.lock" ); 35 | if ( lockFile.open( QIODevice::ReadOnly ) ) 36 | { 37 | 38 | QTextStream lockStream( &lockFile ); 39 | if ( QDir( "/proc/" + lockStream.readLine() ).exists() ) 40 | { 41 | QMessageBox::information( 0, QObject::tr( "User Manager" ), QObject::tr( "UserManager is already running" )); 42 | 43 | exit(0); 44 | } 45 | 46 | lockFile.close(); 47 | 48 | } 49 | if ( lockFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) ) 50 | { 51 | QTextStream lockStream( &lockFile ); 52 | int pid = getpid(); 53 | lockStream << pid << endl; 54 | lockFile.close(); 55 | } 56 | 57 | setspent(); 58 | while ( ( sp = getspent() ) ) 59 | { 60 | pw=getpwnam ( sp->sp_namp ); 61 | if ( pw==NULL ) 62 | 63 | QMessageBox::critical ( 0,QObject::tr ( "User Manager" ),QObject::tr ( " Entry of user ' %1 ' in /etc/shadow does not exist in /etc/passwd " ).arg ( sp->sp_namp ) ); 64 | 65 | } 66 | // if the user is not root the application will not start 67 | char *user = (char *)calloc(128, sizeof(char)); 68 | pw = getpwuid(getuid()); 69 | user = pw->pw_name; 70 | if (strncmp(user , "root", strlen(user)) != 0) 71 | { 72 | QMessageBox::information( 0, QObject::tr( "User Manager" ), QObject::tr( "UserManager cannot run by non root users" )); 73 | if (user != nullptr) { free(user); user = nullptr; } 74 | exit (0); 75 | } 76 | 77 | MainWindow win; 78 | win.show(); 79 | 80 | if ( user != NULL ) { free(user); user = NULL; } 81 | 82 | app.connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) ); 83 | return app.exec(); 84 | } 85 | -------------------------------------------------------------------------------- /models.cpp: -------------------------------------------------------------------------------- 1 | #include "models.h" 2 | 3 | /** 4 | * Constructor κλάσης 5 | */ 6 | 7 | Models::Models() 8 | {} 9 | 10 | /** 11 | * Destructor κλάσης 12 | */ 13 | Models::~Models() 14 | {} 15 | /** 16 | * Δημιουργεί το μοντέλο λίστας των χρηστών το οποίο εμφανίζεται στην κύρια φόρμα της εφαρμογής. 17 | */ 18 | QStandardItemModel *Models::createUsersModel( ) 19 | { 20 | setpwent(); 21 | 22 | struct passwd *users = NULL; 23 | struct finfo info; 24 | QStandardItemModel *model = new QStandardItemModel( 0, 6 ); 25 | model->setHeaderData( 0, Qt::Horizontal, QObject::tr( "UID" ) ); 26 | model->setHeaderData( 1, Qt::Horizontal, QObject::tr( "Login Name" ) ); 27 | model->setHeaderData( 2, Qt::Horizontal, QObject::tr( "Real Name" ) ); 28 | model->setHeaderData( 3, Qt::Horizontal, QObject::tr( "Home Directory" ) ); 29 | model->setHeaderData( 4, Qt::Horizontal, QObject::tr( "Default Shell" ) ); 30 | model->setHeaderData( 5, Qt::Horizontal, QObject::tr( "Disk Usage" ) ); 31 | Users *us = new Users(); 32 | while (( users = getpwent() ) ) 33 | { 34 | us->passwd_parse(getpwnam(users->pw_name),&info); 35 | model->insertRow( 0 ); 36 | QModelIndex UID = model->index( 0, 0 ); 37 | QModelIndex loginName = model->index( 0, 1 ); 38 | QModelIndex realName = model->index( 0, 2 ); 39 | QModelIndex homeDir = model->index( 0, 3 ); 40 | QModelIndex defaultShell = model->index( 0, 4 ); 41 | QModelIndex diskUsage = model->index( 0, 5 ); 42 | QString userName = QString::fromLatin1( users->pw_name ); 43 | 44 | if (us->isLocked(userName)) 45 | model->setData(UID,QVariant(QImage("/usr/share/apps/UserManager/pics/lock.png")),Qt::DecorationRole); 46 | else 47 | model->setData(UID,QVariant(QImage("/usr/share/apps/UserManager/pics/enabled.jpeg")),Qt::DecorationRole); 48 | 49 | model->setData( UID, users->pw_uid ) ; 50 | model->setData( loginName, users->pw_name ); 51 | model->setData( realName, info.full_name); 52 | model->setData( homeDir, users->pw_dir ); 53 | model->setData( defaultShell, users->pw_shell ); 54 | model->setData( diskUsage, QVariant( QString( " " ) ) ); 55 | } 56 | endpwent(); 57 | if (us != nullptr){ delete us; us = nullptr;} 58 | return model; 59 | } 60 | /** 61 | * Δημιουργεί το μοντέλο λίστας των χρηστών στο οποίο εμφανίζεται και η κατανάλωση δίσκου του κάθε χρήστη. 62 | */ 63 | QStandardItemModel *Models::createUsersModelWithSizes( QStringList sizeList ) 64 | { 65 | 66 | 67 | setpwent(); 68 | struct finfo info; 69 | struct passwd *users = NULL; 70 | QStandardItemModel *model = new QStandardItemModel( 0, 6 ); 71 | model->setHeaderData( 0, Qt::Horizontal, QObject::tr( "UID" ) ); 72 | model->setHeaderData( 1, Qt::Horizontal, QObject::tr( "Login Name" ) ); 73 | model->setHeaderData( 2, Qt::Horizontal, QObject::tr( "Real Name" ) ); 74 | model->setHeaderData( 3, Qt::Horizontal, QObject::tr( "Home Directory" ) ); 75 | model->setHeaderData( 4, Qt::Horizontal, QObject::tr( "Default Shell" ) ); 76 | model->setHeaderData( 5, Qt::Horizontal, QObject::tr( "Disk Usage" ) ); 77 | int i=0; 78 | Users *us { new Users()} ; 79 | 80 | while (( users = getpwent() ) ) 81 | { 82 | us->passwd_parse(getpwnam(users->pw_name),&info); 83 | model->insertRow( 0 ); 84 | QModelIndex UID = model->index( 0, 0 ); 85 | QModelIndex loginName = model->index( 0, 1 ); 86 | QModelIndex realName = model->index( 0, 2 ); 87 | QModelIndex homeDir = model->index( 0, 3 ); 88 | QModelIndex defaultShell = model->index( 0, 4 ); 89 | QModelIndex diskUsage = model->index( 0, 5 ); 90 | QString userName = QString::fromLatin1( users->pw_name ); 91 | 92 | if (us->isLocked(userName)) 93 | model->setData(UID,QVariant(QImage("/usr/share/apps/UserManager/pics/lock.png")),Qt::DecorationRole); 94 | else 95 | model->setData(UID,QVariant(QImage("/usr/share/apps/UserManager/pics/enabled.jpeg")),Qt::DecorationRole); 96 | 97 | model->setData( UID, users->pw_uid ) ; 98 | model->setData( loginName, users->pw_name ); 99 | model->setData( realName, info.full_name); 100 | model->setData( homeDir, users->pw_dir ); 101 | model->setData( defaultShell, users->pw_shell ); 102 | model->setData( diskUsage,sizeList[i]); 103 | i++; 104 | } 105 | endpwent(); 106 | delete us; 107 | us=nullptr; 108 | return model; 109 | } 110 | 111 | /** 112 | * Δημιουργεί το μοντέλο λίστας των ομάδων του σύστηματος. 113 | */ 114 | QStandardItemModel *Models::createGroupsModel( ) 115 | { 116 | struct group *groups = NULL; 117 | setgrent(); 118 | QStandardItemModel *model = new QStandardItemModel( 0, 2 ); 119 | model->setHeaderData( 0, Qt::Horizontal, QObject::tr( "GID" ) ); 120 | model->setHeaderData( 1, Qt::Horizontal, QObject::tr( "Group Name" ) ); 121 | while (( groups = getgrent() ) ) 122 | { 123 | model->insertRow( 0 ); 124 | QModelIndex GID = model->index( 0, 0 ); 125 | QModelIndex groupName = model->index( 0, 1 ); 126 | 127 | model->setData( GID, groups->gr_gid ) ; 128 | model->setData( groupName, groups->gr_name ); 129 | } 130 | endgrent(); 131 | return model; 132 | } 133 | 134 | 135 | /** 136 | * Δημιουργεί το μοντέλο του χρήστη που αναζητήθηκε στο σύστημα. 137 | */ 138 | QStandardItemModel *Models::createFoundedGroupModel( struct group *grp ) 139 | { 140 | setgrent(); 141 | QStandardItemModel *model = new QStandardItemModel( 0, 2 ); 142 | model->setHeaderData( 0, Qt::Horizontal, QObject::tr( "GID" ) ); 143 | model->setHeaderData( 1, Qt::Horizontal, QObject::tr( "Group Name" ) ); 144 | 145 | model->insertRow( 0 ); 146 | QModelIndex GID = model->index( 0, 0 ); 147 | QModelIndex groupName = model->index( 0, 1 ); 148 | 149 | model->setData( GID, grp->gr_gid ) ; 150 | model->setData( groupName, grp->gr_name ); 151 | 152 | endgrent(); 153 | return model; 154 | } 155 | 156 | /** 157 | * Δημιουργεί το μοντέλο της ομάδας που αναζητήθηκε στο σύστημα. 158 | */ 159 | QStandardItemModel *Models::createFoundedUserModel( struct passwd *usr ) 160 | { 161 | Users *user = new Users(); 162 | QString sizeString; 163 | QStandardItemModel *model = new QStandardItemModel( 0, 6 ); 164 | model->setHeaderData( 0, Qt::Horizontal, QObject::tr( "UID" ) ); 165 | model->setHeaderData( 1, Qt::Horizontal, QObject::tr( "Login Name" ) ); 166 | model->setHeaderData( 2, Qt::Horizontal, QObject::tr( "Real Name" ) ); 167 | model->setHeaderData( 3, Qt::Horizontal, QObject::tr( "Home Directory" ) ); 168 | model->setHeaderData( 4, Qt::Horizontal, QObject::tr( "Default Shell" ) ); 169 | model->setHeaderData( 5, Qt::Horizontal, QObject::tr( "Disk Usage" ) ); 170 | { 171 | model->insertRow( 0 ); 172 | QModelIndex UID = model->index( 0, 0 ); 173 | QModelIndex loginName = model->index( 0, 1 ); 174 | QModelIndex realName = model->index( 0, 2 ); 175 | QModelIndex homeDir = model->index( 0, 3 ); 176 | QModelIndex defaultShell = model->index( 0, 4 ); 177 | QModelIndex diskUsage = model->index( 0, 5 ); 178 | model->setData( UID, usr->pw_uid ) ; 179 | model->setData( loginName, usr->pw_name ); 180 | model->setData( realName, usr->pw_gecos ); 181 | model->setData( homeDir, usr->pw_dir ); 182 | model->setData( defaultShell, usr->pw_shell ); 183 | char *dir = usr->pw_dir; 184 | string dirString = dir; 185 | char path[PATH_MAX] = "\0"; //PATH_MAX == 4096 xarakthres megisth diadromh.arxikopoihsh me \0 giati alliws exei skpoupidia kai mperdeyetai h getSize 186 | for ( size_t i = 0; i < dirString.length(); i++ )//string se char[].to i size_t gia na sygkrinei to size_t pou epistrefei to length(). 187 | { 188 | path[i] = dirString[i]; 189 | } 190 | if ( path[strlen( path )-1] != '/' ) 191 | strncat( path, "/" , strlen(path) ); 192 | //totalSize = 0;//mhdenismos giati merikoi home fakeloi den yparxoun,kai an den mhdenistei krataei to mege8os tou teleytaiou fakelou poy yphrxe kai metrh8hke 193 | uint64_t size = user->getSize( path ); 194 | if ( size < 1000 && size > 0 ) //if < 1kb 195 | { 196 | sizeString.setNum( size ) ;//bytes 197 | sizeString.append( " B" ); 198 | } 199 | else 200 | if ( size < 1000000 && size > 1000 ) //if < 1mb 201 | { 202 | uint64_t finalSize = ( size / 1024 );//bytes->kb 203 | sizeString.setNum( finalSize ) ; 204 | sizeString.append( " KB" ); 205 | } 206 | else 207 | if ( size > 1000000 ) //if > 1mb 208 | { 209 | uint64_t finalSize = ( size / 1024 / 1024 );//bytes->mb 210 | sizeString.setNum( finalSize ) ; 211 | sizeString.append( " MB" ); 212 | } 213 | else 214 | sizeString = "-"; //an totalsize=0 h den yparxei o fakelos 215 | model->setData( diskUsage, sizeString ); 216 | } 217 | if (user != nullptr) { delete user; user = nullptr; } 218 | return model; 219 | } 220 | 221 | /** 222 | * Δημιουργεί το μοντέλο των χρηστών που είναι μέλη σε μια ομάδα. 223 | */ 224 | QStandardItemModel *Models::createMembersModel ( const char *groupName ) 225 | 226 | { 227 | char **members; 228 | setpwent(); 229 | struct passwd * user=NULL; 230 | struct finfo info; 231 | struct group *grp = getgrnam ( groupName ); 232 | members = grp->gr_mem; 233 | Users *us = new Users(); 234 | 235 | QStandardItemModel *model = new QStandardItemModel ( 0, 3 ); 236 | model->setHeaderData ( 0, Qt::Horizontal, QObject::tr ( "UID" ) ); 237 | model->setHeaderData ( 1, Qt::Horizontal, QObject::tr ( "Login Name" ) ); 238 | model->setHeaderData ( 2, Qt::Horizontal, QObject::tr ( "Real Name" ) ); 239 | 240 | 241 | 242 | while ( *members ) 243 | { 244 | 245 | user = getpwnam ( *members ); 246 | if ( user==NULL ) //an exei meinei akyrh eggrafh enos xrhsth san member sto etc/group enw o xrhsths den yparxei sto etc/passwd 247 | members++; 248 | else 249 | { 250 | model->insertRow ( 0 ); 251 | QModelIndex UID = model->index ( 0, 0 ); 252 | QModelIndex loginName = model->index ( 0, 1 ); 253 | QModelIndex realName = model->index ( 0, 2 ); 254 | model->setData ( UID, user->pw_uid ) ; 255 | model->setData ( loginName, * ( members ) ); 256 | us->passwd_parse ( getpwnam ( *members ),&info ); 257 | model->setData ( realName, info.full_name ) ; 258 | members++; 259 | } 260 | 261 | } 262 | user=NULL; 263 | setpwent(); 264 | while ( ( user=getpwent() ) ) 265 | { 266 | if ( user->pw_gid==grp->gr_gid ) 267 | { 268 | model->insertRow ( 0 ); 269 | QModelIndex UID = model->index ( 0, 0 ); 270 | QModelIndex loginName = model->index ( 0, 1 ); 271 | QModelIndex realName = model->index ( 0, 2 ); 272 | model->setData ( UID, user->pw_uid ) ; 273 | model->setData ( UID,QVariant ( QImage ( "/usr/share/apps/UserManager/pics/p.jpeg" ) ),Qt::DecorationRole ); 274 | model->setData ( loginName, user->pw_name ); 275 | us->passwd_parse ( getpwnam ( user->pw_name ),&info ); 276 | model->setData ( realName, info.full_name ) ; 277 | 278 | } 279 | } 280 | endpwent(); 281 | if(us != nullptr){ delete us; us = nullptr; } 282 | return model; 283 | } 284 | 285 | /** 286 | * Δημιουργεί το μοντέλο των ομάδων στις οποίες είναι μέλος ο χρήστης 287 | */ 288 | QStandardItemModel *Models::UsersInGroupModel ( const char *groupName ) 289 | { 290 | 291 | //idia me thn createMembersModel alla xwris na emfanizei ton omonymo xrhsth pou epeidh einai kai o idiokthths tou group den mporoume na ton kanoume remove ap to group tou 292 | char **members=NULL; 293 | struct passwd * user=NULL; 294 | QStandardItemModel *model = new QStandardItemModel ( 0,1 ); 295 | model->setHeaderData ( 0, Qt::Horizontal, QObject::tr ( "*Users IN Group*" ) ); 296 | //vhma vhma 297 | //1)pairnw thn domh tou group gia to opoio 8elw na vrw ta member.2)an yparxoun melh tote paw kai sygkrinw to onoma tou member me ayto tou group gia to opoio psaxnw kai an einai idio shmainei oti to member einai kai o idiokthths tous group ara den to vazw sthn lista giati oute na ton vgalw apo to group tou ginetai oute na ton valw (afou einai hdh mesa).3)an den einai o idiokthths paw kai vazw ena ena ta member mesa sto montelo 298 | struct group *grp = getgrnam ( groupName ); 299 | members = grp->gr_mem; 300 | 301 | if ( *members!=NULL ) 302 | { 303 | 304 | 305 | while ( *members ) 306 | { 307 | user = getpwnam ( *members ); 308 | if ( user!=NULL )//an yparxei akyrh eggrafh sto passwd 309 | { 310 | if ( user->pw_gid==grp->gr_gid ) //elegxos gia na mpei mpei o idiokthths tou group sth lista 311 | members++; 312 | else 313 | { 314 | model->insertRow ( 0 ); 315 | QModelIndex userName = model->index ( 0, 0 ); 316 | 317 | model->setData ( userName, * ( members ) ); 318 | members++; 319 | } 320 | 321 | } 322 | else 323 | members++; 324 | } 325 | } 326 | return model; 327 | } 328 | /** 329 | * Δημιουργεί το μοντέλο των ομάδων στις οποίες ΔΕΝ είναι μέλος ο χρήστης 330 | */ 331 | QStandardItemModel *Models::UsersNotInGroupModel ( const char *groupName ) 332 | { 333 | char **members=NULL; 334 | struct passwd * user=NULL; 335 | QStandardItemModel *model = new QStandardItemModel ( 0,1 ); 336 | struct group *grp = NULL; 337 | model->setHeaderData ( 0, Qt::Horizontal, QObject::tr ( "*Users NOT In Group*" ) ); 338 | //vhma vhma 339 | //perna ena ena ta member kai meta gia ka8e ena xrhsth tou systhmatos koitaei an einai den einai member me thn [strcmp ( *members, user->pw_name ) != 0] 340 | //an den einai ton vazei sto montelo 341 | //an paei meta to else shmainei oti ta *members==NULL kai ara to group den exei kanena melos mesa.ara me thn getpwent paw kai pairnw enan enan olous tous user apo to systhma kai tous xwnw sto montelo.pali ginetai o elegxos gia na mhn mpei o idiokthths tou group 342 | 343 | grp = getgrnam ( groupName ); 344 | members = grp->gr_mem; 345 | if ( *members!=NULL ) 346 | { 347 | setpwent(); 348 | 349 | while ( ( user = getpwent() ) ) 350 | { 351 | bool found=true; 352 | if ( user->pw_gid==grp->gr_gid ) //elegxos an einai to primary kapoiu xrhsth.an einai den xreiazetai na mpei sth lista me tous nonmembers apla anti na fainetai sto groups fainetai sto 3 pedio ap to passwd.(to pw_gid) pou krataei to primary group tou ka8e user 353 | goto usersPrimary; 354 | members = grp->gr_mem;//xanagemizei ta members gia sygkrish me ton epomeno user 355 | while ( *members ) 356 | { 357 | if ( strcmp ( *members, user->pw_name ) != 0 ) 358 | found=false; 359 | else 360 | { 361 | found=true;//an vre8hke den einai melos ara break gia na meinei true kai na mhn allaxei se false ap thn epomenh sygkrish 362 | break; 363 | } 364 | members++; 365 | } 366 | usersPrimary: 367 | if ( found==false ) //osoi user den vre8hkan mpainoun sto montelo 368 | { 369 | model->insertRow ( 0 ); 370 | QModelIndex userName = model->index ( 0, 0 ); 371 | model->setData ( userName, user->pw_name ); 372 | } 373 | 374 | 375 | } 376 | endpwent(); 377 | 378 | } 379 | else 380 | { 381 | 382 | setpwent(); 383 | while ( ( user = getpwent() ) ) 384 | { 385 | if ( user->pw_uid!=grp->gr_gid ) //elegxos an einai to primary kapoiu xrhsth.an einai den xreiazetai na mpei sth lista me tous nonmembers giati einai member kai apla anti na fainetai sto groups fainetai sto 3 pedio ap to passwd.(to pw_gid) pou krataei to primary group tou ka8e user 386 | { 387 | model->insertRow ( 0 ); 388 | QModelIndex userName = model->index ( 0, 0 ); 389 | model->setData ( userName, user->pw_name ); 390 | 391 | } 392 | else 393 | {} 394 | } 395 | endpwent(); 396 | 397 | 398 | } 399 | return model; 400 | } 401 | /** 402 | * Δημιουργεί ένα μοντέλο με όλες τις ομάδες του συστήματος και δίπλα στην κάθε μια τοποθετεί ένα checkbox,ανάλογα με τον αν ο χρήστης του ορίσματος είναι μέλος στην εκάστοτε ομάδα ή όχι. 403 | */ 404 | QStandardItemModel *Models::createUserInGroupsModel ( QString username ) 405 | { 406 | struct group *grp=NULL; 407 | struct passwd *user=NULL; 408 | QStandardItemModel *model = new QStandardItemModel ( 0, 2 ); 409 | user=getpwnam ( username.toLatin1().data() ); 410 | char **members=NULL; 411 | model->setHeaderData ( 1, Qt::Horizontal, QObject::tr ( "Groups" ) ); 412 | model->setHeaderData ( 0, Qt::Horizontal, QObject::tr ( "" ) ); 413 | setgrent(); 414 | while ( ( grp = getgrent() ) ) 415 | { 416 | bool found=false; 417 | QModelIndex checkbox = model->index ( 0, 0 ); 418 | QModelIndex groupname = model->index ( 0, 1 ); 419 | //QModelIndex pic = model->index ( 0, 2 ); 420 | if ( ( grp->gr_gid==user->pw_gid ) ) 421 | goto resume;//an vrei to primary group tou na mhn to emfanisei sto montelo giati to emfanizei hdh sto label primary group apo katw 422 | 423 | members = grp->gr_mem; 424 | if ( *members==NULL ) 425 | { 426 | model->setData ( checkbox, Qt::Unchecked, Qt::CheckStateRole ); 427 | model->setData ( groupname, grp->gr_name ); 428 | found=true; 429 | } 430 | while ( *members ) 431 | { 432 | QString mem ( *members ); 433 | if ( mem==username ) 434 | { 435 | 436 | model->setData ( checkbox, Qt::Checked, Qt::CheckStateRole ); 437 | model->setData ( groupname, grp->gr_name ); 438 | found=true; 439 | break; 440 | } 441 | members++; 442 | } 443 | if ( !found ) 444 | { 445 | 446 | model->setData ( checkbox, Qt::Unchecked, Qt::CheckStateRole ); 447 | model->setData ( groupname, grp->gr_name ); 448 | 449 | } 450 | 451 | model->insertRow ( 0 ); 452 | resume: 453 | {} 454 | } 455 | endgrent(); 456 | return model; 457 | } 458 | 459 | -------------------------------------------------------------------------------- /models.h: -------------------------------------------------------------------------------- 1 | #ifndef MODELS_H 2 | #define MODELS_H 3 | #include "editProperties.h" 4 | #include "groups.h" 5 | 6 | using std::string; 7 | /** 8 | * Στην κλάση αυτή δημιουργούνται οι λίστες των δεδομένων που ζητούνται κάθε φορά ανάλογα με την ενέργεια που έχει επιλέξει να εκτελέσει ο χρήστης. 9 | * Η φιλοσοφία είναι ίδια σε όλες τις συναρτήσεις της κλάσης. 10 | * Αρχικά παίρνουμε τα δεδομένα τα οποία θέλουμε να εμφανιστούν σε ένα component,πχ σε μια λίστα. 11 | * Αυτά τα φορτώνουμε σε ένα αντικείμενο της κλάσης QstandardItemModel, η οποία προσφέρεται από τις βιβλιοθήκες της Qt. 12 | * Σε αυτό το αντικείμενο/μοντέλο αποθηκεύουμε όλα τα δεδομένα που θέλουμε να εμφανίσουμε. 13 | * Μπορούμε να καθορίσουμε τον αριθμό των στηλών,των γραμμών,το χρώμα στο κείμενο,να βάλουμε επικεφαλίδες στις στήλες και γενικά να προσδιορίσουμε 14 | * ποια θα είναι η οπτική αναπαράσταση των δεδομένων. 15 | */ 16 | 17 | 18 | class Models : public QStandardItemModel 19 | { 20 | public: 21 | Models(); 22 | ~Models(); 23 | QStandardItemModel *createUsersModel(); 24 | QStandardItemModel *createUsersModelWithSizes( QStringList sizeList ); 25 | QStandardItemModel *createGroupsModel( ); 26 | QStandardItemModel *createFoundedUserModel( struct passwd *userFound ); 27 | QStandardItemModel *createMembersModel( const char *groupName ); 28 | QStandardItemModel *createFoundedGroupModel( struct group *grp ); 29 | QStandardItemModel *UsersInGroupModel( const char *groupName ); 30 | QStandardItemModel *UsersNotInGroupModel( const char *groupName ); 31 | QStandardItemModel *createUserInGroupsModel(QString username ); 32 | }; 33 | #endif 34 | -------------------------------------------------------------------------------- /move.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd .. && mv UserManager/ /opt 4 | cd /opt/UserManager 5 | chown -R root:root UserManager 6 | chmod -R 700 /opt/UserManager 7 | -------------------------------------------------------------------------------- /myLibb.cpp: -------------------------------------------------------------------------------- 1 | #include "myLibb.h" 2 | #include 3 | #include "pathfile.h" 4 | #include 5 | #include 6 | #include 7 | #include "userproperties.h" 8 | #define _POSIX_SOURCE 1 9 | 10 | 11 | /** 12 | * Constructor κλάσης 13 | */ 14 | MyLibb::MyLibb() 15 | {} 16 | /** 17 | * Destructor κλάσης 18 | */ 19 | MyLibb::~MyLibb() 20 | {} 21 | /** 22 | * Συνάρτηση ελέγχου πρόσβασης σε αρχεία.Δίνουμε σαν ορίσματα το path του αρχείου και τον τρόπο με τον οποίο θέλουμε να το ανοίξουμε (read write κτλ) και σε περίπτωση που είναι εφικτή η πρόσβαση στο συγκεκριμένο αρχείο μας επιστρέφει έναν δείκτη στο αρχείο.Σε διαφορετική περίπτωση μας εμφανίζει ανάλογο μήνυμα. 23 | */ 24 | FILE *MyLibb::fopen_wrapper(const char *filename,const char *mode)//elegxos prosvasis sto arxeio. An oxi epistrefei sfalma 25 | { 26 | FILE *f; 27 | f = fopen(filename,mode); 28 | if (f == NULL) 29 | { 30 | QMessageBox::critical(0,tr("User Manager"),tr(" could not Open DataBase file %1 ").arg(filename)); 31 | 32 | } 33 | return f; 34 | } 35 | /** 36 | * 37 | *Η συνάρτηση διαγράφει εγγραφές μέσα στο αρχείο passwd.Είναι ίδια με την setpwnam με τη μόνη διαφορά ότι 38 | *χρησιμοποιεί το όρισμα name το οποίο ειναι string χαρακτήρων και περιέχει το όνομα του λογαριασμου του χρήστη. 39 | *Η κενή δομή περνάει μια κενή εγγραφή στο αρχείο . 40 | */ 41 | int MyLibb::setpwnam_r (struct passwd *pwd,char *name) 42 | { 43 | FILE *fp = NULL, *pwf = NULL; 44 | int x, ret; 45 | int fd; 46 | bool found; 47 | int namelen; 48 | 49 | int buflen = 512; 50 | char *linebuf = (char*)calloc(buflen,sizeof(char)); 51 | if (linebuf == NULL) 52 | return -1; 53 | 54 | //σε περίπτωση που το προσωρινό αρχείο υπάρχει και δεν έχει διαγραφεί για λόγους όπως να έχει διακοπεί η διεργασία πριν διαγραφεί το αρχείο ,τοτε η παρακάτω επανάληψη χρησιμοποιειται για να διαγράψει προσωρινα αρχεία και να δημιουργήσει καινούρια 55 | for (x = 0; x < 3; x++) { 56 | if (x > 0) 57 | { 58 | unlink(PTMP_FILE); 59 | sleep(1); 60 | } 61 | fd = open(PTMPTMP_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644);//-rw-r--r-- owner ->rw group->r other->r 62 | if (!fd) 63 | { 64 | return -1; 65 | } 66 | ret = link(PTMPTMP_FILE, PTMP_FILE); 67 | unlink(PTMPTMP_FILE); 68 | if (ret == -1) 69 | close (fd); 70 | else 71 | break; 72 | } 73 | 74 | if (ret == -1) return -1; 75 | 76 | fp = fopen_wrapper(PTMP_FILE, "w+"); 77 | pwf = fopen_wrapper(PASSWD_FILE, "r"); 78 | namelen = strlen(name); 79 | 80 | found = false; 81 | //διαβάζεται γραμμή προς γραμμή το προσωρινο αρχείο PASSWD_FILE που βρίσκεται στον κατάλογο /tmp/. 82 | while (fgets(linebuf, buflen, pwf) != NULL) { 83 | 84 | int res = strncmp(linebuf,name, namelen); 85 | if ((found == false) && (res == 0) ) 86 | { 87 | putpwent(pwd, fp); 88 | found = true; 89 | continue; 90 | } 91 | //προσθέτει εγγραφές χαρακτήρων στο αρχείο έως ότου φθάσει στον χαρακτήρα null \0 92 | fputs(linebuf, fp); 93 | } 94 | 95 | fclose(fp); 96 | close(fd); 97 | fclose(pwf); 98 | 99 | if (!found) { 100 | errno = EIDRM; 101 | QMessageBox::critical( 0,tr( "User Manager" ),tr( " %1 ").arg(strerror(errno))); 102 | free(linebuf); 103 | return -1; 104 | } 105 | 106 | unlink(PASSWD_FILE".bak"); 107 | 108 | link(PASSWD_FILE, PASSWD_FILE".bak"); 109 | 110 | rename(PTMP_FILE, PASSWD_FILE) ; 111 | 112 | unlink(PTMP_FILE); 113 | 114 | if (linebuf != NULL) free(linebuf); 115 | 116 | return 0; 117 | } 118 | 119 | /** 120 | *Η συνάρτηση διαγράφει εγγραφές μέσα στο αρχείο group.Είναι ίδια με την setpwnam με τη μόνη διαφορά ότι 121 | *χρησιμοποιεί το όρισμα name το οποίο ειναι string χαρακτήρων με το όνομα του λογαριασμου του χρήστη. 122 | *Η κενή δομή περνάει μια κενή εγγραφή στο αρχείο . 123 | */ 124 | int MyLibb::setgrnam_r(struct group *grs,char *grp) 125 | { 126 | FILE *fp = NULL, *pwf = NULL; 127 | int x, ret; 128 | int fd; 129 | bool found; 130 | int namelen; 131 | int buflen = 1024; 132 | char *linebuf = (char*)calloc(buflen, sizeof(char)); 133 | if (!linebuf) return -1; 134 | 135 | //σε περίπτωση που το προσωρινό αρχείο υπάρχει και δεν έχει διαγραφεί για λόγους όπως να έχει διακοπεί η διεργασία πριν διαγραφεί το αρχείο ,τοτε η παρακάτω επανάληψη χρησιμοποιειται για να διαγράψει προσωρινα αρχεία και να δημιουργήσει καινούρια 136 | for (x = 0; x < 3; x++) { 137 | if (x > 0) 138 | { 139 | unlink(GTMP_FILE); 140 | sleep(1); 141 | } 142 | fd = open(GTMPTMP_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644);//-rw-r--r-- owner ->rw group->r other->r 143 | if (!fd) 144 | { 145 | return -1; 146 | } 147 | ret = link(GTMPTMP_FILE, GTMP_FILE); 148 | unlink(GTMPTMP_FILE); 149 | if (ret == -1) 150 | close (fd); 151 | else 152 | break; 153 | } 154 | if (ret == -1) return -1; 155 | 156 | if(chown(GTMP_FILE,(uid_t) 0,(gid_t) 0 ) > 0 ) 157 | { 158 | errno = EPERM; 159 | QMessageBox::information(0,tr("User Manager"),tr( "%1" ).arg(strerror(errno))); 160 | return -1; 161 | } 162 | fp = fopen_wrapper(GTMP_FILE, "w+"); 163 | pwf = fopen_wrapper(GR_FILE, "r"); 164 | 165 | namelen = strlen(grp); 166 | found = false; 167 | 168 | //διαβάζεται γραμμή προς γραμμή το προσωρινο αρχείο GR_FILE που βρίσκεται στον κατάλογο /tmp/. 169 | while (fgets(linebuf, buflen, pwf) != NULL) 170 | { 171 | 172 | int res = strncmp(linebuf, grp, namelen); 173 | if ((found == false)&& (res == 0) ) 174 | { 175 | putgrent(grs, fp); 176 | found = true; 177 | continue; 178 | } 179 | //προσθέτει εγγραφές χαρακτήρων στο αρχείο έως ότου φθάσει στον χαρακτήρα null \0 180 | fputs(linebuf, fp); 181 | } 182 | fclose(fp); 183 | close(fd); 184 | fclose (pwf); 185 | if (!found) 186 | { 187 | errno = EIDRM; 188 | QMessageBox::critical( 0,tr( "User Manager" ),QString( "%1").arg(strerror(errno))); 189 | return -1; 190 | } 191 | 192 | unlink(GR_FILE".bak"); 193 | link(GR_FILE, GR_FILE".bak"); 194 | 195 | rename(GTMP_FILE, GR_FILE) ; 196 | 197 | if (linebuf != NULL) free(linebuf); 198 | unlink(GTMP_FILE); 199 | 200 | return 0; 201 | } 202 | /** 203 | * Η συνάρτηση διαβάζει το αρχείο γραμμή πρός γραμμη εώς ότου να βρεθεί η εγγραφή η οποία είναι δείκτης σε δομή 204 | * και μόλις βρέθει εισάγει στη σωστή γραμμή την εγγραφή με το τροποποιημένο πεδίο μέσα στο αρχείο /etc/shadow 205 | * αντικαθιστώντας την παλαιά εγγραφή. 206 | */ 207 | int MyLibb::setspnam(struct spwd *sh) 208 | { 209 | FILE *fp = NULL, *swf = NULL; 210 | int x, ret; 211 | int fd; 212 | bool found; 213 | int namelen; 214 | int buflen = 256; 215 | char *linebuf = (char*)calloc(buflen, sizeof(char)); 216 | 217 | if (!linebuf) return -1; 218 | 219 | //σε περίπτωση που το προσωρινό αρχείο υπάρχει και δεν έχει διαγραφεί για λόγους όπως να έχει διακοπεί η διεργασία πριν διαγραφεί το αρχείο ,τοτε η παρακάτω επανάληψη χρησιμοποιειται για να διαγράψει προσωρινα αρχεία και να δημιουργήσει καινούρια 220 | for (x = 0; x < 3; x++) { 221 | if (x > 0) 222 | { 223 | unlink(STMP_FILE); 224 | sleep(1); 225 | } 226 | fd = open(STMPTMP_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644);//-rw-r--r-- owner ->rw group->r other->r 227 | if (!fd) 228 | { 229 | 230 | return -1; 231 | } 232 | ret = link(STMPTMP_FILE, STMP_FILE); 233 | unlink(STMPTMP_FILE); 234 | if (ret == -1) 235 | close (fd); 236 | else 237 | break; 238 | } 239 | if (ret == -1) return -1; 240 | 241 | fp = fopen_wrapper(STMP_FILE, "w+"); 242 | swf = fopen_wrapper(SH_FILE, "r"); 243 | 244 | namelen = strlen(sh->sp_namp); 245 | found = false; 246 | //διαβάζεται γραμμή προς γραμμή το προσωρινο αρχείο SH_FILE που βρίσκεται στον κατάλογο /tmp/. 247 | while (fgets(linebuf, buflen, swf) != NULL) 248 | { 249 | 250 | int res = strncmp(linebuf, sh->sp_namp, namelen); 251 | if ((found == false) && (res == 0) ) 252 | { 253 | putspent(sh, fp); 254 | found = true; 255 | continue; 256 | } 257 | //προσθέτει εγγραφές χαρακτήρων στο αρχείο έως ότου φθάσει στον χαρακτήρα null \0 258 | fputs(linebuf, fp); 259 | } 260 | if(fclose(fp)) fp = NULL; 261 | if(close(fd)) fd = -1; 262 | if(fclose (swf)) swf = NULL; 263 | if (!found) 264 | { 265 | errno = EIDRM; 266 | QMessageBox::critical( 0,tr( "User Manager" ),tr( "%1").arg(strerror(errno))); 267 | return -1; 268 | } 269 | unlink(SH_FILE".bak"); 270 | link(SH_FILE, SH_FILE".bak"); 271 | rename(STMP_FILE, SH_FILE) ; 272 | 273 | if (linebuf != NULL) free(linebuf); 274 | unlink(STMP_FILE); 275 | 276 | return 0; 277 | } 278 | /** 279 | * Η συνάρτηση διαβάζει το αρχείο γραμμή πρός γραμμη εώς ότου να βρεθεί η εγγραφή η οποία είναι δείκτης σε δομή 280 | * και μόλις βρέθει εισάγει στη σωστή γραμμή την εγγραφή με το τροποποιημένο πεδίο μέσα στο αρχείο /etc/group * αντικαθιστώντας την παλαιά εγγραφή. 281 | */ 282 | int MyLibb::setgrnam(struct group *gr) 283 | { 284 | FILE *fp = NULL, *pwf = NULL; 285 | int x, ret; 286 | int fd; 287 | bool found; 288 | 289 | int namelen; 290 | int buflen = 256; 291 | char *linebuf = (char*)calloc(buflen, sizeof(char)); 292 | 293 | if (linebuf == NULL) 294 | return -1; 295 | //σε περίπτωση που το προσωρινό αρχείο υπάρχει και δεν έχει διαγραφεί για λόγους όπως να έχει διακοπεί η διεργασία πριν διαγραφεί το αρχείο ,τοτε η παρακάτω επανάληψη χρησιμοποιειται για να διαγράψει προσωρινα αρχεία και να δημιουργήσει καινούρια 296 | for (x = 0; x < 3; x++) { 297 | if (x > 0) 298 | { 299 | unlink(GTMP_FILE); 300 | sleep(1); 301 | } 302 | fd = open(GTMPTMP_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644);//-rw-r--r-- owner ->rw group->r other->r 303 | if (!fd) 304 | { 305 | return -1; 306 | } 307 | ret = link(GTMPTMP_FILE, GTMP_FILE); 308 | unlink(GTMPTMP_FILE); 309 | if (ret == -1) 310 | close (fd); 311 | else 312 | break; 313 | } 314 | if (ret == -1) return -1; 315 | 316 | fp = fopen_wrapper(GTMP_FILE, "w+"); 317 | pwf = fopen_wrapper(GR_FILE, "r"); 318 | 319 | namelen = strlen(gr->gr_name); 320 | found = false; 321 | 322 | //διαβάζεται γραμμή προς γραμμή το προσωρινο αρχείο GR_FILE. 323 | while (fgets(linebuf, buflen, pwf) != NULL) 324 | { 325 | 326 | int res = strncmp(linebuf, gr->gr_name, namelen); 327 | if ((found == false) && (res == 0) ) 328 | { 329 | putgrent(gr, fp); 330 | found = true; 331 | continue; 332 | } 333 | //προσθέτει εγγραφές χαρακτήρων στο αρχείο έως ότου φθάσει στον χαρακτήρα null \0 334 | fputs(linebuf, fp); 335 | 336 | } 337 | 338 | fclose(fp); 339 | close(fd); 340 | fclose(pwf); 341 | 342 | if (!found) 343 | { 344 | errno = EIDRM; 345 | QMessageBox::critical( 0,tr( "User Manager" ),tr( "%1").arg(strerror(errno))); 346 | if (linebuf!=NULL) 347 | { 348 | free(linebuf); 349 | linebuf = NULL; 350 | } 351 | return -1; 352 | } 353 | 354 | unlink(GR_FILE".bak"); 355 | 356 | link(GR_FILE, GR_FILE".bak"); 357 | 358 | rename(GTMP_FILE, GR_FILE) ; 359 | 360 | if (linebuf != NULL) { free(linebuf); linebuf = NULL; } 361 | unlink(GTMP_FILE); 362 | 363 | return 0; 364 | } 365 | /** 366 | * Η συνάρτηση διαβάζει το αρχείο γραμμή πρός γραμμη εώς ότου να βρεθεί η εγγραφή η οποία είναι δείκτης σε δομή 367 | * και μόλις βρέθει εισάγει στη σωστή γραμμή την εγγραφή με το τροποποιημένο πεδίο μέσα στο αρχείο passwd αντικαθιστώντας την παλαιά εγγραφή. 368 | */ 369 | int MyLibb::setpwnam (struct passwd *pwd) 370 | { 371 | 372 | FILE *fp = NULL, *pwf = NULL; 373 | int x, ret; 374 | int fd; 375 | bool found; 376 | int namelen; 377 | int buflen = 256; 378 | char *linebuf = (char*)calloc(buflen, sizeof(char)); 379 | if (!linebuf) return -1; 380 | 381 | //σε περίπτωση που το προσωρινό αρχείο υπάρχει και δεν έχει διαγραφεί για λόγους όπως να έχει διακοπεί η διεργασία πριν διαγραφεί το αρχείο ,τοτε η παρακάτω επανάληψη χρησιμοποιειται για να διαγράψει προσωρινα αρχεία και να δημιουργήσει καινούρια 382 | for (x = 0; x < 3; x++) { 383 | if (x > 0) 384 | { 385 | unlink(PTMP_FILE); 386 | sleep(1); 387 | } 388 | fd = open(PTMPTMP_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644); //-rw-r--r-- owner ->rw group->r other->r 389 | if (!fd) { 390 | return -1; 391 | } 392 | ret = link(PTMPTMP_FILE, PTMP_FILE); 393 | unlink(PTMPTMP_FILE); 394 | if (ret == -1) 395 | close (fd); 396 | else 397 | break; 398 | } 399 | if (ret == -1) return -1; 400 | 401 | fp = fopen_wrapper(PTMP_FILE, "w+"); 402 | pwf = fopen_wrapper(PASSWD_FILE, "r"); 403 | 404 | namelen = strlen(pwd->pw_name); 405 | 406 | found = false; 407 | 408 | //διαβάζεται γραμμή προς γραμμή το προσωρινο αρχείο PASSWD_FILE που βρίσκεται στον κατάλογο /tmp/. 409 | while (fgets(linebuf, buflen, pwf) != NULL) 410 | { 411 | int res = strncmp(linebuf,pwd->pw_name, namelen); 412 | if ((found == false) && (res == 0) ) 413 | { 414 | putpwent(pwd, fp); 415 | found = true; 416 | continue; 417 | } 418 | //προσθέτει εγγραφές χαρακτήρων στο αρχείο έως ότου φθάσει στον χαρακτήρα null \0 419 | fputs(linebuf, fp); 420 | } 421 | 422 | fclose(fp); 423 | close(fd); 424 | fclose (pwf); 425 | 426 | if (!found) { 427 | errno = EIDRM; 428 | QMessageBox::critical( 0,tr( "User Manager" ),tr( " %1 ").arg(strerror(errno))); 429 | if (linebuf != NULL) free(linebuf); 430 | return -1; 431 | } 432 | 433 | unlink(PASSWD_FILE".bak"); 434 | 435 | link(PASSWD_FILE, PASSWD_FILE".bak"); 436 | 437 | rename(PTMP_FILE, PASSWD_FILE) ; 438 | 439 | if (linebuf != NULL) free(linebuf); 440 | unlink(PTMP_FILE); 441 | return 0; 442 | } 443 | 444 | 445 | 446 | 447 | -------------------------------------------------------------------------------- /myLibb.h: -------------------------------------------------------------------------------- 1 | #ifndef MYLIBB_H 2 | #define MYLIBB_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /** 11 | Δομή στην οποία αποθηκεύονται βασικές πληροφορίες ενός λογαριασμού.Χρησιμοποιείται στην επεξεργασία στοιχείων των χρηστών, 12 | */ 13 | struct finfo 14 | { 15 | char *username; 16 | char *full_name; 17 | char *office; 18 | char *office_phone; 19 | char *home_phone; 20 | struct passwd *pw; 21 | }; 22 | 23 | /** 24 | Η κλάση περιέχει συναρτήσεις οι οποίες μας επιτρέπουν να επεξεργαστούμε εγγραφές στα αρχεία 25 | /etc/passwd /etc/group /etc/shadow και μια συνάρτηση ελέγχου η οποία ελέγχει αν είναι εφικτό το άνοιγμα αρχείων. 26 | */ 27 | class MyLibb : public QObject 28 | { 29 | Q_OBJECT 30 | public: 31 | MyLibb(); 32 | ~MyLibb(); 33 | int setspnam(struct spwd *sh); 34 | int setgrnam(struct group *gr); 35 | int setpwnam(struct passwd *pwd); 36 | int setgrnam_r(struct group *grs, char *grp); 37 | int setpwnam_r(struct passwd *pwd,char *name); 38 | FILE *fopen_wrapper(const char *filename,const char *mode); 39 | }; 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /other/exp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | HOST=`uname -n` 4 | 5 | email_user() { 6 | echo "Your password on $HOST will be expired in $DAYS_UNTIL_PASS_EXPIRE days" | mail -s "Password Expiration" $USER 7 | 8 | } 9 | 10 | ## Today's date (expressed in epoch format) 11 | today=`/usr/bin/perl -e 'printf("%d\n", (time/60/60/24))'` 12 | echo $today 13 | for line in `cat /etc/shadow` 14 | do 15 | USER=`echo $line | awk -F: '{print $1}'` 16 | DAY_LAST_PASS_CHANGE=`echo $line | awk -F: '{print $3}'` 17 | DAYS_PASS_VALID=`echo $line | awk -F: '{print $5}'` 18 | DAYS_SINCE_LAST_PASS_CHANGE=`expr $today - $DAY_LAST_PASS_CHANGE` 19 | DAYS_UNTIL_PASS_EXPIRE=`expr $DAYS_PASS_VALID - $DAYS_SINCE_LAST_PASS_CHANGE` 20 | 21 | echo $USER 22 | #echo $DAYS_UNTIL_PASS_EXPIRE 23 | echo $DAYS_PASS_VALID 24 | #echo $DAYS_SINCE_LAST_PASS_CHANGE 25 | echo $DAYS_UNTIL_PASS_EXPIRE 26 | 27 | 28 | if [ $DAYS_UNTIL_PASS_EXPIRE -lt "8" ] && [ $DAYS_UNTIL_PASS_EXPIRE -gt "-1" ]; then 29 | email_user $DAYS_UNTIL_PASS_EXPIRE 30 | fi 31 | 32 | done 33 | -------------------------------------------------------------------------------- /other/usermanager.conf: -------------------------------------------------------------------------------- 1 | WARN_USER=no 2 | MINIMUM_UID=1000 3 | MINIMUM_GID=1000 4 | LANGUAGE=English -------------------------------------------------------------------------------- /pathfile.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG 2 | #define GR_FILE "/etc/group" 3 | #define GTMP_FILE "/tmp/gtmp" 4 | #define GTMPTMP_FILE "/tmp/gtmptmp" 5 | #endif 6 | 7 | #ifndef DEBUG 8 | #define SH_FILE "/etc/shadow" 9 | #define STMP_FILE "/tmp/stmp" 10 | #define STMPTMP_FILE "/tmp/stmptmp" 11 | #define PASSWORD "/tmp/.password" 12 | #define TIMEDATE "/tmp/.timedate" 13 | #endif 14 | 15 | #ifndef DEBUG 16 | #define PASSWD_FILE "/etc/passwd" 17 | #define PTMP_FILE "/tmp/ptmp" 18 | #define PTMPTMP_FILE "/tmp/ptmptmp" 19 | #endif 20 | 21 | 22 | #ifndef DEBUG 23 | #define GROUP_FILE "/etc/group" 24 | #define SHADOW_FILE "/etc/shadow" 25 | //#define GSHAD_FILE "/home/xenofon/gshadow" 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /resources/images.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/p.jpeg 4 | images/qt.png 5 | images/keys.png 6 | images/quit.png 7 | images/editUser.png 8 | images/editGroup.png 9 | images/addgroup2.jpeg 10 | images/UserManager.gif 11 | images/backup.png 12 | images/CD.png 13 | images/fax.png 14 | images/floppy.png 15 | images/storage.png 16 | images/scanner.png 17 | images/log.png 18 | images/greek.jpeg 19 | images/uk.jpeg 20 | images/language.png 21 | images/deleteuser2.jpeg 22 | images/settings.png 23 | images/enabled.jpeg 24 | images/adduser.jpeg 25 | images/cancel.png 26 | images/user.jpeg 27 | images/deleteuser.jpeg 28 | images/refresh.png 29 | images/deleteuser1.jpeg 30 | images/group_remove.png 31 | images/group_add.png 32 | images/user_add.png 33 | images/addgr.jpeg 34 | images/search.png 35 | images/user_lock.png 36 | images/user_remove.png 37 | images/user_unlock.png 38 | images/edit.png 39 | images/group.jpeg 40 | images/lock.png 41 | images/ok.png 42 | images/reload.png 43 | images/remove.png 44 | images/add.png 45 | 46 | 47 | -------------------------------------------------------------------------------- /resources/images/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | ShowPreview=true 3 | Timestamp=2008,5,24,23,0,0 4 | -------------------------------------------------------------------------------- /resources/images/CD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/CD.png -------------------------------------------------------------------------------- /resources/images/UserManager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/UserManager.gif -------------------------------------------------------------------------------- /resources/images/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/about.png -------------------------------------------------------------------------------- /resources/images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/add.png -------------------------------------------------------------------------------- /resources/images/addgr.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/addgr.jpeg -------------------------------------------------------------------------------- /resources/images/addgr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/addgr.png -------------------------------------------------------------------------------- /resources/images/addgroup.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/addgroup.jpeg -------------------------------------------------------------------------------- /resources/images/addgroup2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/addgroup2.jpeg -------------------------------------------------------------------------------- /resources/images/adduser.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/adduser.jpeg -------------------------------------------------------------------------------- /resources/images/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/admin.png -------------------------------------------------------------------------------- /resources/images/apply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/apply.png -------------------------------------------------------------------------------- /resources/images/backup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/backup.png -------------------------------------------------------------------------------- /resources/images/bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/bottom.png -------------------------------------------------------------------------------- /resources/images/browse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/browse.png -------------------------------------------------------------------------------- /resources/images/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/cancel.png -------------------------------------------------------------------------------- /resources/images/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/clear.png -------------------------------------------------------------------------------- /resources/images/contexthelp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/contexthelp.png -------------------------------------------------------------------------------- /resources/images/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/copy.png -------------------------------------------------------------------------------- /resources/images/deleteuser.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/deleteuser.jpeg -------------------------------------------------------------------------------- /resources/images/deleteuser1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/deleteuser1.jpeg -------------------------------------------------------------------------------- /resources/images/deleteuser2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/deleteuser2.jpeg -------------------------------------------------------------------------------- /resources/images/dialout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/dialout.png -------------------------------------------------------------------------------- /resources/images/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/down.png -------------------------------------------------------------------------------- /resources/images/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/edit.png -------------------------------------------------------------------------------- /resources/images/editGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/editGroup.png -------------------------------------------------------------------------------- /resources/images/editUser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/editUser.png -------------------------------------------------------------------------------- /resources/images/enabled.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/enabled.jpeg -------------------------------------------------------------------------------- /resources/images/enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/enter.png -------------------------------------------------------------------------------- /resources/images/fax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/fax.png -------------------------------------------------------------------------------- /resources/images/floppy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/floppy.png -------------------------------------------------------------------------------- /resources/images/general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/general.png -------------------------------------------------------------------------------- /resources/images/greek.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/greek.jpeg -------------------------------------------------------------------------------- /resources/images/group.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/group.jpeg -------------------------------------------------------------------------------- /resources/images/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/group.png -------------------------------------------------------------------------------- /resources/images/group_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/group_add.png -------------------------------------------------------------------------------- /resources/images/group_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/group_remove.png -------------------------------------------------------------------------------- /resources/images/grub_entries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/grub_entries.png -------------------------------------------------------------------------------- /resources/images/grub_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/grub_settings.png -------------------------------------------------------------------------------- /resources/images/keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/keys.png -------------------------------------------------------------------------------- /resources/images/language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/language.png -------------------------------------------------------------------------------- /resources/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/loading.gif -------------------------------------------------------------------------------- /resources/images/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/lock.png -------------------------------------------------------------------------------- /resources/images/log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/log.png -------------------------------------------------------------------------------- /resources/images/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/ok.png -------------------------------------------------------------------------------- /resources/images/p.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/p.jpeg -------------------------------------------------------------------------------- /resources/images/path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/path.png -------------------------------------------------------------------------------- /resources/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/preview.png -------------------------------------------------------------------------------- /resources/images/profile_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/profile_edit.png -------------------------------------------------------------------------------- /resources/images/qgrubeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/qgrubeditor.png -------------------------------------------------------------------------------- /resources/images/qt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/qt.png -------------------------------------------------------------------------------- /resources/images/quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/quit.png -------------------------------------------------------------------------------- /resources/images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/refresh.png -------------------------------------------------------------------------------- /resources/images/reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/reload.png -------------------------------------------------------------------------------- /resources/images/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/remove.png -------------------------------------------------------------------------------- /resources/images/restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/restore.png -------------------------------------------------------------------------------- /resources/images/restore_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/restore_default.png -------------------------------------------------------------------------------- /resources/images/scan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/scan.png -------------------------------------------------------------------------------- /resources/images/scanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/scanner.png -------------------------------------------------------------------------------- /resources/images/search.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/search.jpg -------------------------------------------------------------------------------- /resources/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/search.png -------------------------------------------------------------------------------- /resources/images/searchuser.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/searchuser.jpeg -------------------------------------------------------------------------------- /resources/images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/settings.png -------------------------------------------------------------------------------- /resources/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/splash.png -------------------------------------------------------------------------------- /resources/images/storage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/storage.png -------------------------------------------------------------------------------- /resources/images/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/top.png -------------------------------------------------------------------------------- /resources/images/uk.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/uk.jpeg -------------------------------------------------------------------------------- /resources/images/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/up.png -------------------------------------------------------------------------------- /resources/images/user.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/user.jpeg -------------------------------------------------------------------------------- /resources/images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/user.png -------------------------------------------------------------------------------- /resources/images/user_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/user_add.png -------------------------------------------------------------------------------- /resources/images/user_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/user_lock.png -------------------------------------------------------------------------------- /resources/images/user_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/user_remove.png -------------------------------------------------------------------------------- /resources/images/user_unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/user_unlock.png -------------------------------------------------------------------------------- /resources/images/view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xen0vas/UserManager/f6327846068179f4373ab58d83d51c26501d1a43/resources/images/view.png -------------------------------------------------------------------------------- /sha256.cpp: -------------------------------------------------------------------------------- 1 | #include "sha256.h" 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | IHashing *sha256::Create() 8 | { 9 | return new sha256(); 10 | } 11 | 12 | void sha256::Free() 13 | { 14 | delete this; 15 | } 16 | 17 | /* Hashing */ 18 | 19 | char *sha256::encryptpass( QString passwd) const 20 | { 21 | HashEncode *hEnc = new HashEncode(); 22 | /* 23 | * seed is the SHA-256($5$) identifier 24 | */ 25 | static char seed[12]; 26 | seed[0] = '$'; 27 | seed[1] = '5'; 28 | seed[2] = '$'; 29 | 30 | /* 31 | * The srandom() function creates different sets of pseudorandom numbers every time the program runs. 32 | * It sets its argument as the seed for a new sequence of pseudo-random integers to be returned by random() 33 | */ 34 | 35 | srandom ( ( int ) time ( ( time_t * ) NULL ) ); 36 | hEnc->into64 ( &seed[3], random(),saltLength ); 37 | hEnc->into64 ( &seed[saltLength],random(),3 ); 38 | seed[saltLength+3] = '$'; 39 | 40 | if (hEnc != nullptr ) 41 | {delete hEnc; 42 | hEnc = nullptr;} 43 | 44 | char *buf = ( char * )calloc ( 512, sizeof(*buf) ); 45 | char *password = passwd.toLatin1().data(); 46 | memcpy( buf,password,strlen(password)); 47 | 48 | /* 49 | * The crypt_r function does the same thing as crypt, but takes an extra parameter which includes space for its result (among other things), so it can be reentrant. data->initialized must be cleared to zero before the first time crypt_r is called 50 | */ 51 | struct crypt_data data; 52 | data.initialized = 0; 53 | 54 | char *pass = crypt_r ( buf,seed, &data); 55 | 56 | if ( pass == NULL ) 57 | QMessageBox::critical ( 0,QObject::tr ( "User Manager" ),QObject::tr ( "%1" ).arg ( ENOSYS ) ); 58 | if (buf!=NULL)free(buf); 59 | return strdup ( pass ); 60 | } 61 | -------------------------------------------------------------------------------- /sha256.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "HashEncode.h" 4 | #include "IHashing.h" 5 | 6 | class sha256 : public IHashing 7 | { 8 | public: 9 | static const int saltLength = 8; 10 | char* encryptpass(QString passwd) const; 11 | void Free(); 12 | static IHashing* Create(); 13 | }; 14 | -------------------------------------------------------------------------------- /sha512.cpp: -------------------------------------------------------------------------------- 1 | #include "sha512.h" 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | IHashing *sha512::Create() 8 | { 9 | return new sha512(); 10 | } 11 | 12 | void sha512::Free() 13 | { 14 | delete this; 15 | } 16 | 17 | /* Hashing */ 18 | 19 | char *sha512::encryptpass( QString passwd) const 20 | { 21 | HashEncode *hEnc = new HashEncode(); 22 | //το seed είναι το αναγνωριστικό του αλγόριθμου SHA-512($6$) 23 | static char seed[12]; 24 | seed[0] = '$'; 25 | seed[1] = '6'; 26 | seed[2] = '$'; 27 | //παράγει διαφορετικά σετ απο ψευδοτυχαίους αριθμούς κάθε φορά που το πρόγραμμα τρέχει 28 | //Στη συνέχεια η random επιστρέφει τυχαίους αριθμούς ανάλογα με το σετ που έχει δημιουργηθεί απο τη srandom 29 | srandom ( ( int ) time ( ( time_t * ) NULL ) ); 30 | hEnc->into64 ( &seed[3], random(),saltLength ); 31 | hEnc->into64 ( &seed[saltLength],random(),3 ); 32 | seed[saltLength+3] = '$'; 33 | 34 | if (hEnc != nullptr ) 35 | {delete hEnc; 36 | hEnc = nullptr;} 37 | 38 | char *buf = ( char * )calloc ( 512, sizeof(*buf) ); 39 | char *password = passwd.toLatin1().data(); 40 | strncpy( buf,password,strlen(password)); 41 | 42 | /* 43 | * The crypt_r function does the same thing as crypt, but takes an extra parameter which includes space 44 | * for its result (among other things), so it can be reentrant. 45 | * data->initialized must be cleared to zero before the first time crypt_r is called 46 | */ 47 | struct crypt_data data; 48 | data.initialized = 0; 49 | 50 | char *pass = crypt_r ( buf,seed, &data); 51 | 52 | if ( pass == NULL ) 53 | QMessageBox::critical ( 0,QObject::tr ( "User Manager" ),QObject::tr ( "%1" ).arg ( ENOSYS ) ); 54 | if (buf!=NULL)free(buf); 55 | return strdup ( pass ); 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /sha512.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "HashEncode.h" 4 | #include "IHashing.h" 5 | 6 | class sha512 : public IHashing 7 | { 8 | public: 9 | static const int saltLength = 8; 10 | char* encryptpass(QString passwd) const; 11 | void Free(); 12 | static IHashing* Create(); 13 | }; 14 | -------------------------------------------------------------------------------- /spc.cpp: -------------------------------------------------------------------------------- 1 | #include "spc.h" 2 | #include 3 | #include 4 | 5 | using std::string; 6 | 7 | 8 | Spc::Spc() 9 | {} 10 | 11 | Spc::~Spc() 12 | {} 13 | 14 | 15 | /** 16 | * A space-separated list of variable=value pairs is returned, with variable names guaranteed not to contain equal signs (=), 17 | * and variable=value pairs guaranteed not to contain spaces. Used together with the _CS_PATH request, 18 | * this completely describes the minimum environment variable settings required to obtain a clean, conforming environment. 19 | * On systems conforming to the POSIX.1-2008 standard, this should be used to create a sanitized environment 20 | */ 21 | int Spc::clearenv(void) 22 | { 23 | 24 | static char *namebuf = NULL; 25 | static size_t lastlen = 0; 26 | 27 | while (environ != NULL && environ[0] != NULL) 28 | { 29 | size_t len = strcspn(environ[0], "="); 30 | 31 | if (len == 0) { 32 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Problem calculating the size %1 " ).arg ( strerror ( errno ) ) ); 33 | return -1; 34 | } 35 | 36 | if (len > lastlen) { 37 | namebuf = (char*)realloc(namebuf, len+1); 38 | 39 | if (namebuf == NULL) { 40 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Cannot rellocate memory %1 " ).arg ( strerror ( errno ) ) ); 41 | return -1; 42 | } 43 | 44 | lastlen = len; 45 | } 46 | 47 | memcpy(namebuf, environ[0], len); 48 | namebuf[len] = '\0'; 49 | 50 | if (unsetenv(namebuf) == -1) { 51 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Cannot unset the environmental variable %1 " ).arg ( strerror ( errno ) ) ); 52 | if (namebuf != NULL) 53 | return -1; 54 | } 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | /** 61 | * This function used to clear Environmental variables. 62 | * The environment is cleared by clearenv(), and then the PATH and IFS variables are set to safe values before system() is invoked 63 | * Ref:. ENV03-C. Sanitize the environment when invoking external programs 64 | */ 65 | int Spc::clenv(void) 66 | { 67 | 68 | char *pathbuf = {} ; 69 | 70 | size_t n; 71 | 72 | n = confstr(_CS_PATH, NULL, 0); 73 | 74 | if (clearenv() != 0) { 75 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Clearing the environment failed %1 " ).arg ( strerror ( errno ) ) ); 76 | return -1; 77 | } else if (n == 0) { 78 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Could not allocate memory for path %1 " ).arg ( strerror ( errno ) ) ); 79 | return -1; 80 | } else if ((pathbuf = (char*)calloc(128, n)) == NULL) { 81 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Could not allocate memory for path %1 " ).arg ( strerror ( errno ) ) ); 82 | free(pathbuf); 83 | return -1; 84 | 85 | /* 86 | * _CS_PATH : This parameter’s value is the recommended default path for 87 | * searching for executable files. This is the path that a user has by default just after logging in 88 | */ 89 | 90 | } else if (confstr(_CS_PATH, pathbuf, n) == 0) { 91 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Could not get configuration dependent string variables %1 " ).arg ( strerror ( errno ) ) ); 92 | free(pathbuf); 93 | return -1; 94 | } else if (setenv("PATH", pathbuf, 1) == -1) { 95 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Setting default environment failed %1 " ).arg ( strerror ( errno ) ) ); 96 | free(pathbuf); 97 | return -1; 98 | } else if (setenv("IFS", " \t\n", 1) == -1) { 99 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Setting IFS failed %1 " ).arg ( strerror ( errno ) ) ); 100 | free(pathbuf); 101 | return -1; 102 | } 103 | free(pathbuf); 104 | return 0; 105 | } 106 | 107 | char *Spc::canonicalize_path(QByteArray directory) 108 | { 109 | size_t path_size = (size_t)PATH_MAX+1; 110 | char *realpath_res = NULL; 111 | char *canonical_path = NULL; 112 | char *actualpath = NULL; 113 | const size_t len = strlen( directory.data() ); 114 | 115 | if (path_size > 0) { 116 | canonical_path = (char*)calloc(1,path_size); 117 | 118 | if (canonical_path == NULL) { 119 | 120 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Could not calculate memory for homedir path " ) ) ; 121 | } 122 | else if( (strrchr( directory.data(), '/') != directory.data() + len) && canonical_path != NULL ) 123 | { 124 | actualpath = directory.data(); 125 | realpath_res = realpath(actualpath, canonical_path); 126 | } 127 | else 128 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Invalid path detected " ) ) ; 129 | } 130 | 131 | if (realpath_res == NULL ) 132 | { 133 | QMessageBox::critical ( 0,tr ( "User Manager" ),tr ( " Invalid path %1 " ).arg ( strerror ( errno ) ) ); 134 | } 135 | 136 | if ( canonical_path != NULL ) { free(canonical_path); canonical_path = NULL; } 137 | 138 | return realpath_res; 139 | } 140 | 141 | /** 142 | * Sanitize sascpicious characters in order to avoid injections. Possible characters that migh cause harm are 143 | * *,-,+,|,/,\,*,&,{,},[,],\0,\x1A,\r,\t,\n,<,>,;,#,\",' .These chars need to be trimmed. 144 | * The stringValue called be reference and has to be checked 145 | */ 146 | void Spc::spc_sanitize(std::string &stringValue) 147 | { 148 | stringValue.erase( 149 | std::remove_if( 150 | stringValue.begin(), stringValue.end(), [](char const c) { 151 | return '\\' == c || '"' == c || '#' == c || '\'' == c || '\r' == c || '{' == c || '}' ==c || '[' == c || ']' == c || '&' == c || '+' == c || ';' == c || '<' == c || '>' == c || '-' == c || '/' == c || '*' == c || '%' == c || '\n' == c || '|' == c || '\0' == c || '\x1A' == c; 152 | } 153 | ), 154 | stringValue.end() 155 | ); 156 | } 157 | 158 | void Spc::spc_drop_privilleges(int permanent) 159 | { 160 | gid_t newgid = getgid( ), oldgid = getegid( ); 161 | uid_t newuid = getuid( ), olduid = geteuid( ); 162 | 163 | if (!permanent) { 164 | /* Save information about the privileges that are being dropped so that they 165 | * can be restored later. 166 | */ 167 | orig_gid = oldgid; 168 | orig_uid = olduid; 169 | orig_ngroups = getgroups(NGROUPS_MAX, orig_groups); 170 | } 171 | 172 | if (!olduid) 173 | setgroups(1, &newgid); 174 | 175 | 176 | if (newgid != oldgid) { 177 | #if !defined(linux) 178 | setegid(newgid); 179 | if (permanent && setgid(newgid) == -1) abort( ); 180 | #else 181 | if (setregid((permanent ? newgid : -1), newgid) == -1) abort( ); 182 | #endif 183 | } 184 | 185 | if (newuid != olduid) { 186 | #if !defined(linux) 187 | seteuid(newuid); 188 | if (permanent && setuid(newuid) == -1) abort(); 189 | #else 190 | if (setreuid((permanent ? newuid : -1), newuid) == -1) abort( ); 191 | #endif 192 | } 193 | 194 | if (newuid != olduid) { 195 | #if !defined(linux) 196 | seteuid(newuid); 197 | if (permanent && setuid(newuid) == -1) abort(); 198 | #else 199 | if (setreuid((permanent ? newuid : -1), newuid) == -1) abort( ); 200 | #endif 201 | } 202 | 203 | /* verify that the changes were successful */ 204 | if (permanent) { 205 | if (newgid != oldgid && (setegid(oldgid) != -1 || getegid( ) != newgid)) 206 | abort( ); 207 | if (newuid != olduid && (seteuid(olduid) != -1 || geteuid( ) != newuid)) 208 | abort( ); 209 | } else { 210 | if (newgid != oldgid && getegid( ) != newgid) abort( ); 211 | if (newuid != olduid && geteuid( ) != newuid) abort( ); 212 | } 213 | } 214 | 215 | void Spc::spc_restore_privileges() 216 | { 217 | if (geteuid( ) != orig_uid) 218 | if (seteuid(orig_uid) == -1 || geteuid( ) != orig_uid) abort( ); 219 | if (getegid( ) != orig_gid) 220 | if (setegid(orig_gid) == -1 || getegid( ) != orig_gid) abort( ); 221 | if (!orig_uid) 222 | setgroups(orig_ngroups, orig_groups); 223 | } 224 | -------------------------------------------------------------------------------- /spc.h: -------------------------------------------------------------------------------- 1 | #ifndef SPC_H 2 | #define SPC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | static int orig_ngroups = -1; 19 | static gid_t orig_gid = -1; 20 | static uid_t orig_uid = -1; 21 | static gid_t orig_groups[NGROUPS_MAX]; 22 | 23 | class Spc : public QObject 24 | { 25 | Q_OBJECT 26 | 27 | protected: 28 | Spc(); 29 | ~Spc(); 30 | void spc_drop_privilleges(int permanent); 31 | void spc_restore_privileges(void); 32 | void spc_sanitize(std::string &stringValue); 33 | int clearenv(void); 34 | int clenv(void); 35 | char *canonicalize_path(QByteArray di); 36 | friend class GroupProperties; 37 | friend class UserProperties; 38 | friend class Groups; 39 | friend class MainWindow; 40 | friend class EditProperties; 41 | }; 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /ui/GroupProperties.ui: -------------------------------------------------------------------------------- 1 | 2 | GroupProperties 3 | 4 | 5 | 6 | 0 7 | 0 8 | 450 9 | 448 10 | 11 | 12 | 13 | false 14 | 15 | 16 | Qt::StrongFocus 17 | 18 | 19 | false 20 | 21 | 22 | Group Properties 23 | 24 | 25 | 26 | :/new/prefix1/images/editGroup.png:/new/prefix1/images/editGroup.png 27 | 28 | 29 | false 30 | 31 | 32 | 33 | 34 | 35 | Group ID: 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 0 44 | 0 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | OpenHandCursor 53 | 54 | 55 | false 56 | 57 | 58 | ... 59 | 60 | 61 | 62 | :/new/prefix1/images/addgr.jpeg:/new/prefix1/images/addgr.jpeg 63 | 64 | 65 | 66 | 50 67 | 40 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Qt::Horizontal 76 | 77 | 78 | 79 | 98 80 | 20 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | Qt::ClickFocus 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | Group Name: 99 | 100 | 101 | 102 | 103 | 104 | 105 | Qt::Vertical 106 | 107 | 108 | QSizePolicy::Preferred 109 | 110 | 111 | 112 | 20 113 | 18 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 0 123 | 0 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | Qt::Horizontal 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | true 144 | 145 | 146 | 147 | 0 148 | 0 149 | 150 | 151 | 152 | PointingHandCursor 153 | 154 | 155 | true 156 | 157 | 158 | true 159 | 160 | 161 | selection-background-color: red 162 | 163 | 164 | QAbstractItemView::NoEditTriggers 165 | 166 | 167 | false 168 | 169 | 170 | true 171 | 172 | 173 | QAbstractItemView::ExtendedSelection 174 | 175 | 176 | false 177 | 178 | 179 | true 180 | 181 | 182 | true 183 | 184 | 185 | true 186 | 187 | 188 | true 189 | 190 | 191 | 192 | 193 | 194 | 195 | Qt::Vertical 196 | 197 | 198 | 199 | 20 200 | 78 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 0 210 | 0 211 | 212 | 213 | 214 | PointingHandCursor 215 | 216 | 217 | true 218 | 219 | 220 | true 221 | 222 | 223 | selection-background-color: red 224 | 225 | 226 | QFrame::StyledPanel 227 | 228 | 229 | QFrame::Sunken 230 | 231 | 232 | QAbstractItemView::NoEditTriggers 233 | 234 | 235 | true 236 | 237 | 238 | QAbstractItemView::ExtendedSelection 239 | 240 | 241 | false 242 | 243 | 244 | true 245 | 246 | 247 | true 248 | 249 | 250 | true 251 | 252 | 253 | true 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | <- Add 263 | 264 | 265 | 266 | 267 | 268 | 269 | Remove-> 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | Qt::Vertical 279 | 280 | 281 | 282 | 20 283 | 98 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | Qt::Horizontal 294 | 295 | 296 | 297 | 270 298 | 20 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | &OK 307 | 308 | 309 | 310 | :/new/prefix1/images/ok.png:/new/prefix1/images/ok.png 311 | 312 | 313 | 314 | 315 | 316 | 317 | &Close 318 | 319 | 320 | 321 | :/new/prefix1/images/cancel.png:/new/prefix1/images/cancel.png 322 | 323 | 324 | 325 | 326 | 327 | 328 | Qt::Horizontal 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 110 337 | 16 338 | 63 339 | 17 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | closeBtn 353 | clicked() 354 | GroupProperties 355 | close() 356 | 357 | 358 | 385 359 | 421 360 | 361 | 362 | 188 363 | 422 364 | 365 | 366 | 367 | 368 | 369 | -------------------------------------------------------------------------------- /ui/HashingAlgorithm.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | HashingAlgorithm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 366 10 | 415 11 | 12 | 13 | 14 | 15 | 75 16 | true 17 | 18 | 19 | 20 | Setup Password 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 91 30 | 16777215 31 | 32 | 33 | 34 | User name : 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 0 43 | 0 44 | 45 | 46 | 47 | 48 | 151 49 | 16777215 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Qt::Horizontal 61 | 62 | 63 | 64 | 40 65 | 20 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 0 75 | 0 76 | 77 | 78 | 79 | 80 | 151 81 | 16777215 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | Qt::Vertical 95 | 96 | 97 | QSizePolicy::Preferred 98 | 99 | 100 | 101 | 345 102 | 28 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | Hashing Algorithm 111 | 112 | 113 | 114 | 115 | 116 | SHA-512 117 | 118 | 119 | 120 | 121 | 122 | 123 | MD5 124 | 125 | 126 | 127 | 128 | 129 | 130 | SHA-256 131 | 132 | 133 | 134 | 135 | 136 | 137 | Blowfish 138 | 139 | 140 | 141 | 142 | Sha256rdb 143 | MD5rdb 144 | Sha512rdb 145 | Blowfishrdb 146 | 147 | 148 | 149 | 150 | 151 | Qt::Vertical 152 | 153 | 154 | QSizePolicy::Preferred 155 | 156 | 157 | 158 | 348 159 | 34 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | Password: 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | Qt::Vertical 184 | 185 | 186 | QSizePolicy::Preferred 187 | 188 | 189 | 190 | 321 191 | 14 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | Confirm: 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | Qt::Vertical 210 | 211 | 212 | QSizePolicy::Preferred 213 | 214 | 215 | 216 | 321 217 | 15 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | Qt::Vertical 229 | 230 | 231 | QSizePolicy::Preferred 232 | 233 | 234 | 235 | 348 236 | 34 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | Qt::Horizontal 247 | 248 | 249 | 250 | 68 251 | 20 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | Close 260 | 261 | 262 | 263 | :/new/prefix1/images/cancel.png:/new/prefix1/images/cancel.png 264 | 265 | 266 | 267 | 268 | 269 | 270 | Accept 271 | 272 | 273 | 274 | :/new/prefix1/images/ok.png:/new/prefix1/images/ok.png 275 | 276 | 277 | 278 | 279 | 280 | 281 | Qt::Horizontal 282 | 283 | 284 | 285 | 68 286 | 20 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | verticalSpacer_10 295 | groupBox 296 | verticalSpacer_11 297 | verticalSpacer_13 298 | groupBox_2 299 | 300 | 301 | 302 | 303 | 304 | 305 | okBtn 306 | clicked() 307 | HashingAlgorithm 308 | close() 309 | 310 | 311 | 179 312 | 404 313 | 314 | 315 | 115 316 | 91 317 | 318 | 319 | 320 | 321 | 322 | -------------------------------------------------------------------------------- /ui/Settings.ui: -------------------------------------------------------------------------------- 1 | 2 | Settings 3 | 4 | 5 | Qt::WindowModal 6 | 7 | 8 | 9 | 0 10 | 0 11 | 541 12 | 338 13 | 14 | 15 | 16 | UserManager-Settings 17 | 18 | 19 | 20 | :/new/prefix1/images/settings.png:/new/prefix1/images/settings.png 21 | 22 | 23 | 24 | 25 | 429 26 | 60 27 | 31 28 | 23 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 190 39 | 51 40 | 241 41 | 41 42 | 43 | 44 | 45 | E-mail users before account expires 46 | 47 | 48 | Qt::RichText 49 | 50 | 51 | true 52 | 53 | 54 | true 55 | 56 | 57 | 58 | 59 | 60 | 230 61 | 280 62 | 91 63 | 30 64 | 65 | 66 | 67 | OK 68 | 69 | 70 | 71 | :/new/prefix1/images/ok.png:/new/prefix1/images/ok.png 72 | 73 | 74 | 75 | 76 | true 77 | 78 | 79 | 80 | 430 81 | 145 82 | 101 83 | 29 84 | 85 | 86 | 87 | 88 | 89 | true 90 | 91 | 92 | 93 | 430 94 | 101 95 | 101 96 | 31 97 | 98 | 99 | 100 | 101 | 102 | 103 | 190 104 | 100 105 | 241 106 | 31 107 | 108 | 109 | 110 | First Normal UID: 111 | 112 | 113 | 114 | 115 | 116 | 189 117 | 150 118 | 171 119 | 20 120 | 121 | 122 | 123 | First Normal GID: 124 | 125 | 126 | 127 | 128 | 129 | 190 130 | 200 131 | 221 132 | 20 133 | 134 | 135 | 136 | Select Language: 137 | 138 | 139 | 140 | 141 | 142 | 430 143 | 200 144 | 101 145 | 25 146 | 147 | 148 | 149 | true 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | okSetBtn 159 | clicked() 160 | Settings 161 | close() 162 | 163 | 164 | 274 165 | 292 166 | 167 | 168 | 372 169 | 290 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /userproperties.h: -------------------------------------------------------------------------------- 1 | #ifndef USERPROPERTIES_H 2 | #define USERPROPERTIES_H 3 | // 4 | #include "ui_UserProperties.h" 5 | #include 6 | #include 7 | #include "users.h" 8 | 9 | using namespace std; 10 | 11 | 12 | /** 13 | * This class used in order to process UserProperties form data. 14 | * Αποτελεί κλάση ορίου-διεπαφής καθώς επικοινωνεί με τη φόρμα-χρήστη και κληρονομεί τις ιδιότητες και τα χαρακτηριστικά της. 15 | * Περιέχει συναρτήσεις που σκοπό έχουν να λαμβάνουν και να επιστρέφουν δεδομένα που χειρίζεται η φόρμα. 16 | * Επίσης χειρίζεται *συναρτήσεις κρυπτογράφησης και δημιουργίας κωδικών 17 | */ 18 | 19 | class UserProperties : public QDialog , public Ui::UserProperties 20 | { 21 | Q_OBJECT 22 | public: 23 | UserProperties( QWidget *parent = 0 ); 24 | ~UserProperties(); 25 | void combotext(); 26 | int setPasswdUID(); 27 | 28 | private: 29 | QString oldUsername_; 30 | QString passhash; 31 | int insertIntoPasswdFile(QString nam,QString uid,QString gid,QString directory,QString gec, QString shellcon ); 32 | int insertIntoGroupFile(QString nam,QString gid); 33 | struct spwd setShadowStruct(int max, int warn,int inact, int min,string inact_user,char *name,char *password_hash,int current_days); 34 | int insertIntoShadowFile(QString logname,QString encrypted_pass); 35 | void addGroup(QString label, char* group); 36 | // use execve in order to execute external programs 37 | void addGroup_execve(QString label, char* group); 38 | void usermod_execve(QString index, QString label); 39 | 40 | public slots: 41 | void openHashingAlgorithm(); 42 | void fillEasyList(); 43 | void easyCheckboxClicked(); 44 | void addUserBase(); 45 | void setFormContents(); 46 | void easyAddGroups(const QModelIndex &index); 47 | void changeMembers(const QModelIndex &index ); 48 | void setPrimaryGroup(); 49 | 50 | 51 | }; 52 | #endif 53 | -------------------------------------------------------------------------------- /users.cpp: -------------------------------------------------------------------------------- 1 | #include "users.h" 2 | #include 3 | #include "myLibb.h" 4 | #define MAX_FIELD_SIZE 256 5 | 6 | using std::string; 7 | /** 8 | * Constructor κλάσης. 9 | */ 10 | Users::Users() 11 | {} 12 | /** 13 | * Destructor κλάσης. 14 | */ 15 | Users::~Users() 16 | {} 17 | /** 18 | * Αναζήτηση ενός χρήστη στο σύστημα.Η συνάρτηση αναζητεί ένα χρήστη στο σύστημα και αν βρεθέι επιστρέφει την δομή του. 19 | */ 20 | struct passwd *Users::searchUser() 21 | { 22 | bool okBtn; 23 | char *userToSearch ; 24 | 25 | struct passwd *result = NULL; 26 | QString userString = QInputDialog::getText( 0, QObject::tr( "Search" ), QObject::tr( "Enter Login Name:(case sensitive)" ), QLineEdit::Normal, QString( "" ), &okBtn ); 27 | 28 | if ( okBtn && userString != " " ) 29 | { 30 | userToSearch = userString.toLatin1().data(); 31 | result = getpwnam( userToSearch ); 32 | if ( result == NULL ) 33 | { 34 | QMessageBox::information( 0, QObject::tr( "User Manager" ), QObject::tr( "User %1 not found" ).arg( userString ) ); 35 | } 36 | } 37 | return result; 38 | } 39 | /** 40 | * Ψάχνει να βρει αν υπάρχει ένας συγκεκριμένος χρήστης στο σύστημα.Επιστρέφει true σν βρεθεί διαφορετικά επιστρέφει false. 41 | */ 42 | bool Users::userExists( QString name ) 43 | { 44 | struct passwd *user; 45 | user = getpwnam( name.toLatin1().data() ); 46 | if ( user != NULL ) 47 | { 48 | QMessageBox::information( 0, QObject::tr( "User Manager" ), QObject::tr( "User Exists!! " ) ); 49 | return true; 50 | } 51 | else 52 | return false; 53 | } 54 | 55 | /** 56 | * Searches for the main group of a certain user. It takes the UID as an argument and then searches the 57 | * group structure to find the user's group using the group id 58 | * 59 | */ 60 | QString Users::getUsersPrimaryGroup( QString UID ) 61 | { 62 | struct passwd pwd; 63 | struct passwd *result; 64 | struct group *group = {}; 65 | size_t pwdlen; 66 | QString groupName=""; 67 | 68 | QByteArray pwuid = UID.toLatin1(); 69 | 70 | size_t size = strlen(pwuid.data()); 71 | 72 | char *pwuid_t = (char*)calloc(size, sizeof(char)); 73 | 74 | if (pwuid_t != NULL) 75 | { 76 | 77 | strncpy(pwuid_t, pwuid.data(), strlen(pwuid.data())); 78 | 79 | pwdlen = sysconf(_SC_GETPW_R_SIZE_MAX); 80 | if (pwdlen == (size_t)-1) 81 | pwdlen = 16384; 82 | 83 | char *pwdBuffer = (char*)malloc(pwdlen); 84 | 85 | memset( pwdBuffer, 0, sizeof(char) ); 86 | 87 | setgrent(); 88 | if ((getpwuid_r(atoi(pwuid_t), &pwd, pwdBuffer, pwdlen, &result)) == 0 ) 89 | { 90 | group = getgrgid( pwd.pw_gid ); 91 | } 92 | if (group!=NULL) 93 | groupName = QString::fromUtf8( group->gr_name ); 94 | else 95 | QMessageBox::critical( 0, QObject::tr( "User Manager" ), QObject::tr( "No group entry for user %1 in /etc/group" ).arg(pwd.pw_name) ); 96 | endgrent(); 97 | if ( pwuid_t != NULL ) { free(pwuid_t) ; pwuid_t = NULL; } 98 | if ( pwdBuffer != NULL ) { free(pwdBuffer); pwdBuffer = NULL; } 99 | } 100 | else 101 | { 102 | errno = ENOMEM; 103 | QMessageBox::critical( 0, QObject::tr( "User Manager" ), QObject::tr("Bad memory allocation : %1 ").arg(errno)); 104 | } 105 | return groupName; 106 | } 107 | 108 | /** 109 | * 110 | * The following function searches the groups that the user is member taking as a parameter the name of the user 111 | * 112 | */ 113 | 114 | QString Users::getUsersSecondaryGroups( QString name ) 115 | { 116 | struct group *group; 117 | setgrent(); 118 | QString listGroup; 119 | QByteArray nameArray = name.toLatin1(); 120 | const char *userChar = nameArray.data(); 121 | 122 | char **members; 123 | members = (char**)malloc(sizeof(char*)); 124 | memset(&members, 0, sizeof(members)); 125 | while (( group = getgrent() ) != NULL ) 126 | { 127 | for ( members = group->gr_mem; *members; members++ ) 128 | if ( strncmp( *members, userChar, strlen(*members) ) == 0 ) 129 | { 130 | listGroup.append( group->gr_name ); 131 | listGroup.append( "," ); 132 | } 133 | } 134 | listGroup.chop(1); 135 | endgrent(); 136 | free(*members); 137 | return listGroup; 138 | } 139 | /** 140 | * Η συνάρτηση σαρώνει μια μια τις εγγραφές από το /etc/shadow και ψάχνει να βρει αν ένας λογαριασμός είναι κλειδωμένος. 141 | * Για να θεωρηθεί κλειδωμένος ένας λογαριασμός πρέπει το δεύτερο πεδίο της εγγραφής το οποίο είναι ο κρυπτογραφημένος κωδικός να έχι ένα ! ή * 142 | * Επιστρέφει true αν ο λογαριασμός είναι κλειδωμένος και false αν δεν είναι. 143 | */ 144 | bool Users::isLocked( QString user ) 145 | { 146 | 147 | struct spwd *sp; 148 | int sp_size = sizeof(sp->sp_pwdp); 149 | bool lock = false; 150 | QByteArray userArray = user.toLatin1(); 151 | const char *userChar = userArray.data(); 152 | setspent(); 153 | 154 | sp = getspnam( userChar ); 155 | if(sp != NULL) 156 | { 157 | if ( strncmp( sp->sp_pwdp, "!",1 ) == 0 || strncmp( sp->sp_pwdp, "*" , sp_size) == 0 ) 158 | lock = true; 159 | } 160 | else lock = false; 161 | 162 | endspent(); 163 | 164 | return lock; 165 | 166 | } 167 | 168 | /** 169 | * Η συνάρτηση παρακολουθεί το gecos αν ξεπερνάει το μέγεθος των 256 bytes σε περίπτωση που το ξεπερνάει εμφανιζεται στην οθόνη το κατάλληλο μήνυμα λάθους 170 | * Επίσης ελέγχει για τους χαρακτήρες [, : = " \n] και σε περίπτωση που βρεθούν επιστρέφει -1 (κωδικό λάθους) 171 | */ 172 | 173 | int Users::check_gecos_string( char *gecos ) 174 | { 175 | int i, c; 176 | if ( strlen( gecos ) > MAX_FIELD_SIZE ) 177 | { 178 | QMessageBox::information( 0, tr( "User Manager" ), tr( "field is too long" ) ); 179 | return -1; 180 | } 181 | int p = strlen( gecos ); 182 | for ( i = 0; i < p; i++ ) 183 | { 184 | c = gecos[i]; 185 | if ( c == ',' || c == ':' || c == '=' || c == '"' || c == '\n' ) 186 | return -1; 187 | if ( iscntrl( c ) ) 188 | return -1; 189 | } 190 | return ( 0 ); 191 | } 192 | 193 | /** 194 | * Η συνάρτηση χρησιμοποιείται για να συνδεθούν τα δεδομένα της δομής finfo (που αφορά τη δημιουργία gecos)και τής εκάστοτε δομής passwd για περεταίρω επεξεργασία.Αυτο που γίνεται στη συνάρτηση είναι πως με τη σύνδεση της δομής finfo με την passwd αντιστοιχίζεται το gecos με τα δεδομένα της passwd του κάθε χρήστη. 195 | */ 196 | int Users::passwd_parse( struct passwd *pw, struct finfo *pinfo ) 197 | { 198 | char *gecos; 199 | char *cp; 200 | if ( pw ) 201 | { 202 | pinfo->pw = pw; 203 | pinfo->username = pw->pw_name; 204 | gecos = strdup( pw->pw_gecos ); 205 | cp = gecos; 206 | pinfo->full_name = cp; 207 | cp = strchr( cp, ',' ); 208 | if ( cp ) 209 | { 210 | *cp = 0, cp++; 211 | } 212 | else 213 | { 214 | return 2; 215 | } 216 | pinfo->office = cp; 217 | cp = strchr( cp, ',' ); 218 | 219 | if ( cp ) 220 | { 221 | *cp = 0, cp++; 222 | } 223 | else 224 | { 225 | return 3; 226 | } 227 | 228 | pinfo->office_phone = cp; 229 | cp = strchr( cp, ',' ); 230 | 231 | if ( cp ) 232 | { 233 | *cp = 0, cp++; 234 | } 235 | else 236 | return 4; 237 | pinfo->home_phone = cp; 238 | return 1; 239 | } 240 | return 0; 241 | } 242 | /** 243 | * Η συνάρτηση θέτει τις νέες εγγραφές newfn στις παλιές oldfn της δομής finfo η οποία τροποποιεί τα πεδία 244 | * της finfo που αφορούν τις πληροφορίες gecos 245 | */ 246 | bool Users::set_Gecos_Data( struct finfo *oldfn , struct finfo *newfn ) 247 | { 248 | bool changed = false; 249 | if ( newfn->full_name ) 250 | { 251 | oldfn->full_name = newfn->full_name; 252 | changed = true; 253 | } 254 | if ( newfn->office ) 255 | { 256 | oldfn->office = newfn->office; 257 | changed = true; 258 | } 259 | if ( newfn->office_phone ) 260 | { 261 | oldfn->office_phone = newfn->office_phone; 262 | changed = true; 263 | } 264 | if ( newfn->home_phone ) 265 | { 266 | oldfn->home_phone = newfn->home_phone; 267 | changed = true; 268 | } 269 | return changed; 270 | } 271 | /** 272 | * Διαγραφή ενός χρήστη εισάγοντας έναν NULL pointer στην δομή passwd και χρησιμοποιώντας την 273 | setpwnam.σαρώνοντας έναν έναν τους χρήστες στο αρχείο ωστε να βρεθεί η σωστη εγγραφή που θα πρέπει να διαγραφεί 274 | σε περίπτωση επιτυχούς κλήσης και διαγραφής η συνάρτηση επιστρέφει 0 και σε περίπτωση αποτυχιας -1 275 | */ 276 | int Users::rm_pwUser(QString name) 277 | { 278 | MyLibb lib; 279 | struct passwd *pw = NULL; 280 | char *nam = name.toLatin1().data(); 281 | if(lib.setpwnam_r(pw,nam)<0) 282 | return -1; 283 | else 284 | return 0; 285 | } 286 | 287 | /** 288 | * Η συνάρτηση χρησιμοποιείται για να αποθηκευτούν τα δεδομένα της δομής finfo στο αρχείο passwd. 289 | */ 290 | int Users::save_new_info (struct finfo *pinfo,uid_t uid,char *shellnew) 291 | { 292 | int len = 128; 293 | QString gec; 294 | QString emptystr = ""; 295 | if (!pinfo->full_name) pinfo->full_name = emptystr.toLatin1().data(); 296 | if (!pinfo->office) pinfo->office = emptystr.toLatin1().data(); 297 | if (!pinfo->office_phone) pinfo->office_phone = emptystr.toLatin1().data(); 298 | if (!pinfo->home_phone) pinfo->home_phone = emptystr.toLatin1().data(); 299 | /* create the new gecos string */ 300 | len =(strlen (pinfo->full_name) + strlen (pinfo->office) + strlen (pinfo->office_phone) + strlen (pinfo->home_phone) + 4); 301 | char *gecos =(char*)calloc(len, sizeof(char)); 302 | int fname = strlen(pinfo->full_name); 303 | 304 | if (pinfo->full_name == emptystr.toLatin1().data() && pinfo->office == emptystr.toLatin1().data() && pinfo->office_phone == emptystr.toLatin1().data() && pinfo->home_phone == emptystr.toLatin1().data()) 305 | strncpy(gecos, emptystr.toLatin1().data(), fname); 306 | 307 | else 308 | { 309 | 310 | if(strncmp(pinfo->full_name,emptystr.toLatin1().data(),fname) != 0) 311 | { 312 | gec = pinfo->full_name; 313 | } 314 | int officesize = sizeof(pinfo->office); 315 | if(strncmp(pinfo->office ,emptystr.toLatin1().data(), officesize) != 0) 316 | { 317 | gec ="" + gec + ","; 318 | gec = "" + gec + "" + pinfo->office + ""; 319 | } 320 | int pinfo_size = sizeof(pinfo->office_phone); 321 | if(strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) != 0) 322 | { 323 | int pinfo_office = sizeof(pinfo->office); 324 | if (strncmp(pinfo->office,emptystr.toLatin1().data(), pinfo_office) == 0 ) 325 | gec ="" + gec + ","; 326 | gec ="" + gec + ","; 327 | gec = "" + gec + "" + pinfo->office_phone + ""; 328 | } 329 | 330 | int ophone = sizeof(pinfo->office_phone); 331 | if(strncmp(pinfo->home_phone,emptystr.toLatin1().data(), ophone) != 0) 332 | { 333 | if (strncmp(pinfo->office_phone,emptystr.toLatin1().data(),ophone) == 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size)!= 0 )gec ="" + gec + ",,"; 334 | if (strncmp(pinfo->office_phone,emptystr.toLatin1().data(), ophone) != 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) == 0 )gec ="" + gec + ","; 335 | if (strncmp(pinfo->full_name,emptystr.toLatin1().data(), fname) == 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) == 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) == 0){gec ="" + gec + ",,,";} 336 | if (strncmp(pinfo->full_name,emptystr.toLatin1().data(), fname) != 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size)== 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) == 0){gec ="" + gec + ",,,";} 337 | if (strncmp(pinfo->full_name,emptystr.toLatin1().data(), fname) != 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) != 0 && strncmp(pinfo->office_phone,emptystr.toLatin1().data(),pinfo_size) != 0){gec ="" + gec + ",";} 338 | gec = "" + gec + "" + pinfo->home_phone + ""; 339 | } 340 | 341 | 342 | } 343 | sprintf(gecos, "%s",gec.toLatin1().data()); 344 | 345 | pinfo->pw->pw_gecos = gecos; 346 | pinfo->pw->pw_uid = uid; 347 | pinfo->pw->pw_shell = shellnew; 348 | MyLibb set; 349 | if(set.setpwnam (pinfo->pw) < 0) 350 | { 351 | if(gecos!=NULL) free( gecos ); 352 | return(-1); 353 | } 354 | else { 355 | if(gecos!=NULL) free( gecos ); 356 | } 357 | return 0; 358 | } 359 | /** 360 | * This function returns the size of a file. 361 | * for every regular file it counts the size and then adds the value copy it at the variable totalSize. 362 | * When the calculation ends the totalSize variable will end up having the total size of the current folder. 363 | * if There is a folder inside the current folder then the function is used retrospectively. 364 | * The retrospective behavior happens until there are no folders to calculate the size. 365 | */ 366 | uint64_t Users::getSize( char *dirname ) 367 | { 368 | DIR *dir; 369 | struct dirent *ent = NULL; 370 | struct stat st; 371 | char *path = (char*)calloc(PATH_MAX, sizeof(*path)); 372 | uint64_t totalsize = 0; 373 | 374 | if(!(dir = opendir(dirname))) 375 | { 376 | if (path != nullptr) { free(path); path =nullptr; } 377 | return totalsize; 378 | } 379 | 380 | while((ent = readdir(dir))) 381 | { 382 | if(!strncmp(ent->d_name, "..", (int)sizeof(ent->d_name)) || !strncmp(ent->d_name, ".",(int)sizeof(ent->d_name))) 383 | { 384 | continue; 385 | } 386 | 387 | sprintf(path, "%s%s", dirname, ent->d_name); 388 | 389 | if(lstat(path, &st) == -1) 390 | { 391 | printf("Couldn't stat %s: %s\n", path, strerror(errno)); 392 | continue; 393 | } 394 | 395 | if(S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) 396 | { 397 | uint64_t dirsize; 398 | strncat(path, "/", strlen(path)); 399 | dirsize = getSize(path); 400 | totalsize += dirsize; 401 | } 402 | else if(S_ISREG(st.st_mode)) 403 | { 404 | totalsize += st.st_size; 405 | } 406 | } 407 | 408 | if ( closedir(dir) < 0 ){ printf("Error closing file \n") ; } 409 | if (path != nullptr) { free(path); path =nullptr; } 410 | return totalsize; 411 | } 412 | /** 413 | * Η συνάρτηση μετράει τον αριθμό των χρηστών του συστήματος.Χρησιμοποιείται για να είναι ακριβής το ποσοστό ολοκλήρωσης της 414 | * progress bar που χρησιμοποιείται στον υπολογισμό του χώρου που καταλαμβάνουν οι χρήστες. 415 | */ 416 | int Users::countUsers( ) 417 | { 418 | struct passwd *users = NULL; 419 | int total=0; 420 | setpwent(); 421 | while (( users = getpwent() ) ) 422 | { 423 | total++; 424 | } 425 | endpwent(); 426 | 427 | return total; 428 | } 429 | /** 430 | * Ψάχνει να βρει την κύρια ομάδα ενός χρήστη.Παίρνει την δομή του χρήστη και βλέπει το πεδίο της δομής το οποίο αναφέρει την κύρια ομάδα.Με το GID που υπάρχει στο πεδίο αυτό κάνει αναζήτηση στις ομάδες του συστήματος και η ομάδα η οποία έχει ίδιο GID θεωρείται κύρια του χρήστη. 431 | */ 432 | QString Users::getPrimaryGroup(QString username) 433 | { 434 | 435 | struct group *group=NULL; 436 | struct passwd *user=NULL; 437 | QString primGroup; 438 | bool found=false; 439 | user=getpwnam(username.toLatin1().data()); 440 | 441 | setgrent(); 442 | while (( group = getgrent() )) 443 | { 444 | if (user->pw_gid==group->gr_gid) 445 | { 446 | primGroup.append(group->gr_name); 447 | found=true; 448 | } 449 | } 450 | if(!found) 451 | primGroup.append(""); 452 | 453 | endgrent(); 454 | return primGroup; 455 | 456 | } 457 | 458 | 459 | -------------------------------------------------------------------------------- /users.h: -------------------------------------------------------------------------------- 1 | #ifndef USERS_H 2 | #define USERS_H 3 | // 4 | #include "MainWindow.h" 5 | #include "userproperties.h" 6 | #include 7 | #include 8 | /** 9 | *Η κλάση περιέχει βασικές συναρτήσεις ελέγχου χρηστών,διαχωρισμού των πεδίων των λογαριασμών (όνομα,τηλέφωνο,διεύθυνση κτλ),καταμέτρηση χρηστών του συστήματος,έλεγχος κλειδώματος λογαριασμών,μέτρηση του χώρου που καταναλώνουν στον δίσκο,αναζήτηση χρηστών κτλ. 10 | */ 11 | class Users : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | Users(); 16 | ~Users(); 17 | static int check_gecos_string (char *gecos); 18 | bool set_Gecos_Data(struct finfo *oldfn , struct finfo *newfn ); 19 | int passwd_parse(struct passwd *pw,struct finfo *pinfo); 20 | int save_new_info(struct finfo *pinfo,uid_t uid,char *shellnew); 21 | bool isLocked(QString user); 22 | QString getUsersPrimaryGroup( QString UID ); 23 | QString getUsersSecondaryGroups( QString name ); 24 | bool userExists(QString name); 25 | int rm_pwUser(QString name); 26 | struct passwd *searchUser(); 27 | int countUsers(); 28 | 29 | public slots: 30 | uint64_t getSize(char *dirname); 31 | QString getPrimaryGroup(QString username); 32 | 33 | private: 34 | int rm_shUser(QString name); 35 | QString passhash; 36 | }; 37 | #endif 38 | --------------------------------------------------------------------------------