You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
6.2 KiB
279 lines
6.2 KiB
/*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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;
|
|
}
|
|
|