summaryrefslogtreecommitdiffstats
path: root/kppp/runtests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kppp/runtests.cpp')
-rw-r--r--kppp/runtests.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/kppp/runtests.cpp b/kppp/runtests.cpp
new file mode 100644
index 00000000..63fa0794
--- /dev/null
+++ b/kppp/runtests.cpp
@@ -0,0 +1,278 @@
+/*
+ * kPPP: A pppd front end for the KDE project
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997 Bernd Johannes Wuebben
+ * wuebben@math.cornell.edu
+ *
+ * This file was contributed by Mario Weilguni <mweilguni@sime.com>
+ * Thanks Mario !
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <qdir.h>
+#include "runtests.h"
+#include <ctype.h>
+#include <unistd.h>
+#include <kmessagebox.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <netinet/in.h>
+
+#ifdef HAVE_RESOLV_H
+#include <arpa/nameser.h>
+#include <resolv.h>
+#endif
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF "/etc/resolv.conf"
+#endif
+
+#include <klocale.h>
+#include "pppdata.h"
+
+// initial effective uid (main.cpp)
+extern uid_t euid;
+
+// secure pppd location (opener.cpp)
+extern const char* pppdPath();
+
+// shamelessly stolen from pppd-2.3.5
+/********************************************************************
+ *
+ * Internal routine to decode the version.modification.patch level
+ */
+
+static void decode_version (const char *_buf, int *version,
+ int *modification, int *patch)
+ {
+ char *buffer = qstrdup(_buf);
+ char *buf = buffer;
+ *version = (int) strtoul (buf, &buf, 10);
+ *modification = 0;
+ *patch = 0;
+
+ if (*buf == '.')
+ {
+ ++buf;
+ *modification = (int) strtoul (buf, &buf, 10);
+ if (*buf == '.')
+ {
+ ++buf;
+ *patch = (int) strtoul (buf, &buf, 10);
+ }
+ }
+
+ if (*buf != '\0')
+ {
+ *version =
+ *modification =
+ *patch = 0;
+ }
+
+ delete [] buffer;
+ }
+
+
+void pppdVersion(int *version, int *modification, int *patch) {
+ char buffer[30];
+ const char *pppd;
+ char *query;
+
+ *version = *modification = *patch = 0;
+
+ // locate pppd
+ if(!(pppd = pppdPath()))
+ return;
+
+ // call pppd with --version option
+ if(!(query = new char[strlen(pppd)+25]))
+ return;
+ strcpy(query, pppd);
+ // had to add a dummy device to prevent a "no device specified
+ // and stdin is not a tty" error from newer pppd versions.
+ strcat(query, " --version /dev/tty 2>&1");
+ fflush(0L);
+ FILE *output = popen(query, "r");
+ delete [] query;
+ if(!output)
+ return;
+
+ // read output
+ int size = fread(buffer, sizeof(char), 29, output);
+
+ if(ferror(output)) {
+ pclose(output);
+ return;
+ }
+ pclose(output);
+ buffer[size] = '\0';
+
+ // find position of version number x.y.z
+ char *p = buffer;
+ while(*p && !isdigit(*p))
+ p++;
+ if (*p == 0)
+ return;
+ char *p2 = p;
+ while(*p2 == '.' || isdigit(*p2))
+ p2++;
+ *p2 = '\0';
+
+ decode_version(p, version, modification, patch);
+}
+
+
+int uidFromName(const char *uname) {
+ struct passwd *pw;
+
+ setpwent();
+ while((pw = getpwent()) != NULL) {
+ if(strcmp(uname, pw->pw_name) == 0) {
+ int uid = pw->pw_uid;
+ endpwent();
+ return uid;
+ }
+ }
+
+ endpwent();
+ return -1;
+}
+
+
+const char *homedirFromUid(uid_t uid) {
+ struct passwd *pw;
+ char *d = 0;
+
+ setpwent();
+ while((pw = getpwent()) != NULL) {
+ if(pw->pw_uid == uid) {
+ d = strdup(pw->pw_dir);
+ endpwent();
+ return d;
+ }
+ }
+
+ endpwent();
+ return d;
+}
+
+
+const char* getHomeDir() {
+ static const char *hd = 0;
+ static bool ranTest = false;
+ if(!ranTest) {
+ hd = homedirFromUid(getuid());
+ ranTest = true;
+ }
+
+ return hd;
+}
+
+
+int runTests() {
+ int warning = 0;
+
+ // Test pre-1: check if the user is allowed to dial-out
+ if(access("/etc/kppp.allow", R_OK) == 0 && getuid() != 0) {
+ bool access = FALSE;
+ FILE *f;
+ if((f = fopen("/etc/kppp.allow", "r")) != NULL) {
+ char buf[2048]; // safe
+ while(f != NULL && !feof(f)) {
+ if(fgets(buf, sizeof(buf), f) != NULL) {
+ QString s(buf);
+
+ s = s.stripWhiteSpace();
+ if(s[0] == '#' || s.length() == 0)
+ continue;
+
+ if((uid_t)uidFromName(QFile::encodeName(s)) == getuid()) {
+ access = TRUE;
+ fclose(f);
+ f = NULL;
+ }
+ }
+ }
+ if(f)
+ fclose(f);
+ }
+
+ if(!access) {
+ KMessageBox::error(0,
+ i18n("You're not allowed to dial out with "
+ "kppp.\nContact your system administrator."));
+ return TEST_CRITICAL;
+ }
+ }
+
+ // Test 1: search the pppd binary
+ const char *f = pppdPath();
+
+ if(!f) {
+ KMessageBox::error(0,
+ i18n("Cannot find the PPP daemon!\n"
+ "Make sure that pppd is installed."));
+ warning++;
+ }
+
+ // Test 2: check access to the pppd binary
+ if(f) {
+#if 0
+ if(access(f, X_OK) != 0 /* && geteuid() != 0 */) {
+ KMessageBox::error(0,
+ i18n("You do not have the permission "
+ "to start pppd!\n"
+ "Contact your system administrator "
+ "and ask to get access to pppd."));
+ return TEST_CRITICAL;
+ }
+#endif
+
+ if(euid != 0) {
+ struct stat st;
+ stat(f, &st);
+ if(st.st_uid != 0 || (st.st_mode & S_ISUID) == 0) {
+ KMessageBox::error(0,
+ i18n("You don't have sufficient permission to run\n"
+ "%1\n"
+ "Please make sure that kppp is owned by root "
+ "and has the SUID bit set.").arg(f));
+ warning++;
+ }
+ }
+ }
+
+ // Test 5: check for existence of /etc/resolv.conf
+ if (access(_PATH_RESCONF, R_OK) != 0) {
+ QString file = _PATH_RESCONF" ";
+ QString msgstr = i18n("%1 is missing or can't be read!\n"
+ "Ask your system administrator to create "
+ "this file (can be empty) with appropriate "
+ "read and write permissions.").arg(file);
+ KMessageBox::error(0, msgstr);
+ warning ++;
+ }
+
+ if(warning == 0)
+ return TEST_OK;
+ else
+ return TEST_WARNING;
+}
+