File indexing completed on 2025-02-02 14:11:33
0001 /* 0002 This file is part of the KDE project, module kdesu. 0003 SPDX-FileCopyrightText: 1999, 2000 Geert Jansen <jansen@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-only 0006 0007 stubprocess.cpp: Conversation with kdesu_stub. 0008 */ 0009 0010 #include "stubprocess.h" 0011 #include "kcookie_p.h" 0012 #include "stubprocess_p.h" 0013 0014 #include <config-kdesu.h> 0015 #include <ksu_debug.h> 0016 0017 #include <unistd.h> 0018 0019 extern int kdesuDebugArea(); 0020 0021 namespace KDESu 0022 { 0023 using namespace KDESuPrivate; 0024 0025 StubProcess::StubProcess() 0026 : StubProcess(*new StubProcessPrivate) 0027 { 0028 } 0029 0030 StubProcess::StubProcess(StubProcessPrivate &dd) 0031 : PtyProcess(dd) 0032 { 0033 m_user = "root"; 0034 m_scheduler = SchedNormal; 0035 m_priority = 50; 0036 m_cookie = new KCookie; 0037 m_XOnly = true; 0038 } 0039 0040 StubProcess::~StubProcess() 0041 { 0042 delete m_cookie; 0043 } 0044 0045 void StubProcess::setCommand(const QByteArray &command) 0046 { 0047 m_command = command; 0048 } 0049 0050 void StubProcess::setUser(const QByteArray &user) 0051 { 0052 m_user = user; 0053 } 0054 0055 void StubProcess::setXOnly(bool xonly) 0056 { 0057 m_XOnly = xonly; 0058 } 0059 0060 void StubProcess::setPriority(int prio) 0061 { 0062 if (prio > 100) { 0063 m_priority = 100; 0064 } else if (prio < 0) { 0065 m_priority = 0; 0066 } else { 0067 m_priority = prio; 0068 } 0069 } 0070 0071 void StubProcess::setScheduler(int sched) 0072 { 0073 m_scheduler = sched; 0074 } 0075 0076 void StubProcess::writeString(const QByteArray &str) 0077 { 0078 QByteArray out; 0079 out.reserve(str.size() + 8); 0080 for (const uchar c : str) { 0081 if (c < 32) { 0082 out.append('\\'); 0083 out.append(c + '@'); 0084 } else if (c == '\\') { 0085 out.append('\\'); 0086 out.append('/'); 0087 } else { 0088 out.append(c); 0089 } 0090 } 0091 writeLine(out); 0092 } 0093 0094 /* 0095 * Map pid_t to a signed integer type that makes sense for QByteArray; 0096 * only the most common sizes 16 bit and 32 bit are special-cased. 0097 */ 0098 template<int T> 0099 struct PIDType { 0100 typedef pid_t PID_t; 0101 }; 0102 template<> 0103 struct PIDType<2> { 0104 typedef qint16 PID_t; 0105 }; 0106 template<> 0107 struct PIDType<4> { 0108 typedef qint32 PID_t; 0109 }; 0110 0111 /* 0112 * Conversation with kdesu_stub. This is how we pass the authentication 0113 * tokens (X11) and other stuff to kdesu_stub. 0114 * return values: -1 = error, 0 = ok, 1 = kill me 0115 */ 0116 0117 int StubProcess::converseStub(int check) 0118 { 0119 QByteArray line; 0120 QByteArray tmp; 0121 0122 while (1) { 0123 line = readLine(); 0124 if (line.isNull()) { 0125 return -1; 0126 } 0127 0128 if (line == "kdesu_stub") { 0129 // This makes parsing a lot easier. 0130 enableLocalEcho(false); 0131 if (check) { 0132 writeLine("stop"); 0133 } else { 0134 writeLine("ok"); 0135 } 0136 break; 0137 } 0138 } 0139 0140 while (1) { 0141 line = readLine(); 0142 if (line.isNull()) { 0143 return -1; 0144 } 0145 0146 if (line == "display") { 0147 writeLine(display()); 0148 } else if (line == "display_auth") { 0149 #if HAVE_X11 0150 writeLine(displayAuth()); 0151 #else 0152 writeLine(""); 0153 #endif 0154 } else if (line == "command") { 0155 writeString(m_command); 0156 } else if (line == "path") { 0157 QByteArray path = qgetenv("PATH"); 0158 if (!path.isEmpty() && path[0] == ':') { 0159 path = path.mid(1); 0160 } 0161 if (m_user == "root") { 0162 if (!path.isEmpty()) { 0163 path = "/sbin:/bin:/usr/sbin:/usr/bin:" + path; 0164 } else { 0165 path = "/sbin:/bin:/usr/sbin:/usr/bin"; 0166 } 0167 } 0168 writeLine(path); 0169 } else if (line == "user") { 0170 writeLine(m_user); 0171 } else if (line == "priority") { 0172 tmp.setNum(m_priority); 0173 writeLine(tmp); 0174 } else if (line == "scheduler") { 0175 if (m_scheduler == SchedRealtime) { 0176 writeLine("realtime"); 0177 } else { 0178 writeLine("normal"); 0179 } 0180 } else if (line == "xwindows_only") { 0181 if (m_XOnly) { 0182 writeLine("no"); 0183 } else { 0184 writeLine("yes"); 0185 } 0186 } else if (line == "app_startup_id") { 0187 const QList<QByteArray> env = environment(); 0188 QByteArray tmp; 0189 static const char startup_env[] = "DESKTOP_STARTUP_ID="; 0190 static const std::size_t size = sizeof(startup_env); 0191 for (const auto &var : env) { 0192 if (var.startsWith(startup_env)) { 0193 tmp = var.mid(size - 1); 0194 } 0195 } 0196 if (tmp.isEmpty()) { 0197 tmp = "0"; // krazy:exclude=doublequote_chars 0198 } 0199 writeLine(tmp); 0200 } else if (line == "app_start_pid") { // obsolete 0201 // Force the pid_t returned from getpid() into 0202 // something QByteArray understands; avoids ambiguity 0203 // between short and unsigned short in particular. 0204 tmp.setNum((PIDType<sizeof(pid_t)>::PID_t)(getpid())); 0205 writeLine(tmp); 0206 } else if (line == "environment") { // additional env vars 0207 const QList<QByteArray> env = environment(); 0208 for (const auto &var : env) { 0209 writeString(var); 0210 } 0211 writeLine(""); 0212 } else if (line == "end") { 0213 return 0; 0214 } else { 0215 qCWarning(KSU_LOG) << "[" << __FILE__ << ":" << __LINE__ << "] " 0216 << "Unknown request:" << line; 0217 return 1; 0218 } 0219 } 0220 0221 return 0; 0222 } 0223 0224 QByteArray StubProcess::display() 0225 { 0226 return m_cookie->display(); 0227 } 0228 0229 QByteArray StubProcess::displayAuth() 0230 { 0231 #if HAVE_X11 0232 return m_cookie->displayAuth(); 0233 #else 0234 return QByteArray(); 0235 #endif 0236 } 0237 0238 void StubProcess::virtual_hook(int id, void *data) 0239 { 0240 PtyProcess::virtual_hook(id, data); 0241 } 0242 0243 } // namespace KDESu