⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrapper.c

📁 linux下的拨号程序rp-pppoe.3.7
💻 C
字号:
/* -*-Mode: C;-*- *//************************************************************************* wrapper.c** C wrapper designed to run SUID root for controlling PPPoE connections.** Copyright (C) 2005 by Roaring Penguin Software Inc.** LIC: GPL** This program may be distributed under the terms of the GNU General* Public License, Version 2, or (at your option) any later version.***********************************************************************/static char const RCSID[] ="$Id: wrapper.c,v 1.10 2005/08/09 02:49:15 dfs Exp $";#define _SVID_SOURCE 1 /* For putenv */#define _POSIX_SOURCE 1 /* For fileno */#define _BSD_SOURCE 1 /* For setreuid */#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <sys/stat.h>#include <unistd.h>#define CONN_NAME_LEN 64#define LINELEN 512static char const *pppoe_start = PPPOE_START_PATH;static char const *pppoe_stop = PPPOE_STOP_PATH;static char const *pppoe_status = PPPOE_STATUS_PATH;/********************************************************************** *%FUNCTION: PathOK *%ARGUMENTS: * fname -- a file name. *%RETURNS: * 1 if path to fname is secure; 0 otherwise. *%DESCRIPTION: * Makes sure ownership/permissions of file and parent directories * are safe. **********************************************************************/static intPathOK(char const *fname){    char path[LINELEN];    struct stat buf;    char const *slash;    if (strlen(fname) > LINELEN) {	fprintf(stderr, "Pathname '%s' too long\n", fname);	return 0;    }    /* Must be absolute path */    if (*fname != '/') {	fprintf(stderr, "Unsafe path '%s' not absolute\n", fname);	return 0;    }    /* Check root directory */    if (stat("/", &buf) < 0) {	perror("stat");	return 0;    }    if (buf.st_uid) {	fprintf(stderr, "SECURITY ALERT: Root directory (/) not owned by root\n");	return 0;    }    if (buf.st_mode & (S_IWGRP | S_IWOTH)) {	fprintf(stderr, "SECURITY ALERT: Root directory (/) writable by group or other\n");	return 0;    }    /* Check each component */    slash = fname;    while(*slash) {	slash = strchr(slash+1, '/');	if (!slash) {	    slash = fname + strlen(fname);	}	memcpy(path, fname, slash-fname);	path[slash-fname] = 0;	if (stat(path, &buf) < 0) {	    perror("stat");	    return 0;	}	if (buf.st_uid) {	    fprintf(stderr, "SECURITY ALERT: '%s' not owned by root\n", path);	    return 0;	}	if (buf.st_mode & (S_IWGRP | S_IWOTH)) {	    fprintf(stderr, "SECURITY ALERT: '%s' writable by group or other\n",		    path);	    return 0;	}    }    return 1;}/********************************************************************** *%FUNCTION: CleanEnvironment *%ARGUMENTS: * envp -- environment passed to main *%RETURNS: * Nothing *%DESCRIPTION: * Deletes all environment variables; makes safe environment **********************************************************************/static voidCleanEnvironment(char *envp[]){    envp[0] = NULL;    putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin");}/********************************************************************** *%FUNCTION: main *%ARGUMENTS: * argc, argv -- usual suspects * Usage: pppoe-wrapper {start|stop|status} {connection_name} *%RETURNS: * Whatever pppoe-start, pppoe-stop or pppoe-status returns. *%DESCRIPTION: * Runs pppoe-start, pppoe-stop or pppoe-status on given connection if * non-root users are allowed to do it. **********************************************************************/intmain(int argc, char *argv[]){    int amRoot;    char *cp;    char fname[64+CONN_NAME_LEN];    char line[LINELEN+1];    int allowed = 0;    FILE *fp;    extern char **environ;    /* Clean out environment */    CleanEnvironment(environ);        /* Are we root? */    amRoot = (getuid() == 0);    /* Validate arguments */    if (argc != 3) {	fprintf(stderr, "Usage: %s {start|stop|status} connection_name\n",		argv[0]);	exit(1);    }    if (strcmp(argv[1], "start") &&	strcmp(argv[1], "stop") &&	strcmp(argv[1], "status")) {	fprintf(stderr, "Usage: %s {start|stop|status} connection_name\n",		argv[0]);	exit(1);    }    /* Connection name can be at most CONN_NAME_LEN chars; alpha, num, underscore */    if (strlen(argv[2]) > CONN_NAME_LEN) {	fprintf(stderr, "%s: Connection name '%s' too long.\n",		argv[0], argv[2]);	exit(1);    }    for (cp = argv[2]; *cp; cp++) {	if (!strchr("abcdefghijklmnopqrstuvwxyz"		    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"		    "0123456789_-", *cp)) {	    fprintf(stderr, "%s: Connection name '%s' contains illegal character '%c'\n", argv[0], argv[2], *cp);	    exit(1);	}    }    /* Open the connection file */    sprintf(fname, "/etc/ppp/rp-pppoe-gui/conf.%s", argv[2]);    /* Check path sanity */    if (!PathOK(fname)) {	exit(1);    }    fp = fopen(fname, "r");    if (!fp) {	fprintf(stderr, "%s: Could not open '%s': %s\n",		argv[0], fname, strerror(errno));	exit(1);    }    /* Check if non-root users can control it */    if (amRoot) {	allowed = 1;    } else {	while (!feof(fp)) {	    if (!fgets(line, LINELEN, fp)) {		break;	    }	    if (!strcmp(line, "NONROOT=OK\n")) {		allowed = 1;		break;	    }	}    }    fclose(fp);    if (!allowed) {	fprintf(stderr, "%s: Non-root users are not permitted to control connection '%s'\n", argv[0], argv[2]);	exit(1);    }    /* Become root with setuid() to defeat is-root checks in shell scripts */    if (setreuid(0, 0) < 0) {	perror("setreuid");	exit(1);    }           /* It's OK -- do it.  */    if (!strcmp(argv[1], "start")) {	if (!PathOK(pppoe_start)) exit(1);	execl(pppoe_start, "pppoe-start", fname, NULL);    } else if (!strcmp(argv[1], "stop")) {	if (!PathOK(pppoe_stop)) exit(1);	execl(pppoe_stop, "pppoe-stop", fname, NULL);    } else {	if (!PathOK(pppoe_status)) exit(1);	execl(pppoe_status, "pppoe-status", fname, NULL);    }    fprintf(stderr, "%s: execl: %s\n", argv[0], strerror(errno));    exit(1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -