📄 misc.c
字号:
/* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2002-2004 James Yonan <jim@yonan.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef WIN32#include "config-win32.h"#else#include "config.h"#endif#include "syshead.h"#include "buffer.h"#include "misc.h"#include "tun.h"#include "error.h"#include "thread.h"#include "otime.h"#include "memdbg.h"/* Redefine the top level directory of the filesystem to restrict access to files for security */voiddo_chroot (const char *path){ if (path) {#ifdef HAVE_CHROOT const char *top = "/"; if (chroot (path)) msg (M_ERR, "chroot to '%s' failed", path); if (openvpn_chdir (top)) msg (M_ERR, "cd to '%s' failed", top); msg (M_INFO, "chroot to '%s' and cd to '%s' succeeded", path, top);#else msg (M_FATAL, "Sorry but I can't chroot to '%s' because this operating system doesn't appear to support the chroot() system call", path);#endif }}/* Get/Set UID of process */voidget_user (const char *username, struct user_state *state){ CLEAR (*state); if (username) {#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID) state->pw = getpwnam (username); if (!state->pw) msg (M_ERR, "failed to find UID for user %s", username); state->username = username;#else msg (M_FATAL, "Sorry but I can't setuid to '%s' because this operating system doesn't appear to support the getpwname() or setuid() system calls", username);#endif }}voidset_user (const struct user_state *state){#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID) if (state->username && state->pw) { if (setuid (state->pw->pw_uid)) msg (M_ERR, "setuid('%s') failed", state->username); msg (M_INFO, "UID set to %s", state->username); }#endif}/* Get/Set GID of process */voidget_group (const char *groupname, struct group_state *state){ CLEAR (*state); if (groupname) {#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID) state->gr = getgrnam (groupname); if (!state->gr) msg (M_ERR, "failed to find GID for group %s", groupname); state->groupname = groupname;#else msg (M_FATAL, "Sorry but I can't setgid to '%s' because this operating system doesn't appear to support the getgrnam() or setgid() system calls", groupname);#endif }}voidset_group (const struct group_state *state){#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID) if (state->groupname && state->gr) { if (setgid (state->gr->gr_gid)) msg (M_ERR, "setgid('%s') failed", state->groupname); msg (M_INFO, "GID set to %s", state->groupname);#ifdef HAVE_SETGROUPS { gid_t gr_list[1]; gr_list[0] = state->gr->gr_gid; if (setgroups (1, gr_list)) msg (M_ERR, "setgroups('%s') failed", state->groupname); }#endif }#endif}/* Change process priority */voidset_nice (int niceval){ if (niceval) {#ifdef HAVE_NICE errno = 0; nice (niceval); if (errno != 0) msg (M_WARN | M_ERRNO, "WARNING: nice %d failed", niceval); else msg (M_INFO, "nice %d succeeded", niceval);#else msg (M_WARN, "WARNING: nice %d failed (function not implemented)", niceval);#endif }}/* Pass tunnel endpoint and MTU parms to a user-supplied script */voidrun_script (const char *command, const char *arg, int tun_mtu, int link_mtu, const char *ifconfig_local, const char* ifconfig_remote, const char *context, const char *signal_text, const char *script_type){ if (signal_text) setenv_str ("signal", signal_text); setenv_str ("script_context", context); setenv_int ("tun_mtu", tun_mtu); setenv_int ("link_mtu", link_mtu); setenv_str ("dev", arg); if (command) { char command_line[512]; ASSERT (arg); if (!ifconfig_local) ifconfig_local = ""; if (!ifconfig_remote) ifconfig_remote = ""; if (!context) context = ""; setenv_str ("script_type", script_type); openvpn_snprintf (command_line, sizeof (command_line), "%s %s %d %d %s %s %s", command, arg, tun_mtu, link_mtu, ifconfig_local, ifconfig_remote, context); msg (M_INFO, "%s", command_line); system_check (command_line, "script failed", true); }}/* remove non-parameter environmental vars except for signal */voiddel_env_nonparm (int n_tls_id){ setenv_del ("script_context"); setenv_del ("tun_mtu"); setenv_del ("link_mtu"); setenv_del ("dev"); setenv_del ("ifconfig_remote"); setenv_del ("ifconfig_netmask"); setenv_del ("ifconfig_broadcast"); setenv_del ("untrusted_ip"); setenv_del ("untrusted_port"); setenv_del ("trusted_ip"); setenv_del ("trusted_port"); /* delete tls_id_{n} values */ { int i; char buf[64]; for (i = 0; i < n_tls_id; ++i) { openvpn_snprintf (buf, sizeof (buf), "tls_id_%d", i); setenv_del (buf); } }}/* Get the file we will later write our process ID to */voidget_pid_file (const char* filename, struct pid_state *state){ CLEAR (*state); if (filename) {#ifdef HAVE_GETPID state->fp = fopen (filename, "w"); if (!state->fp) msg (M_ERR, "Open error on pid file %s", filename); state->filename = filename;#else msg (M_FATAL, "Sorry but I can't write my pid to '%s' because this operating system doesn't appear to support the getpid() system call", filename);#endif }}/* Write our PID to a file */voidwrite_pid (const struct pid_state *state){#ifdef HAVE_GETPID if (state->filename && state->fp) { const pid_t pid = getpid (); fprintf(state->fp, "%d\n", (int)pid); if (fclose (state->fp)) msg (M_ERR, "Close error on pid file %s", state->filename); }#endif}/* Get current PID */intget_current_pid (){#ifdef HAVE_GETPID return (int) getpid ();#else return 0;#endif}/* Disable paging */voiddo_mlockall(bool print_msg){#ifdef HAVE_MLOCKALL if (mlockall (MCL_CURRENT | MCL_FUTURE)) msg (M_WARN | M_ERRNO, "WARNING: mlockall call failed"); else if (print_msg) msg (M_INFO, "mlockall call succeeded");#else msg (M_WARN, "WARNING: mlockall call failed (function not implemented)");#endif}#ifndef HAVE_DAEMONintdaemon(int nochdir, int noclose){#if defined(HAVE_FORK) && defined(HAVE_SETSID) switch (fork()) { case -1: return (-1); case 0: break; default: openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */ } if (setsid() == -1) return (-1); if (!nochdir) openvpn_chdir ("/"); if (!noclose) set_std_files_to_null (false);#else msg (M_FATAL, "Sorry but I can't become a daemon because this operating system doesn't appear to support either the daemon() or fork() system calls");#endif return (0);}#endif/* * Set standard file descriptors to /dev/null */voidset_std_files_to_null (bool stdin_only){#if defined(HAVE_DUP) && defined(HAVE_DUP2) int fd; if ((fd = open ("/dev/null", O_RDWR, 0)) != -1) { dup2 (fd, 0); if (!stdin_only) { dup2 (fd, 1); dup2 (fd, 2); } if (fd > 2) close (fd); }#endif}/* * Wrapper for chdir library function */intopenvpn_chdir (const char* dir){#ifdef HAVE_CHDIR return chdir (dir);#else return -1;#endif}/* * dup inetd/xinetd socket descriptor and save */int inetd_socket_descriptor = -1; /* GLOBAL */voidsave_inetd_socket_descriptor (void){ inetd_socket_descriptor = INETD_SOCKET_DESCRIPTOR;#if defined(HAVE_DUP) && defined(HAVE_DUP2) /* use handle passed by inetd/xinetd */ if ((inetd_socket_descriptor = dup (INETD_SOCKET_DESCRIPTOR)) < 0) msg (M_ERR, "INETD_SOCKET_DESCRIPTOR dup(%d) failed", INETD_SOCKET_DESCRIPTOR); set_std_files_to_null (true);#endif}/* * Wrapper around the system() call. */intopenvpn_system (const char *command){#ifdef HAVE_SYSTEM return system (command);#else msg (M_FATAL, "Sorry but I can't execute the shell command '%s' because this operating system doesn't appear to support the system() call", command); return -1; /* NOTREACHED */#endif}/* * Warn if a given file is group/others accessible. */voidwarn_if_group_others_accessible (const char* filename){#ifdef HAVE_STAT struct stat st; if (stat (filename, &st)) { msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -