1 /*-
2  * Copyright (c) 2018 Marcel Kaiser. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24 
25 #include <QDesktopWidget>
26 #include <QTextCodec>
27 #include <QScreen>
28 #include <iostream>
29 
30 #include "mainwin.h"
31 #include "qt-helper/qt-helper.h"
32 
MainWin(const char * msg,const char * usr,const char * cmd,QWidget * parent)33 MainWin::MainWin(const char *msg, const char *usr, const char *cmd,
34 	QWidget *parent) : QMainWindow(parent) {
35 	this->cmd = cmd;
36 	this->usr = usr;
37 
38 	QString pstring	    = QString(tr("Please enter the password for " \
39 					 "user %1"));
40 	QString ustr	    = QString(usr == 0 ? "root" : usr);
41 	QString prompt	    = pstring.arg(ustr);
42 	QIcon okIcon	    = qh_loadStockIcon(QStyle::SP_DialogOkButton, 0);
43 	QIcon cancelIcon    = qh_loadStockIcon(QStyle::SP_DialogCancelButton,
44 					       NULL);
45 	QIcon pic	    = qh_loadIcon("dialog-password", NULL);
46 	pwdField	    = new QLineEdit(this);
47 	statusMsg	    = new QLabel(this);
48 	statusBar	    = new QStatusBar(this);
49 	QLabel	    *icon   = new QLabel(this);
50 	QLabel	    *text;
51 	QLabel	    *label  = new QLabel(prompt);
52 	QPushButton *ok	    = new QPushButton(okIcon, tr("&Ok"));
53 	QPushButton *cancel = new QPushButton(cancelIcon, tr("&Cancel"));
54 	QVBoxLayout *vbox   = new QVBoxLayout;
55 	QHBoxLayout *bbox   = new QHBoxLayout;
56 	QHBoxLayout *hbox   = new QHBoxLayout;
57 	QWidget *container  = new QWidget(this);
58 
59 	if (msg == 0 || *msg == '\0') {
60 		text = new QLabel(QString(tr("Execute '%1' as user %2\n")
61 				  .arg(QString(cmd)).arg(ustr)));
62 	} else
63 		text = new QLabel(QString(msg).append("\n"));
64 	icon->setPixmap(pic.pixmap(64));
65 	text->setWordWrap(true);
66 	pwdField->setEchoMode(QLineEdit::Password);
67 	label->setStyleSheet("font-weight: bold;");
68 	ok->setDefault(true);
69 	cancel->setDefault(true);
70 
71 	bbox->addWidget(ok,     1, Qt::AlignRight);
72         bbox->addWidget(cancel, 0, Qt::AlignRight);
73 
74 	hbox->addWidget(icon,   0, Qt::AlignLeft);
75 	hbox->addWidget(text,   1, Qt::AlignJustify);
76 	vbox->addLayout(hbox);
77 	vbox->addWidget(label,  1, Qt::AlignLeft);
78 
79 	vbox->addWidget(pwdField);
80 	vbox->addWidget(statusMsg);
81 	vbox->addLayout(bbox);
82 	container->setLayout(vbox);
83 	setCentralWidget(container);
84 
85 	setMinimumWidth(500);
86 	setMaximumWidth(500);
87 	setWindowIcon(pic);
88 	setWindowTitle("DSBSu");
89 	show();
90 	setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,
91 	    size(), qApp->primaryScreen()->geometry()));
92 	connect(ok, SIGNAL(clicked()), this, SLOT(callBackend()));
93 	connect(pwdField, SIGNAL(returnPressed()), this, SLOT(callBackend()));
94 	connect(cancel, SIGNAL(clicked()), this, SLOT(cbCancel()));
95 	connect(pwdField, SIGNAL(textChanged(const QString &)), this,
96 	    SLOT(resetStatusBar(const QString &)));
97 }
98 
MainWin(const char * cmd,const char * usr,QWidget * parent)99 MainWin::MainWin(const char *cmd, const char *usr, QWidget *parent)
100 	: QMainWindow(parent) {
101 	this->usr = usr;
102 
103 	QString pstring	    = QString(tr("Please enter the password for " \
104 					 "user %1"));
105 	QString ustr	    = QString(usr == 0 ? "root" : usr);
106 	QString prompt	    = pstring.arg(ustr);
107 	QIcon okIcon	    = qh_loadStockIcon(QStyle::SP_DialogOkButton, 0);
108 	QIcon cancelIcon    = qh_loadStockIcon(QStyle::SP_DialogCancelButton,
109 					       NULL);
110 	QIcon pic	    = qh_loadIcon("dialog-password", NULL);
111 	pwdField	    = new QLineEdit(this);
112 	statusMsg	    = new QLabel(this);
113 	statusBar	    = new QStatusBar(this);
114 	QLabel	    *icon   = new QLabel(this);
115 	QLabel	    *text;
116 	QLabel	    *label  = new QLabel(prompt);
117 	QPushButton *ok	    = new QPushButton(okIcon, tr("&Ok"));
118 	QPushButton *cancel = new QPushButton(cancelIcon, tr("&Cancel"));
119 	QVBoxLayout *vbox   = new QVBoxLayout;
120 	QHBoxLayout *bbox   = new QHBoxLayout;
121 	QHBoxLayout *hbox   = new QHBoxLayout;
122 	QWidget *container  = new QWidget(this);
123 
124 	text = new QLabel(tr("<qt>The command \"<tt>%1</tt>\" " \
125 			     "requires authentication\n</qt>").arg(cmd));
126 	icon->setPixmap(pic.pixmap(64));
127 	pwdField->setEchoMode(QLineEdit::Password);
128 	label->setStyleSheet("font-weight: bold;");
129 	ok->setDefault(true);
130 	cancel->setDefault(true);
131 
132 	bbox->addWidget(ok,     1, Qt::AlignRight);
133         bbox->addWidget(cancel, 0, Qt::AlignRight);
134 
135 	hbox->addWidget(icon,   0, Qt::AlignLeft);
136 	hbox->addWidget(text,   1, Qt::AlignLeft);
137 	vbox->addLayout(hbox);
138 	vbox->addWidget(label,  1, Qt::AlignLeft);
139 
140 	vbox->addWidget(pwdField);
141 	vbox->addWidget(statusMsg);
142 	vbox->addLayout(bbox);
143 	container->setLayout(vbox);
144 	setCentralWidget(container);
145 
146 	setMinimumWidth(500);
147 	setWindowIcon(pic);
148 	setWindowTitle("DSBSu");
149 	show();
150 	setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,
151 	    size(), qApp->primaryScreen()->geometry()));
152 	connect(ok, SIGNAL(clicked()), this, SLOT(printPwd()));
153 	connect(pwdField, SIGNAL(returnPressed()), this, SLOT(printPwd()));
154 	connect(cancel, SIGNAL(clicked()), this, SLOT(cbCancel()));
155 	connect(pwdField, SIGNAL(textChanged(const QString &)), this,
156 	    SLOT(resetStatusBar(const QString &)));
157 }
158 
159 void
printPwd()160 MainWin::printPwd()
161 {
162 	QTextCodec *codec = QTextCodec::codecForLocale();
163 	QByteArray encstr = codec->fromUnicode(pwdField->text());
164 
165 	std::cout << encstr.data() << std::endl;
166 	QCoreApplication::exit(0);
167 }
168 
169 void
resetStatusBar(const QString &)170 MainWin::resetStatusBar(const QString & /*unused*/)
171 {
172 	statusMsg->setText("");
173 }
174 
175 void
callBackend()176 MainWin::callBackend()
177 {
178 	QTextCodec *codec = QTextCodec::codecForLocale();
179 	QByteArray encstr = codec->fromUnicode(pwdField->text());
180 
181 	if ((proc = dsbsu_exec_su(cmd, usr, encstr.data())) == NULL) {
182 		if (dsbsu_error() == DSBSU_EAUTH) {
183 			pwdField->clear();
184 			statusMsg->setText(tr("Wrong password"));
185 		} else {
186 			close();
187 			QCoreApplication::exit(1);
188 		}
189 	} else {
190 		close();
191 		QCoreApplication::exit(0);
192 	}
193 }
194 
195 void
cbCancel()196 MainWin::cbCancel()
197 {
198 	QCoreApplication::exit(-1);
199 }
200 
closeEvent(QCloseEvent *)201 void MainWin::closeEvent(QCloseEvent * /* unused */)
202 {
203 	QCoreApplication::exit(-1);
204 }
205 
206