mirror of https://github.com/Cisco-Talos/clamav
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.
527 lines
12 KiB
527 lines
12 KiB
/*
|
|
* The builtin System object.
|
|
* Copyright (c) 1998-1999 New Generation Software (NGS) Oy
|
|
*
|
|
* Author: Markku Rossi <mtr@ngs.fi>
|
|
*/
|
|
|
|
/*
|
|
* This library 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 library 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 library; if not, write to the Free
|
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
* MA 02111-1307, USA
|
|
*/
|
|
|
|
/*
|
|
* $Source: /tmp/cvsroot-15-2-2007/clamav-devel/libclamav/js/b_system.c,v $
|
|
* $Id: b_system.c,v 1.3 2006/11/18 22:44:04 njh Exp $
|
|
*/
|
|
|
|
/*
|
|
* Static methods:
|
|
*
|
|
* chdir (string) => boolean
|
|
* error ([ANY...]) => undefined
|
|
* exit (value)
|
|
* getcwd () => string
|
|
* getenv (string) => string / undefined
|
|
* popen (COMMAND, MODE) => file
|
|
* print ([ANY...]) => undefined
|
|
* sleep (int) => undefined
|
|
* strerror (errno) => string
|
|
* system (string) => integer
|
|
* usleep (int) => undefined
|
|
*
|
|
* Properties: type mutable
|
|
*
|
|
* bits integer
|
|
* canonicalHost string
|
|
* canonicalHostCPU string
|
|
* canonicalHostVendor string
|
|
* canonicalHostOS string
|
|
* errno integer
|
|
* lineBreakSequence string
|
|
* stderr file
|
|
* stdin file
|
|
* stdout file
|
|
*/
|
|
#if HAVE_CONFIG_H
|
|
#include "clamav-config.h"
|
|
#endif
|
|
|
|
#ifdef CL_EXPERIMENTAL
|
|
|
|
#include "jsint.h"
|
|
|
|
/*
|
|
* Types and definitions.
|
|
*/
|
|
|
|
#define INSECURE() \
|
|
do { \
|
|
if (secure_mode) \
|
|
goto insecure_feature; \
|
|
} while (0)
|
|
|
|
struct system_ctx_st
|
|
{
|
|
JSSymbol s_chdir;
|
|
JSSymbol s_error;
|
|
JSSymbol s_exit;
|
|
JSSymbol s_getcwd;
|
|
JSSymbol s_getenv;
|
|
JSSymbol s_popen;
|
|
JSSymbol s_print;
|
|
JSSymbol s_sleep;
|
|
JSSymbol s_strerror;
|
|
JSSymbol s_system;
|
|
JSSymbol s_usleep;
|
|
|
|
JSSymbol s_bits;
|
|
JSSymbol s_canonicalHost;
|
|
JSSymbol s_canonicalHostCPU;
|
|
JSSymbol s_canonicalHostVendor;
|
|
JSSymbol s_canonicalHostOS;
|
|
JSSymbol s_errno;
|
|
JSSymbol s_lineBreakSequence;
|
|
JSSymbol s_stderr;
|
|
JSSymbol s_stdin;
|
|
JSSymbol s_stdout;
|
|
|
|
/* System file handles. */
|
|
JSNode pstderr;
|
|
JSNode pstdin;
|
|
JSNode pstdout;
|
|
};
|
|
|
|
typedef struct system_ctx_st SystemCtx;
|
|
|
|
|
|
/*
|
|
* Static functions.
|
|
*/
|
|
|
|
/* Method proc */
|
|
static int
|
|
method (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
|
|
void *instance_context, JSSymbol method, JSNode *result_return,
|
|
JSNode *args)
|
|
{
|
|
SystemCtx *ctx = builtin_info->obj_context;
|
|
int i;
|
|
char *cp;
|
|
int secure_mode = vm->security & JS_VM_SECURE_SYSTEM;
|
|
|
|
/* The default result. */
|
|
result_return->type = JS_UNDEFINED;
|
|
|
|
if (method == ctx->s_chdir)
|
|
{
|
|
INSECURE ();
|
|
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_STRING)
|
|
goto argument_type_error;
|
|
|
|
result_return->type= JS_BOOLEAN;
|
|
|
|
cp = js_string_to_c_string (vm, &args[1]);
|
|
result_return->u.vboolean = (chdir (cp) == 0);
|
|
js_free (cp);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_exit)
|
|
{
|
|
INSECURE ();
|
|
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_INTEGER)
|
|
goto argument_type_error;
|
|
|
|
/* Exit. */
|
|
exit (args[1].u.vinteger);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_getcwd)
|
|
{
|
|
int size = 10 * 1024;
|
|
|
|
INSECURE ();
|
|
|
|
if (args->u.vinteger != 0)
|
|
goto argument_error;
|
|
|
|
cp = js_malloc (vm, size);
|
|
if (!getcwd (cp, size))
|
|
{
|
|
result_return->type = JS_BOOLEAN;
|
|
result_return->u.vboolean = 0;
|
|
js_free (cp);
|
|
}
|
|
else
|
|
{
|
|
js_vm_make_string (vm, result_return, cp, strlen (cp));
|
|
js_free (cp);
|
|
}
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_getenv)
|
|
{
|
|
char *val;
|
|
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_STRING)
|
|
goto argument_type_error;
|
|
|
|
cp = js_string_to_c_string (vm, &args[1]);
|
|
val = getenv (cp);
|
|
js_free (cp);
|
|
|
|
if (val)
|
|
js_vm_make_string (vm, result_return, val, strlen (val));
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_popen)
|
|
{
|
|
char *cmd, *mode;
|
|
FILE *fp;
|
|
int readp = 0;
|
|
|
|
INSECURE ();
|
|
|
|
if (args->u.vinteger != 2)
|
|
goto argument_error;
|
|
if (args[1].type != JS_STRING || args[2].type != JS_STRING
|
|
|| args[2].u.vstring->len > 10)
|
|
goto argument_type_error;
|
|
|
|
cmd = js_string_to_c_string (vm, &args[1]);
|
|
mode = js_string_to_c_string (vm, &args[2]);
|
|
|
|
for (i = 0; mode[i]; i++)
|
|
if (mode[i] == 'r')
|
|
readp = 1;
|
|
|
|
JS_VM_ALLOCATE_FD (vm, "System.popen()");
|
|
fp = popen (cmd, mode);
|
|
|
|
if (fp == NULL)
|
|
JS_VM_FREE_FD (vm);
|
|
else
|
|
js_builtin_File_new (vm, result_return, cmd,
|
|
js_iostream_pipe (fp, readp), 0);
|
|
|
|
js_free (cmd);
|
|
js_free (mode);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_print || method == ctx->s_error)
|
|
{
|
|
JSIOStream *stream;
|
|
|
|
if (method == ctx->s_print)
|
|
stream = vm->s_stdout;
|
|
else
|
|
stream = vm->s_stderr;
|
|
|
|
for (i = 1; i <= args->u.vinteger; i++)
|
|
{
|
|
JSNode result;
|
|
|
|
js_vm_to_string (vm, &args[i], &result);
|
|
js_iostream_write (stream, result.u.vstring->data,
|
|
result.u.vstring->len);
|
|
}
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_sleep)
|
|
{
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_INTEGER)
|
|
goto argument_type_error;
|
|
|
|
/*sleep (args[1].u.vinteger);*/
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_strerror)
|
|
{
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_INTEGER)
|
|
goto argument_type_error;
|
|
|
|
cp = strerror (args[1].u.vinteger);
|
|
js_vm_make_string (vm, result_return, cp, strlen (cp));
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_system)
|
|
{
|
|
INSECURE ();
|
|
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_STRING)
|
|
goto argument_type_error;
|
|
|
|
result_return->type = JS_INTEGER;
|
|
|
|
cp = js_string_to_c_string (vm, &args[1]);
|
|
result_return->u.vinteger = system (cp);
|
|
js_free (cp);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == vm->syms.s_toString)
|
|
{
|
|
if (args->u.vinteger != 0)
|
|
goto argument_error;
|
|
|
|
js_vm_make_static_string (vm, result_return, "System", 6);
|
|
}
|
|
/* ********************************************************************** */
|
|
else if (method == ctx->s_usleep)
|
|
{
|
|
if (args->u.vinteger != 1)
|
|
goto argument_error;
|
|
if (args[1].type != JS_INTEGER)
|
|
goto argument_type_error;
|
|
|
|
/*usleep (args[1].u.vinteger);*/
|
|
}
|
|
/* ********************************************************************** */
|
|
else
|
|
return JS_PROPERTY_UNKNOWN;
|
|
|
|
return JS_PROPERTY_FOUND;
|
|
|
|
|
|
/*
|
|
* Error handling.
|
|
*/
|
|
|
|
argument_error:
|
|
sprintf (vm->error, "System.%s(): illegal amout of arguments",
|
|
js_vm_symname (vm, method));
|
|
js_vm_error (vm);
|
|
|
|
argument_type_error:
|
|
sprintf (vm->error, "System.%s(): illegal argument",
|
|
js_vm_symname (vm, method));
|
|
js_vm_error (vm);
|
|
|
|
insecure_feature:
|
|
sprintf (vm->error, "System.%s(): not allowed in secure mode",
|
|
js_vm_symname (vm, method));
|
|
js_vm_error (vm);
|
|
|
|
/* NOTREACHED */
|
|
return 0;
|
|
}
|
|
|
|
/* Property proc. */
|
|
static int
|
|
property (JSVirtualMachine *vm, JSBuiltinInfo *builtin_info,
|
|
void *instance_context, JSSymbol property, int set, JSNode *node)
|
|
{
|
|
SystemCtx *ctx = builtin_info->obj_context;
|
|
|
|
if (property == ctx->s_bits)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->type = JS_INTEGER;
|
|
#if SIZEOF_INT == 2
|
|
node->u.vinteger = 16;
|
|
#else /* not SIZEOF_INT == 2 */
|
|
|
|
#if SIZEOF_LONG == 4
|
|
node->u.vinteger = 32;
|
|
#else /* not SIZEOF_LONG == 4 */
|
|
|
|
#if SIZEOF_LONG == 8
|
|
node->u.vinteger = 64;
|
|
#else /* not SIZEOF_LONG == 8 */
|
|
|
|
/* Do not know. */
|
|
node->u.vinteger = 0;
|
|
|
|
#endif /* not SIZEOF_LONG == 8 */
|
|
#endif /* not SIZEOF_LONG == 4 */
|
|
#endif /* not SIZEOF_INT == 2 */
|
|
}
|
|
else if (property == ctx->s_canonicalHost)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
js_vm_make_static_string (vm, node, CANONICAL_HOST,
|
|
strlen (CANONICAL_HOST));
|
|
}
|
|
else if (property == ctx->s_canonicalHostCPU)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
js_vm_make_static_string (vm, node, CANONICAL_HOST_CPU,
|
|
strlen (CANONICAL_HOST_CPU));
|
|
}
|
|
else if (property == ctx->s_canonicalHostVendor)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
js_vm_make_static_string (vm, node, CANONICAL_HOST_VENDOR,
|
|
strlen (CANONICAL_HOST_VENDOR));
|
|
}
|
|
else if (property == ctx->s_canonicalHostOS)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
js_vm_make_static_string (vm, node, CANONICAL_HOST_OS,
|
|
strlen (CANONICAL_HOST_OS));
|
|
}
|
|
else if (property == ctx->s_errno)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
node->type = JS_INTEGER;
|
|
node->u.vinteger = errno;
|
|
}
|
|
else if (property == ctx->s_lineBreakSequence)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
js_vm_make_static_string (vm, node, JS_HOST_LINE_BREAK,
|
|
JS_HOST_LINE_BREAK_LEN);
|
|
}
|
|
else if (property == ctx->s_stderr)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
JS_COPY (node, &ctx->pstderr);
|
|
}
|
|
else if (property == ctx->s_stdin)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
JS_COPY (node, &ctx->pstdin);
|
|
}
|
|
else if (property == ctx->s_stdout)
|
|
{
|
|
if (set)
|
|
goto immutable;
|
|
|
|
JS_COPY (node, &ctx->pstdout);
|
|
}
|
|
|
|
else
|
|
{
|
|
if (!set)
|
|
node->type = JS_UNDEFINED;
|
|
|
|
return JS_PROPERTY_UNKNOWN;
|
|
}
|
|
|
|
return JS_PROPERTY_FOUND;
|
|
|
|
|
|
/*
|
|
* Error handling.
|
|
*/
|
|
|
|
immutable:
|
|
sprintf (vm->error, "System.%s: immutable property",
|
|
js_vm_symname (vm, property));
|
|
js_vm_error (vm);
|
|
|
|
/* NOTREACHED. */
|
|
return 0;
|
|
}
|
|
|
|
/* Mark proc. */
|
|
static void
|
|
mark (JSBuiltinInfo *builtin_info, void *instance_context)
|
|
{
|
|
SystemCtx *ctx = builtin_info->obj_context;
|
|
|
|
js_vm_mark (&ctx->pstderr);
|
|
js_vm_mark (&ctx->pstdin);
|
|
js_vm_mark (&ctx->pstdout);
|
|
}
|
|
|
|
|
|
/*
|
|
* Global functions.
|
|
*/
|
|
|
|
void
|
|
js_builtin_System (JSVirtualMachine *vm)
|
|
{
|
|
JSNode *n;
|
|
JSBuiltinInfo *info;
|
|
SystemCtx *ctx;
|
|
|
|
ctx = js_calloc (vm, 1, sizeof (*ctx));
|
|
|
|
ctx->s_chdir = js_vm_intern (vm, "chdir");
|
|
ctx->s_error = js_vm_intern (vm, "error");
|
|
ctx->s_exit = js_vm_intern (vm, "exit");
|
|
ctx->s_getcwd = js_vm_intern (vm, "getcwd");
|
|
ctx->s_getenv = js_vm_intern (vm, "getenv");
|
|
ctx->s_popen = js_vm_intern (vm, "popen");
|
|
ctx->s_print = js_vm_intern (vm, "print");
|
|
ctx->s_sleep = js_vm_intern (vm, "sleep");
|
|
ctx->s_strerror = js_vm_intern (vm, "strerror");
|
|
ctx->s_system = js_vm_intern (vm, "system");
|
|
ctx->s_usleep = js_vm_intern (vm, "usleep");
|
|
|
|
ctx->s_bits = js_vm_intern (vm, "bits");
|
|
ctx->s_canonicalHost = js_vm_intern (vm, "canonicalHost");
|
|
ctx->s_canonicalHostCPU = js_vm_intern (vm, "canonicalHostCPU");
|
|
ctx->s_canonicalHostVendor = js_vm_intern (vm, "canonicalHostVendor");
|
|
ctx->s_canonicalHostOS = js_vm_intern (vm, "canonicalHostOS");
|
|
ctx->s_errno = js_vm_intern (vm, "errno");
|
|
ctx->s_lineBreakSequence = js_vm_intern (vm, "lineBreakSequence");
|
|
ctx->s_stderr = js_vm_intern (vm, "stderr");
|
|
ctx->s_stdin = js_vm_intern (vm, "stdin");
|
|
ctx->s_stdout = js_vm_intern (vm, "stdout");
|
|
|
|
/* Object information. */
|
|
|
|
info = js_vm_builtin_info_create (vm);
|
|
|
|
info->method_proc = method;
|
|
info->property_proc = property;
|
|
info->mark_proc = mark;
|
|
info->obj_context = ctx;
|
|
info->obj_context_delete = js_free;
|
|
|
|
/* Define it. */
|
|
n = &vm->globals[js_vm_intern (vm, "System")];
|
|
js_vm_builtin_create (vm, n, info, NULL);
|
|
|
|
/* Enter system properties. */
|
|
js_builtin_File_new (vm, &ctx->pstderr, "stdout", vm->s_stderr, 1);
|
|
js_builtin_File_new (vm, &ctx->pstdin, "stdin", vm->s_stdin, 1);
|
|
js_builtin_File_new (vm, &ctx->pstdout, "stdout", vm->s_stdout, 1);
|
|
}
|
|
#endif /*CL_EXPERIMENTAL*/
|
|
|