File indexing completed on 2024-05-05 05:48:31
0001 /* 0002 -------------------------------------------------------------------- 0003 CT Host Implementation 0004 -------------------------------------------------------------------- 0005 SPDX-FileCopyrightText: 1999 Gary Meyer <gary@meyer.net> 0006 -------------------------------------------------------------------- 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "cthost.h" 0011 0012 #include <pwd.h> 0013 #include <sys/types.h> 0014 #include <unistd.h> // getuid() 0015 0016 #include <QFile> 0017 #include <QTextStream> 0018 0019 #include <KLocalizedString> 0020 0021 #include "crontabWidget.h" 0022 0023 #include "ctInitializationError.h" 0024 #include "ctSystemCron.h" 0025 #include "ctcron.h" 0026 0027 #include "kcm_cron_debug.h" 0028 0029 CTHost::CTHost(const QString &cronBinary, CTInitializationError &ctInitializationError) 0030 { 0031 struct passwd *userInfos = nullptr; 0032 0033 mCrontabBinary = cronBinary; 0034 0035 // If it is the root user 0036 if (getuid() == 0) { 0037 // Read /etc/passwd 0038 setpwent(); // restart 0039 while ((userInfos = getpwent())) { 0040 if (allowDeny(userInfos->pw_name)) { 0041 const QString errorMessage = createCTCron(userInfos); 0042 if (!errorMessage.isEmpty()) { 0043 ctInitializationError.setErrorMessage(errorMessage); 0044 return; 0045 } 0046 } 0047 // delete userInfos; 0048 } 0049 setpwent(); // restart again for others 0050 } 0051 // Non-root user, so just create user's cron table. 0052 else { 0053 // Get name from UID, check it against AllowDeny() 0054 unsigned int uid = getuid(); 0055 setpwent(); // restart 0056 while ((userInfos = getpwent())) { 0057 if ((userInfos->pw_uid == uid) && (!allowDeny(userInfos->pw_name))) { 0058 ctInitializationError.setErrorMessage( 0059 i18n("You have been blocked from using KCron\ 0060 by either the /etc/cron.allow file or the /etc/cron.deny file.\ 0061 \n\nCheck the crontab man page for further details.")); 0062 0063 return; 0064 } 0065 // delete userInfos; 0066 } 0067 0068 setpwent(); // restart again for others 0069 0070 passwd *currentUserPassword = getpwuid(uid); 0071 0072 const QString errorMessage = createCTCron(currentUserPassword); 0073 if (!errorMessage.isEmpty()) { 0074 ctInitializationError.setErrorMessage(errorMessage); 0075 return; 0076 } 0077 0078 // delete currentUserPassword; 0079 } 0080 // Create the system cron table. 0081 createSystemCron(); 0082 } 0083 0084 CTHost::~CTHost() 0085 { 0086 qDeleteAll(mCrons); 0087 } 0088 0089 bool CTHost::allowDeny(char *name) 0090 { 0091 QFile allow(QStringLiteral("/etc/cron.allow")); 0092 0093 // if cron.allow exists make sure user is listed 0094 if (allow.open(QFile::ReadOnly)) { 0095 QTextStream stream(&allow); 0096 while (!stream.atEnd()) { 0097 if (stream.readLine() == QLatin1String(name)) { 0098 allow.close(); 0099 return true; 0100 } 0101 } 0102 allow.close(); 0103 return false; 0104 } else { 0105 allow.close(); 0106 QFile deny(QStringLiteral("/etc/cron.deny")); 0107 0108 // else if cron.deny exists make sure user is not listed 0109 if (deny.open(QFile::ReadOnly)) { 0110 QTextStream stream(&deny); 0111 while (!stream.atEnd()) { 0112 if (stream.readLine() == QLatin1String(name)) { 0113 deny.close(); 0114 return false; 0115 } 0116 } 0117 deny.close(); 0118 return true; 0119 } else { 0120 deny.close(); 0121 return true; 0122 } 0123 } 0124 } 0125 0126 CTSaveStatus CTHost::save(CrontabWidget *mCrontabWidget) 0127 { 0128 qCDebug(KCM_CRON_LOG) << "Save current cron."; 0129 // Retrieve the current cron to use. This could either be a user cron or a system cron. 0130 // Implements system cron entry point. 0131 CTCron *ctCron = mCrontabWidget->currentCron(); 0132 0133 return ctCron->save(); 0134 } 0135 0136 void CTHost::cancel() 0137 { 0138 for (CTCron *ctCron : std::as_const(mCrons)) { 0139 ctCron->cancel(); 0140 } 0141 } 0142 0143 bool CTHost::isDirty() 0144 { 0145 bool isDirty = false; 0146 0147 for (CTCron *ctCron : std::as_const(mCrons)) { 0148 if (ctCron->isDirty()) { 0149 isDirty = true; 0150 } 0151 } 0152 0153 return isDirty; 0154 } 0155 0156 CTCron *CTHost::createSystemCron() 0157 { 0158 CTCron *p = new CTSystemCron(mCrontabBinary); 0159 0160 mCrons.append(p); 0161 0162 return p; 0163 } 0164 0165 QString CTHost::createCTCron(const struct passwd *userInfos) 0166 { 0167 bool currentUserCron = false; 0168 if (userInfos->pw_uid == getuid()) { 0169 currentUserCron = true; 0170 } 0171 0172 CTInitializationError ctInitializationError; 0173 auto p = new CTCron(mCrontabBinary, userInfos, currentUserCron, ctInitializationError); 0174 if (ctInitializationError.hasErrorMessage()) { 0175 delete p; 0176 return ctInitializationError.errorMessage(); 0177 } 0178 0179 mCrons.append(p); 0180 0181 return QString(); 0182 } 0183 0184 CTCron *CTHost::findCurrentUserCron() const 0185 { 0186 // Because multiple users may exist, return only the currently logged in user's cron in user cron mode. 0187 for (CTCron *ctCron : std::as_const(mCrons)) { 0188 if (ctCron->isCurrentUserCron()) { 0189 return ctCron; 0190 } 0191 } 0192 0193 qCDebug(KCM_CRON_LOG) << "Unable to find the current user Cron. Please report this bug and your crontab config to the developers."; 0194 return nullptr; 0195 } 0196 0197 CTCron *CTHost::findSystemCron() const 0198 { 0199 // Return the cron belonging to root. 0200 for (CTCron *ctCron : std::as_const(mCrons)) { 0201 if (ctCron->isMultiUserCron()) { 0202 return ctCron; 0203 } 0204 } 0205 0206 qCDebug(KCM_CRON_LOG) << "Unable to find the system Cron. Please report this bug and your crontab config to the developers."; 0207 return nullptr; 0208 } 0209 0210 CTCron *CTHost::findUserCron(const QString &userLogin) const 0211 { 0212 for (CTCron *ctCron : std::as_const(mCrons)) { 0213 if (ctCron->userLogin() == userLogin) { 0214 return ctCron; 0215 } 0216 } 0217 0218 qCDebug(KCM_CRON_LOG) << "Unable to find the user Cron " << userLogin << ". Please report this bug and your crontab config to the developers."; 0219 return nullptr; 0220 } 0221 0222 CTCron *CTHost::findCronContaining(CTTask *ctTask) const 0223 { 0224 for (CTCron *ctCron : std::as_const(mCrons)) { 0225 if (ctCron->tasks().contains(ctTask)) { 0226 return ctCron; 0227 } 0228 } 0229 0230 qCDebug(KCM_CRON_LOG) << "Unable to find the cron of this task. Please report this bug and your crontab config to the developers."; 0231 return nullptr; 0232 } 0233 0234 CTCron *CTHost::findCronContaining(CTVariable *ctVariable) const 0235 { 0236 for (CTCron *ctCron : std::as_const(mCrons)) { 0237 if (ctCron->variables().contains(ctVariable)) { 0238 return ctCron; 0239 } 0240 } 0241 0242 qCDebug(KCM_CRON_LOG) << "Unable to find the cron of this variable. Please report this bug and your crontab config to the developers."; 0243 return nullptr; 0244 }