summaryrefslogtreecommitdiff
path: root/source4/scripting/ejs
diff options
context:
space:
mode:
Diffstat (limited to 'source4/scripting/ejs')
-rw-r--r--source4/scripting/ejs/config.mk63
-rw-r--r--source4/scripting/ejs/mprutil.c494
-rw-r--r--source4/scripting/ejs/smbcalls.c220
-rw-r--r--source4/scripting/ejs/smbcalls.h42
-rw-r--r--source4/scripting/ejs/smbcalls_auth.c243
-rw-r--r--source4/scripting/ejs/smbcalls_config.c228
-rw-r--r--source4/scripting/ejs/smbcalls_creds.c275
-rw-r--r--source4/scripting/ejs/smbcalls_ldb.c772
-rw-r--r--source4/scripting/ejs/smbcalls_options.c193
-rw-r--r--source4/scripting/ejs/smbcalls_string.c529
-rw-r--r--source4/scripting/ejs/smbcalls_sys.c494
-rw-r--r--source4/scripting/ejs/smbscript.c129
12 files changed, 3682 insertions, 0 deletions
diff --git a/source4/scripting/ejs/config.mk b/source4/scripting/ejs/config.mk
new file mode 100644
index 0000000000..34c0a9678e
--- /dev/null
+++ b/source4/scripting/ejs/config.mk
@@ -0,0 +1,63 @@
+[MODULE::smbcalls_config]
+OUTPUT_TYPE = MERGED_OBJ
+SUBSYSTEM = smbcalls
+INIT_FUNCTION = smb_setup_ejs_config
+
+smbcalls_config_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_config.o
+
+[MODULE::smbcalls_ldb]
+OUTPUT_TYPE = MERGED_OBJ
+SUBSYSTEM = smbcalls
+INIT_FUNCTION = smb_setup_ejs_ldb
+PRIVATE_DEPENDENCIES = LIBLDB SAMDB LIBNDR
+
+smbcalls_ldb_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_ldb.o
+
+[MODULE::smbcalls_auth]
+OUTPUT_TYPE = MERGED_OBJ
+SUBSYSTEM = smbcalls
+INIT_FUNCTION = smb_setup_ejs_auth
+PRIVATE_DEPENDENCIES = service_auth
+
+smbcalls_auth_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_auth.o
+
+smbcalls_auth_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_auth.o
+
+[MODULE::smbcalls_string]
+SUBSYSTEM = smbcalls
+OUTPUT_TYPE = MERGED_OBJ
+INIT_FUNCTION = smb_setup_ejs_string
+
+smbcalls_string_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_string.o
+
+[MODULE::smbcalls_sys]
+SUBSYSTEM = smbcalls
+OUTPUT_TYPE = MERGED_OBJ
+INIT_FUNCTION = smb_setup_ejs_system
+
+smbcalls_sys_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_sys.o
+
+[SUBSYSTEM::smbcalls]
+PRIVATE_DEPENDENCIES = \
+ EJS LIBSAMBA-UTIL \
+ MESSAGING \
+ LIBSAMBA-NET LIBCLI_SMB LIBPOPT \
+ CREDENTIALS POPT_CREDENTIALS POPT_SAMBA \
+ NDR_TABLE
+
+smbcalls_OBJ_FILES = $(addprefix $(ejsscriptsrcdir)/, \
+ smbcalls.o \
+ smbcalls_options.o \
+ smbcalls_creds.o \
+ mprutil.o)
+
+$(eval $(call proto_header_template,$(ejsscriptsrcdir)/proto.h,$(smbcalls_OBJ_FILES:.o=.c)))
+
+#######################
+# Start BINARY SMBSCRIPT
+[BINARY::smbscript]
+PRIVATE_DEPENDENCIES = EJS LIBSAMBA-UTIL smbcalls LIBSAMBA-HOSTCONFIG
+# End BINARY SMBSCRIPT
+#######################
+
+smbscript_OBJ_FILES = $(ejsscriptsrcdir)/smbscript.o
diff --git a/source4/scripting/ejs/mprutil.c b/source4/scripting/ejs/mprutil.c
new file mode 100644
index 0000000000..9143947fb8
--- /dev/null
+++ b/source4/scripting/ejs/mprutil.c
@@ -0,0 +1,494 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ utility functions for manipulating mpr variables in ejs calls
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "lib/ldb/include/ldb.h"
+#include "scripting/ejs/smbcalls.h"
+
+/*
+ return a default mpr object
+*/
+struct MprVar mprObject(const char *name)
+{
+ return ejsCreateObj(name && *name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE);
+}
+
+/*
+ return a empty mpr array
+*/
+struct MprVar mprArray(const char *name)
+{
+ return ejsCreateArray(name && *name?name:"(NULL)", 0);
+}
+
+/*
+ find a mpr component, allowing for sub objects, using the '.' convention
+*/
+ NTSTATUS mprGetVar(struct MprVar **v, const char *name)
+{
+ const char *p = strchr(name, '.');
+ char *objname;
+ NTSTATUS status;
+ if (p == NULL) {
+ *v = mprGetProperty(*v, name, NULL);
+ if (*v == NULL) {
+ DEBUG(1,("mprGetVar unable to find '%s'\n", name));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ return NT_STATUS_OK;
+ }
+ objname = talloc_strndup(mprMemCtx(), name, p-name);
+ NT_STATUS_HAVE_NO_MEMORY(objname);
+ *v = mprGetProperty(*v, objname, NULL);
+ NT_STATUS_HAVE_NO_MEMORY(*v);
+ status = mprGetVar(v, p+1);
+ talloc_free(objname);
+ return status;
+}
+
+
+/*
+ set a mpr component, allowing for sub objects, using the '.' convention
+ destroys 'val' after setting
+*/
+ NTSTATUS mprSetVar(struct MprVar *v, const char *name, struct MprVar val)
+{
+ const char *p = strchr(name, '.');
+ char *objname;
+ struct MprVar *v2;
+ NTSTATUS status;
+ if (p == NULL) {
+ v2 = mprSetProperty(v, name, &val);
+ if (v2 == NULL) {
+ DEBUG(1,("mprSetVar unable to set '%s'\n", name));
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+ mprDestroyVar(&val);
+ return NT_STATUS_OK;
+ }
+ objname = talloc_strndup(mprMemCtx(), name, p-name);
+ if (objname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ v2 = mprGetProperty(v, objname, NULL);
+ if (v2 == NULL) {
+ mprSetVar(v, objname, mprObject(objname));
+ v2 = mprGetProperty(v, objname, NULL);
+ }
+ status = mprSetVar(v2, p+1, val);
+ talloc_free(objname);
+ return status;
+}
+
+
+
+/*
+ add an indexed array element to a property
+*/
+ void mprAddArray(struct MprVar *var, int i, struct MprVar v)
+{
+ char idx[16];
+ mprItoa(i, idx, sizeof(idx));
+ mprSetVar(var, idx, v);
+}
+
+/*
+ construct a MprVar from a list
+*/
+struct MprVar mprList(const char *name, const char **list)
+{
+ struct MprVar var;
+ int i;
+
+ var = mprArray(name);
+ for (i=0;list && list[i];i++) {
+ mprAddArray(&var, i, mprString(list[i]));
+ }
+ return var;
+}
+
+/*
+ construct a MprVar from a string, using NULL if needed
+*/
+struct MprVar mprString(const char *s)
+{
+ if (s == NULL) {
+ return mprCreatePtrVar(NULL);
+ }
+ return mprCreateStringVar(s, true);
+}
+
+/*
+ construct a string MprVar from a lump of data
+*/
+struct MprVar mprData(const uint8_t *p, size_t length)
+{
+ struct MprVar var;
+ char *s = talloc_strndup(mprMemCtx(), (const char *)p, length);
+ if (s == NULL) {
+ return mprCreateUndefinedVar();
+ }
+ var = mprString(s);
+ talloc_free(s);
+ return var;
+}
+
+/*
+ turn a ldb_message into a ejs object variable
+*/
+static struct MprVar mprLdbMessage(struct ldb_context *ldb, struct ldb_message *msg)
+{
+ struct MprVar var;
+ int i;
+ /* we force some attributes to always be an array in the
+ returned structure. This makes the scripting easier, as you don't
+ need a special case for the single value case */
+ const char *multivalued[] = { "objectClass", "memberOf", "privilege",
+ "member", NULL };
+
+ var = mprObject(ldb_dn_alloc_linearized(msg, msg->dn));
+
+ for (i=0;i<msg->num_elements;i++) {
+ struct ldb_message_element *el = &msg->elements[i];
+ struct MprVar val;
+ const struct ldb_schema_attribute *a;
+ struct ldb_val v;
+
+ a = ldb_schema_attribute_by_name(ldb, el->name);
+ if (a == NULL) {
+ goto failed;
+ }
+
+ if (el->num_values == 1 &&
+ !str_list_check_ci(multivalued, el->name)) {
+ if (a->syntax->ldif_write_fn(ldb, msg, &el->values[0], &v) != 0) {
+ goto failed;
+ }
+ /* FIXME: nasty hack, remove me when ejs will support
+ * arbitrary string and does not truncate on \0 */
+ if (strlen((char *)v.data) != v.length) {
+ val = mprDataBlob(v);
+ } else {
+ val = mprData(v.data, v.length);
+ }
+ } else {
+ int j;
+ val = mprArray(el->name);
+ for (j=0;j<el->num_values;j++) {
+ if (a->syntax->ldif_write_fn(ldb, msg,
+ &el->values[j], &v) != 0) {
+ goto failed;
+ }
+ /* FIXME: nasty hack, remove me when ejs will support
+ * arbitrary string and does not truncate on \0 */
+ if (strlen((char *)v.data) != v.length) {
+ mprAddArray(&val, j, mprDataBlob(v));
+ } else {
+ mprAddArray(&val, j, mprData(v.data, v.length));
+ }
+ }
+ }
+ mprSetVar(&var, el->name, val);
+ }
+
+ /* add the dn if it is not already specified */
+ if (mprGetProperty(&var, "dn", 0) == 0) {
+ mprSetVar(&var, "dn", mprString(ldb_dn_alloc_linearized(msg, msg->dn)));
+ }
+
+ return var;
+failed:
+ return mprCreateUndefinedVar();
+}
+
+
+/*
+ build a MprVar result object for ldb operations with lots of funky properties
+*/
+struct MprVar mprLdbResult(struct ldb_context *ldb, int err, struct ldb_result *result)
+{
+ struct MprVar ret;
+ struct MprVar ary;
+
+ ret = mprObject("ldbret");
+
+ mprSetVar(&ret, "error", mprCreateIntegerVar(err));
+ mprSetVar(&ret, "errstr", mprString(ldb_errstring(ldb)));
+
+ ary = mprArray("ldb_message");
+ if (result) {
+ int i;
+
+ for (i = 0; i < result->count; i++) {
+ mprAddArray(&ary, i, mprLdbMessage(ldb, result->msgs[i]));
+ }
+ }
+
+ mprSetVar(&ret, "msgs", ary);
+
+ /* TODO: add referrals, exteded ops, and controls */
+
+ return ret;
+}
+
+
+/*
+ turn a MprVar string variable into a const char *
+ */
+const char *mprToString(struct MprVar *v)
+{
+ if (v->trigger) {
+ mprReadProperty(v, 0);
+ }
+ if (!mprVarIsString(v->type)) return NULL;
+ return v->string;
+}
+
+/*
+ turn a MprVar integer variable into an int
+ */
+int mprToInt(struct MprVar *v)
+{
+ if (v->trigger) {
+ mprReadProperty(v, 0);
+ }
+ if (!mprVarIsNumber(v->type)) return 0;
+ return mprVarToNumber(v);
+}
+
+/*
+ turn a MprVar object variable into a string list
+ this assumes the object variable consists only of strings
+*/
+const char **mprToList(TALLOC_CTX *mem_ctx, struct MprVar *v)
+{
+ const char **list = NULL;
+ struct MprVar *el;
+
+ if (v->type != MPR_TYPE_OBJECT ||
+ v->properties == NULL) {
+ return NULL;
+ }
+ for (el=mprGetFirstProperty(v, MPR_ENUM_DATA);
+ el;
+ el=mprGetNextProperty(v, el, MPR_ENUM_DATA)) {
+ const char *s = mprToString(el);
+ if (s) {
+ list = str_list_add(list, s);
+ }
+ }
+ talloc_steal(mem_ctx, list);
+ return list;
+}
+
+
+/*
+ turn a MprVar object variable into a string list
+ this assumes the object variable is an array of strings
+*/
+const char **mprToArray(TALLOC_CTX *mem_ctx, struct MprVar *v)
+{
+ const char **list = NULL;
+ struct MprVar *len;
+ int length, i;
+
+ len = mprGetProperty(v, "length", NULL);
+ if (len == NULL) {
+ return NULL;
+ }
+ length = mprToInt(len);
+
+ for (i=0;i<length;i++) {
+ char idx[16];
+ struct MprVar *vs;
+ mprItoa(i, idx, sizeof(idx));
+ vs = mprGetProperty(v, idx, NULL);
+ if (vs == NULL || vs->type != MPR_TYPE_STRING) {
+ talloc_free(list);
+ return NULL;
+ }
+ list = str_list_add(list, mprToString(vs));
+ }
+ talloc_steal(mem_ctx, list);
+ return list;
+}
+
+/*
+ turn a NTSTATUS into a MprVar object with lots of funky properties
+*/
+struct MprVar mprNTSTATUS(NTSTATUS status)
+{
+ struct MprVar res;
+
+ res = mprObject("ntstatus");
+
+ mprSetVar(&res, "errstr", mprString(nt_errstr(status)));
+ mprSetVar(&res, "v", mprCreateIntegerVar(NT_STATUS_V(status)));
+ mprSetVar(&res, "is_ok", mprCreateBoolVar(NT_STATUS_IS_OK(status)));
+ mprSetVar(&res, "is_err", mprCreateBoolVar(NT_STATUS_IS_ERR(status)));
+
+ return res;
+}
+
+/*
+ create a data-blob in a mpr variable
+*/
+struct MprVar mprDataBlob(DATA_BLOB blob)
+{
+ struct MprVar res;
+ struct datablob *pblob = talloc(mprMemCtx(), struct datablob);
+ *pblob = data_blob_talloc(pblob, blob.data, blob.length);
+
+ res = mprObject("DATA_BLOB");
+
+ mprSetVar(&res, "size", mprCreateIntegerVar(blob.length));
+ mprSetPtrChild(&res, "blob", pblob);
+
+ return res;
+}
+
+/*
+ return a data blob from a mpr var created using mprDataBlob
+*/
+struct datablob *mprToDataBlob(struct MprVar *v)
+{
+ return talloc_get_type(mprGetPtr(v, "blob"), struct datablob);
+}
+
+/*
+ turn a WERROR into a MprVar object with lots of funky properties
+*/
+struct MprVar mprWERROR(WERROR status)
+{
+ struct MprVar res;
+
+ res = mprObject("werror");
+
+ mprSetVar(&res, "errstr", mprString(win_errstr(status)));
+ mprSetVar(&res, "v", mprCreateIntegerVar(W_ERROR_V(status)));
+ mprSetVar(&res, "is_ok", mprCreateBoolVar(W_ERROR_IS_OK(status)));
+ mprSetVar(&res, "is_err", mprCreateBoolVar(!W_ERROR_IS_OK(status)));
+
+ return res;
+}
+
+
+/*
+ set a pointer in a existing MprVar
+*/
+void mprSetPtr(struct MprVar *v, const char *propname, const void *p)
+{
+ mprSetVar(v, propname, mprCreatePtrVar(discard_const(p)));
+}
+
+/*
+ set a pointer in a existing MprVar, freeing it when the property goes away
+*/
+void mprSetPtrChild(struct MprVar *v, const char *propname, const void *p)
+{
+ mprSetVar(v, propname, mprCreatePtrVar(discard_const(p)));
+ v = mprGetProperty(v, propname, NULL);
+ v->allocatedData = 1;
+ talloc_steal(mprMemCtx(), p);
+}
+
+/*
+ get a pointer from a MprVar
+*/
+void *mprGetPtr(struct MprVar *v, const char *propname)
+{
+ struct MprVar *val;
+ val = mprGetProperty(v, propname, NULL);
+ if (val == NULL) {
+ return NULL;
+ }
+ if (val->type != MPR_TYPE_PTR) {
+ return NULL;
+ }
+ return val->ptr;
+}
+
+/*
+ set the return value then free the variable
+*/
+ void mpr_Return(int eid, struct MprVar v)
+{
+ ejsSetReturnValue(eid, v);
+ mprDestroyVar(&v);
+}
+
+/*
+ set the return value then free the variable
+*/
+void mpr_ReturnString(int eid, const char *s)
+{
+ mpr_Return(eid, mprString(s));
+}
+
+
+/*
+ set a C function in a variable
+*/
+ void mprSetCFunction(struct MprVar *obj, const char *name, MprCFunction fn)
+{
+ mprSetVar(obj, name, mprCreateCFunctionVar(fn, obj, MPR_VAR_SCRIPT_HANDLE));
+}
+
+/*
+ set a string C function in a variable
+*/
+ void mprSetStringCFunction(struct MprVar *obj, const char *name, MprStringCFunction fn)
+{
+ mprSetVar(obj, name, mprCreateStringCFunctionVar(fn, obj, MPR_VAR_SCRIPT_HANDLE));
+}
+
+/*
+ get a pointer in the current object
+*/
+void *mprGetThisPtr(int eid, const char *name)
+{
+ struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
+ return mprGetPtr(this, name);
+}
+
+/*
+ set a pointer as a child of the local object
+*/
+void mprSetThisPtr(int eid, const char *name, void *ptr)
+{
+ struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
+ mprSetPtrChild(this, name, ptr);
+}
+
+/*
+ used by object xxx_init() routines to allow for the caller
+ to supply a pre-existing object to add properties to,
+ or create a new object. This makes inheritance easy
+*/
+struct MprVar *mprInitObject(int eid, const char *name, int argc, struct MprVar **argv)
+{
+ if (argc > 0 && mprVarIsObject(argv[0]->type)) {
+ return argv[0];
+ }
+ mpr_Return(eid, mprObject(name));
+ return ejsGetReturnValue(eid);
+}
diff --git a/source4/scripting/ejs/smbcalls.c b/source4/scripting/ejs/smbcalls.c
new file mode 100644
index 0000000000..4314b51455
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls.c
@@ -0,0 +1,220 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide hooks into smbd C calls from ejs scripts
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Tim Potter 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "param/param.h"
+#include "scripting/ejs/smbcalls.h"
+#include "version.h"
+
+/*
+ return the type of a variable
+*/
+static int ejs_typeof(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ const struct {
+ MprType type;
+ const char *name;
+ } types[] = {
+ { MPR_TYPE_UNDEFINED, "undefined" },
+ { MPR_TYPE_NULL, "object" },
+ { MPR_TYPE_BOOL, "boolean" },
+ { MPR_TYPE_CFUNCTION, "function" },
+ { MPR_TYPE_FLOAT, "number" },
+ { MPR_TYPE_INT, "number" },
+ { MPR_TYPE_INT64, "number" },
+ { MPR_TYPE_OBJECT, "object" },
+ { MPR_TYPE_FUNCTION, "function" },
+ { MPR_TYPE_STRING, "string" },
+ { MPR_TYPE_STRING_CFUNCTION, "function" },
+ { MPR_TYPE_PTR, "pointer" }
+ };
+ int i;
+ const char *type = NULL;
+
+ if (argc != 1) return -1;
+
+ for (i=0;i<ARRAY_SIZE(types);i++) {
+ if (argv[0]->type == types[i].type) {
+ type = types[i].name;
+ break;
+ }
+ }
+ if (type == NULL) return -1;
+
+ mpr_ReturnString(eid, type);
+ return 0;
+}
+
+/*
+ return the native type of a variable
+*/
+static int ejs_typeof_native(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ const struct {
+ MprType type;
+ const char *name;
+ } types[] = {
+ { MPR_TYPE_UNDEFINED, "undefined" },
+ { MPR_TYPE_NULL, "null" },
+ { MPR_TYPE_BOOL, "boolean" },
+ { MPR_TYPE_CFUNCTION, "c_function" },
+ { MPR_TYPE_FLOAT, "float" },
+ { MPR_TYPE_INT, "integer" },
+ { MPR_TYPE_INT64, "integer64" },
+ { MPR_TYPE_OBJECT, "object" },
+ { MPR_TYPE_FUNCTION, "js_function" },
+ { MPR_TYPE_STRING, "string" },
+ { MPR_TYPE_STRING_CFUNCTION, "string_c_function" },
+ { MPR_TYPE_PTR, "pointer" }
+ };
+ int i;
+ const char *type = NULL;
+
+ if (argc != 1) return -1;
+
+ for (i=0;i<ARRAY_SIZE(types);i++) {
+ if (argv[0]->type == types[i].type) {
+ type = types[i].name;
+ break;
+ }
+ }
+ if (type == NULL) return -1;
+
+ mpr_ReturnString(eid, type);
+ return 0;
+}
+
+/*
+ libinclude() allows you to include js files using a search path specified
+ in "js include =" in smb.conf.
+*/
+static int ejs_libinclude(int eid, int argc, char **argv)
+{
+ int i, j;
+ const char **js_include = lp_js_include(mprLpCtx());
+
+ if (js_include == NULL || js_include[0] == NULL) {
+ ejsSetErrorMsg(eid, "js include path not set");
+ return -1;
+ }
+
+ for (i = 0; i < argc; i++) {
+ const char *script = argv[i];
+ struct MprVar result;
+ char *path, *emsg;
+ int ret;
+
+ /* use specfied path to search for requested file */
+ for (j=0;js_include[j];j++) {
+ path = talloc_asprintf(mprMemCtx(), "%s/%s", js_include[j], script);
+ if (path == NULL) {
+ return -1;
+ }
+ if (file_exist(path)) {
+
+ ret = ejsEvalFile(eid, path, &result, &emsg);
+ talloc_free(path);
+ if (ret < 0) {
+ ejsSetErrorMsg(eid, "%s: %s", script, emsg);
+ return -1;
+ }
+ break;
+ }
+ talloc_free(path);
+ }
+
+ if (js_include[j] == NULL) {
+ ejsSetErrorMsg(eid, "unable to include '%s'", script);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ return the current version
+*/
+static int ejs_version(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ mpr_ReturnString(eid, SAMBA_VERSION_STRING);
+ return 0;
+}
+
+
+static void (*ejs_exception_handler) (const char *) = NULL;
+
+_PUBLIC_ void ejs_exception(const char *reason)
+{
+ ejs_exception_handler(reason);
+}
+
+/*
+ setup C functions that be called from ejs
+*/
+void smb_setup_ejs_functions(void (*exception_handler)(const char *))
+{
+ extern NTSTATUS ejs_init_security(void);
+ extern NTSTATUS ejs_init_initshutdown(void);
+ extern NTSTATUS smb_setup_ejs_reg(void);
+ extern NTSTATUS smb_setup_ejs_string(void);
+ extern NTSTATUS ejs_init_lsarpc(void);
+ extern NTSTATUS ejs_init_rpcecho(void);
+ extern NTSTATUS ejs_init_winreg(void);
+ extern NTSTATUS smb_setup_ejs_random(void);
+ extern NTSTATUS smb_setup_ejs_config(void);
+ extern NTSTATUS ejs_init_misc(void);
+ extern NTSTATUS ejs_init_netdfs(void);
+ extern NTSTATUS smb_setup_ejs_datablob(void);
+ extern NTSTATUS smb_setup_ejs_auth(void);
+ extern NTSTATUS smb_setup_ejs_nss(void);
+ extern NTSTATUS ejs_init_samr(void);
+ extern NTSTATUS ejs_init_wkssvc(void);
+ extern NTSTATUS smb_setup_ejs_system(void);
+ extern NTSTATUS smb_setup_ejs_ldb(void);
+ extern NTSTATUS ejs_init_svcctl(void);
+ extern NTSTATUS smb_setup_ejs_net(void);
+ extern NTSTATUS ejs_init_srvsvc(void);
+ extern NTSTATUS ejs_init_netlogon(void);
+ extern NTSTATUS ejs_init_drsuapi(void);
+ extern NTSTATUS ejs_init_irpc(void);
+ extern NTSTATUS ejs_init_eventlog(void);
+ init_module_fn static_init[] = { STATIC_smbcalls_MODULES };
+ init_module_fn *shared_init;
+
+ ejs_exception_handler = exception_handler;
+
+ smb_setup_ejs_options();
+ smb_setup_ejs_credentials();
+
+ shared_init = load_samba_modules(NULL, mprLpCtx(), "smbcalls");
+
+ run_init_functions(static_init);
+ run_init_functions(shared_init);
+
+ talloc_free(shared_init);
+
+ ejsDefineCFunction(-1, "typeof", ejs_typeof, NULL, MPR_VAR_SCRIPT_HANDLE);
+ ejsDefineCFunction(-1, "nativeTypeOf", ejs_typeof_native, NULL, MPR_VAR_SCRIPT_HANDLE);
+ ejsDefineStringCFunction(-1, "libinclude", ejs_libinclude, NULL, MPR_VAR_SCRIPT_HANDLE);
+ ejsDefineCFunction(-1, "version", ejs_version, NULL, MPR_VAR_SCRIPT_HANDLE);
+}
+
diff --git a/source4/scripting/ejs/smbcalls.h b/source4/scripting/ejs/smbcalls.h
new file mode 100644
index 0000000000..3aaf324b6e
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls.h
@@ -0,0 +1,42 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide hooks into smbd C calls from ejs scripts
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "lib/appweb/ejs/ejs.h"
+#include "lib/ldb/include/ldb.h"
+
+void mpr_Return(int eid, struct MprVar);
+NTSTATUS mprSetVar(struct MprVar *v, const char *name, struct MprVar val);
+NTSTATUS mprGetVar(struct MprVar **v, const char *name);
+void mprAddArray(struct MprVar *var, int i, struct MprVar v);
+void mprSetCFunction(struct MprVar *obj, const char *name, MprCFunction fn);
+void mprSetStringCFunction(struct MprVar *obj, const char *name, MprStringCFunction fn);
+
+struct smbcalls_context {
+ struct event_context *event_ctx;
+ struct messaging_context *msg_ctx;
+};
+
+struct ldb_context;
+struct ldb_message;
+struct cli_credentials;
+
+#include "param/param.h"
+#include "scripting/ejs/proto.h"
diff --git a/source4/scripting/ejs/smbcalls_auth.c b/source4/scripting/ejs/smbcalls_auth.c
new file mode 100644
index 0000000000..b67bb7ed5b
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_auth.c
@@ -0,0 +1,243 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ ejs auth functions
+
+ Copyright (C) Simo Sorce 2005
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "auth/auth.h"
+#include "auth/credentials/credentials.h"
+#include "scripting/ejs/smbcalls.h"
+#include "lib/events/events.h"
+#include "lib/messaging/irpc.h"
+#include "libcli/security/security.h"
+
+static int ejs_doauth(MprVarHandle eid,
+ TALLOC_CTX *tmp_ctx, struct MprVar *auth,
+ const char *username, const char *password,
+ const char *domain, const char *workstation,
+ struct socket_address *remote_host,
+ const char **auth_types)
+{
+ struct auth_usersupplied_info *user_info = NULL;
+ struct auth_serversupplied_info *server_info = NULL;
+ struct auth_session_info *session_info = NULL;
+ struct auth_context *auth_context;
+ struct MprVar *session_info_obj;
+ NTSTATUS nt_status;
+ bool set;
+
+ struct smbcalls_context *c;
+ struct event_context *ev;
+ struct messaging_context *msg;
+
+ /* Hope we can find an smbcalls_context somewhere up there... */
+ c = talloc_find_parent_bytype(tmp_ctx, struct smbcalls_context);
+ if (c) {
+ ev = c->event_ctx;
+ msg = c->msg_ctx;
+ } else {
+ /* Hope we can find the event context somewhere up there... */
+ ev = mprEventCtx();
+ msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, mprLpCtx()),
+ lp_iconv_convenience(mprLpCtx()), ev);
+ }
+
+ if (auth_types) {
+ nt_status = auth_context_create_methods(tmp_ctx, auth_types, ev, msg, mprLpCtx(), &auth_context);
+ } else {
+ nt_status = auth_context_create(tmp_ctx, ev, msg, mprLpCtx(), &auth_context);
+ }
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(false));
+ mprSetPropertyValue(auth, "report", mprString("Auth System Failure"));
+ goto done;
+ }
+
+ user_info = talloc(tmp_ctx, struct auth_usersupplied_info);
+ if (!user_info) {
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(false));
+ mprSetPropertyValue(auth, "report", mprString("talloc failed"));
+ goto done;
+ }
+
+ user_info->mapped_state = true;
+ user_info->client.account_name = username;
+ user_info->mapped.account_name = username;
+ user_info->client.domain_name = domain;
+ user_info->mapped.domain_name = domain;
+
+ user_info->workstation_name = workstation;
+
+ user_info->remote_host = remote_host;
+
+ user_info->password_state = AUTH_PASSWORD_PLAIN;
+ user_info->password.plaintext = talloc_strdup(user_info, password);
+
+ user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME |
+ USER_INFO_DONT_CHECK_UNIX_ACCOUNT;
+
+ user_info->logon_parameters = 0;
+
+ nt_status = auth_check_password(auth_context, tmp_ctx, user_info, &server_info);
+
+ /* Don't give the game away (any difference between no such
+ * user and wrong password) */
+ nt_status = auth_nt_status_squash(nt_status);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ mprSetPropertyValue(auth, "report",
+ mprString(talloc_strdup(mprMemCtx(), get_friendly_nt_error_msg(nt_status))));
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(false));
+ goto done;
+ }
+
+ nt_status = auth_generate_session_info(tmp_ctx, mprEventCtx(), mprLpCtx(), server_info, &session_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ mprSetPropertyValue(auth, "report", mprString("Session Info generation failed"));
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(false));
+ goto done;
+ }
+
+ if (security_token_has_nt_authenticated_users(session_info->security_token)) {
+ mprSetPropertyValue(auth, "user_class", mprString("USER"));
+ set = true;
+ }
+
+ if (security_token_has_builtin_administrators(session_info->security_token)) {
+ mprSetPropertyValue(auth, "user_class", mprString("ADMINISTRATOR"));
+ set = true;
+ }
+
+ if (security_token_is_system(session_info->security_token)) {
+ mprSetPropertyValue(auth, "user_class", mprString("SYSTEM"));
+ set = true;
+ }
+
+ if (security_token_is_anonymous(session_info->security_token)) {
+ mprSetPropertyValue(auth, "report", mprString("Anonymous login not permitted"));
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(false));
+ goto done;
+ }
+
+ if (!set) {
+ mprSetPropertyValue(auth, "report", mprString("Session Info generation failed"));
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(false));
+ }
+
+ session_info_obj = mprInitObject(eid, "session_info", 0, NULL);
+
+ mprSetPtrChild(session_info_obj, "session_info", session_info);
+ talloc_steal(mprMemCtx(), session_info);
+
+ mprSetProperty(auth, "session_info", session_info_obj);
+ mprSetPropertyValue(auth, "result", mprCreateBoolVar(server_info->authenticated));
+ mprSetPropertyValue(auth, "username", mprString(server_info->account_name));
+ mprSetPropertyValue(auth, "domain", mprString(server_info->domain_name));
+
+done:
+ return 0;
+}
+
+/*
+ perform user authentication, returning an array of results
+
+*/
+static int ejs_userAuth(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *username;
+ const char *password;
+ const char *domain;
+ const char *workstation;
+ struct MprVar auth;
+ struct cli_credentials *creds;
+ struct socket_address *remote_host;
+ const char *auth_types_unix[] = { "unix", NULL };
+
+ if (argc != 2 || argv[0]->type != MPR_TYPE_OBJECT || argv[1]->type != MPR_TYPE_OBJECT) {
+ ejsSetErrorMsg(eid, "userAuth invalid arguments, this function requires an object.");
+ return -1;
+ }
+
+ /* get credential values from credentials object */
+ creds = mprGetPtr(argv[0], "creds");
+ if (creds == NULL) {
+ ejsSetErrorMsg(eid, "userAuth requires a 'creds' first parameter");
+ return -1;
+ }
+
+ remote_host = (struct socket_address *)mprGetPtr(argv[1], "socket_address");
+ if (remote_host == NULL) {
+ ejsSetErrorMsg(eid, "userAuth requires a socket address second parameter");
+ return -1;
+ }
+
+ tmp_ctx = talloc_new(mprMemCtx());
+
+ username = cli_credentials_get_username(creds);
+ password = cli_credentials_get_password(creds);
+ domain = cli_credentials_get_domain(creds);
+ workstation = cli_credentials_get_workstation(creds);
+
+ if (username == NULL || password == NULL || domain == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ talloc_free(tmp_ctx);
+ return 0;
+ }
+
+ auth = mprObject("auth");
+
+ if (domain && (strcmp("SYSTEM USER", domain) == 0)) {
+ ejs_doauth(eid, tmp_ctx, &auth, username, password, domain, workstation, remote_host, auth_types_unix);
+ } else {
+ ejs_doauth(eid, tmp_ctx, &auth, username, password, domain, workstation, remote_host, NULL);
+ }
+
+ mpr_Return(eid, auth);
+ talloc_free(tmp_ctx);
+ return 0;
+}
+
+/*
+ initialise credentials ejs object
+*/
+static int ejs_system_session(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *obj = mprInitObject(eid, "session_info", argc, argv);
+ struct auth_session_info *session_info = system_session(mprMemCtx(), mprLpCtx());
+
+ if (session_info == NULL) {
+ return -1;
+ }
+
+ mprSetPtrChild(obj, "session_info", session_info);
+ return 0;
+}
+
+/*
+ setup C functions that be called from ejs
+*/
+NTSTATUS smb_setup_ejs_auth(void)
+{
+ ejsDefineCFunction(-1, "userAuth", ejs_userAuth, NULL, MPR_VAR_SCRIPT_HANDLE);
+ ejsDefineCFunction(-1, "system_session", ejs_system_session, NULL, MPR_VAR_SCRIPT_HANDLE);
+ return NT_STATUS_OK;
+}
diff --git a/source4/scripting/ejs/smbcalls_config.c b/source4/scripting/ejs/smbcalls_config.c
new file mode 100644
index 0000000000..eb673b3a23
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_config.c
@@ -0,0 +1,228 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide hooks into smbd C calls from ejs scripts
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "scripting/ejs/smbcalls.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "param/loadparm.h"
+#include "system/network.h"
+#include "lib/socket/netif.h"
+#include "param/param.h"
+
+/*
+ return a list of defined services
+*/
+static int ejs_lpServices(MprVarHandle eid, int argc, char **argv)
+{
+ int i;
+ const char **list = NULL;
+ if (argc != 0) return -1;
+
+ for (i=0;i<lp_numservices(mprLpCtx());i++) {
+ list = str_list_add(list, lp_servicename(lp_servicebynum(mprLpCtx(), i)));
+ }
+ talloc_steal(mprMemCtx(), list);
+ mpr_Return(eid, mprList("services", list));
+ return 0;
+}
+
+
+/*
+ allow access to loadparm variables from inside ejs scripts in web apps
+
+ can be called in 4 ways:
+
+ v = lp.get("type:parm"); gets a parametric variable
+ v = lp.get("share", "type:parm"); gets a parametric variable on a share
+ v = lp.get("parm"); gets a global variable
+ v = lp.get("share", "parm"); gets a share variable
+
+ the returned variable is a ejs object. It is an array object for lists.
+*/
+static int ejs_lpGet(MprVarHandle eid, int argc, char **argv)
+{
+ struct parm_struct *parm = NULL;
+ void *parm_ptr = NULL;
+ int i;
+
+ if (argc < 1) return -1;
+
+ if (argc == 2) {
+ struct loadparm_service *service;
+ /* its a share parameter */
+ service = lp_service(mprLpCtx(), argv[0]);
+ if (service == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ if (strchr(argv[1], ':')) {
+ /* its a parametric option on a share */
+ const char *type = talloc_strndup(mprMemCtx(),
+ argv[1],
+ strcspn(argv[1], ":"));
+ const char *option = strchr(argv[1], ':') + 1;
+ const char *value;
+ if (type == NULL || option == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ value = lp_get_parametric(mprLpCtx(), service, type, option);
+ if (value == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ mpr_ReturnString(eid, value);
+ return 0;
+ }
+
+ parm = lp_parm_struct(argv[1]);
+ if (parm == NULL || parm->class == P_GLOBAL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ parm_ptr = lp_parm_ptr(mprLpCtx(), service, parm);
+ } else if (strchr(argv[0], ':')) {
+ /* its a global parametric option */
+ const char *type = talloc_strndup(mprMemCtx(),
+ argv[0], strcspn(argv[0], ":"));
+ const char *option = strchr(argv[0], ':') + 1;
+ const char *value;
+ if (type == NULL || option == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ value = lp_get_parametric(mprLpCtx(), NULL, type, option);
+ if (value == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ mpr_ReturnString(eid, value);
+ return 0;
+ } else {
+ /* its a global parameter */
+ parm = lp_parm_struct(argv[0]);
+ if (parm == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ parm_ptr = lp_parm_ptr(mprLpCtx(), NULL, parm);
+ }
+
+ if (parm == NULL || parm_ptr == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+
+ /* construct and return the right type of ejs object */
+ switch (parm->type) {
+ case P_STRING:
+ case P_USTRING:
+ mpr_ReturnString(eid, *(char **)parm_ptr);
+ break;
+ case P_BOOL:
+ mpr_Return(eid, mprCreateBoolVar(*(bool *)parm_ptr));
+ break;
+ case P_INTEGER:
+ case P_OCTAL:
+ case P_BYTES:
+ mpr_Return(eid, mprCreateIntegerVar(*(int *)parm_ptr));
+ break;
+ case P_ENUM:
+ for (i=0; parm->enum_list[i].name; i++) {
+ if (*(int *)parm_ptr == parm->enum_list[i].value) {
+ mpr_ReturnString(eid, parm->enum_list[i].name);
+ return 0;
+ }
+ }
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ case P_LIST:
+ mpr_Return(eid, mprList(parm->label, *(const char ***)parm_ptr));
+ break;
+ }
+ return 0;
+}
+
+/*
+ v = lp.filename(); obtain filename
+*/
+static int ejs_lpFilename(MprVarHandle eid, int argc, char **argv)
+{
+ mpr_ReturnString(eid, lp_configfile(mprLpCtx()));
+ return 0;
+}
+
+/*
+ set a smb.conf parameter. Only sets in memory, not permanent
+
+ can be called in 4 ways:
+
+ ok = lp.set("parm", "value");
+*/
+static int ejs_lpSet(MprVarHandle eid, int argc, char **argv)
+{
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "lp.set invalid arguments");
+ return -1;
+ }
+
+ mpr_Return(eid, mprCreateBoolVar(lp_set_cmdline(mprLpCtx(), argv[0], argv[1])));
+ return 0;
+}
+
+/*
+ reload smb.conf
+
+ ok = lp.reload();
+*/
+static int ejs_lpReload(MprVarHandle eid, int argc, char **argv)
+{
+ bool ret;
+ const char *filename = lp_configfile(mprLpCtx());
+
+ ret = lp_load(mprLpCtx(), filename);
+ mpr_Return(eid, mprCreateBoolVar(ret));
+ return 0;
+}
+
+/*
+ initialise loadparm ejs subsystem
+*/
+static int ejs_loadparm_init(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *obj = mprInitObject(eid, "loadparm", argc, argv);
+
+ mprSetStringCFunction(obj, "get", ejs_lpGet);
+ mprSetStringCFunction(obj, "set", ejs_lpSet);
+ mprSetStringCFunction(obj, "reload", ejs_lpReload);
+ mprSetStringCFunction(obj, "services", ejs_lpServices);
+ mprSetStringCFunction(obj, "filename", ejs_lpFilename);
+ return 0;
+}
+
+/*
+ setup C functions that be called from ejs
+*/
+NTSTATUS smb_setup_ejs_config(void)
+{
+ ejsDefineCFunction(-1, "loadparm_init", ejs_loadparm_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+ return NT_STATUS_OK;
+}
diff --git a/source4/scripting/ejs/smbcalls_creds.c b/source4/scripting/ejs/smbcalls_creds.c
new file mode 100644
index 0000000000..fd73f0751f
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_creds.c
@@ -0,0 +1,275 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide hooks credentials calls
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "scripting/ejs/smbcalls.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "lib/cmdline/popt_common.h"
+#include "auth/credentials/credentials.h"
+
+/*
+ helper function to get the local objects credentials ptr
+*/
+static struct cli_credentials *ejs_creds_get_credentials(int eid)
+{
+ struct cli_credentials *creds = (struct cli_credentials *)mprGetThisPtr(eid, "creds");
+ if (creds == NULL) {
+ ejsSetErrorMsg(eid, "NULL ejs credentials");
+ }
+ return creds;
+}
+
+/*
+ get a domain
+*/
+static int ejs_creds_get_domain(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+
+ mpr_Return(eid, mprString(cli_credentials_get_domain(creds)));
+ return 0;
+}
+
+
+/*
+ set a domain
+*/
+static int ejs_creds_set_domain(MprVarHandle eid, int argc, char **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "bad arguments to set_domain");
+ return -1;
+ }
+
+ cli_credentials_set_domain(creds, argv[0], CRED_SPECIFIED);
+ mpr_Return(eid, mprCreateBoolVar(true));
+ return 0;
+}
+
+
+/*
+ get a username
+*/
+static int ejs_creds_get_username(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+
+ mpr_Return(eid, mprString(cli_credentials_get_username(creds)));
+ return 0;
+}
+
+
+/*
+ set a username
+*/
+static int ejs_creds_set_username(MprVarHandle eid, int argc, char **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "bad arguments to set_username");
+ return -1;
+ }
+
+ cli_credentials_set_username(creds, argv[0], CRED_SPECIFIED);
+ mpr_Return(eid, mprCreateBoolVar(true));
+ return 0;
+}
+
+
+/*
+ get user password
+*/
+static int ejs_creds_get_password(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+
+ mpr_Return(eid, mprString(cli_credentials_get_password(creds)));
+ return 0;
+}
+
+
+/*
+ set user password
+*/
+static int ejs_creds_set_password(MprVarHandle eid, int argc, char **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "bad arguments to set_password");
+ return -1;
+ }
+
+ cli_credentials_set_password(creds, argv[0], CRED_SPECIFIED);
+ mpr_Return(eid, mprCreateBoolVar(true));
+ return 0;
+}
+
+
+/*
+ set realm
+*/
+static int ejs_creds_set_realm(MprVarHandle eid, int argc, char **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "bad arguments to set_realm");
+ return -1;
+ }
+
+ cli_credentials_set_realm(creds, argv[0], CRED_SPECIFIED);
+ mpr_Return(eid, mprCreateBoolVar(true));
+ return 0;
+}
+
+
+/*
+ get realm
+*/
+static int ejs_creds_get_realm(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+
+ mpr_Return(eid, mprString(cli_credentials_get_realm(creds)));
+ return 0;
+}
+
+
+/*
+ set workstation
+*/
+static int ejs_creds_set_workstation(MprVarHandle eid, int argc, char **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "bad arguments to set_workstation");
+ return -1;
+ }
+
+ cli_credentials_set_workstation(creds, argv[0], CRED_SPECIFIED);
+ mpr_Return(eid, mprCreateBoolVar(true));
+ return 0;
+}
+
+
+/*
+ get workstation
+*/
+static int ejs_creds_get_workstation(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+
+ mpr_Return(eid, mprString(cli_credentials_get_workstation(creds)));
+ return 0;
+}
+
+/*
+ set machine account
+*/
+static int ejs_creds_set_machine_account(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds = ejs_creds_get_credentials(eid);
+ if (argc != 0) {
+ ejsSetErrorMsg(eid, "bad arguments to set_machine_account");
+ return -1;
+ }
+
+ if (NT_STATUS_IS_OK(cli_credentials_set_machine_account(creds, mprLpCtx()))) {
+ mpr_Return(eid, mprCreateBoolVar(true));
+ } else {
+ mpr_Return(eid, mprCreateBoolVar(false));
+ }
+ return 0;
+}
+
+
+/*
+ initialise credentials ejs object
+*/
+static int ejs_credentials_obj(struct MprVar *obj, struct cli_credentials *creds)
+{
+ mprSetPtrChild(obj, "creds", creds);
+
+ /* setup our object methods */
+ mprSetCFunction(obj, "get_domain", ejs_creds_get_domain);
+ mprSetStringCFunction(obj, "set_domain", ejs_creds_set_domain);
+ mprSetCFunction(obj, "get_username", ejs_creds_get_username);
+ mprSetStringCFunction(obj, "set_username", ejs_creds_set_username);
+ mprSetCFunction(obj, "get_password", ejs_creds_get_password);
+ mprSetStringCFunction(obj, "set_password", ejs_creds_set_password);
+ mprSetCFunction(obj, "get_realm", ejs_creds_get_realm);
+ mprSetStringCFunction(obj, "set_realm", ejs_creds_set_realm);
+ mprSetCFunction(obj, "get_workstation", ejs_creds_get_workstation);
+ mprSetStringCFunction(obj, "set_workstation", ejs_creds_set_workstation);
+ mprSetCFunction(obj, "set_machine_account", ejs_creds_set_machine_account);
+
+ return 0;
+}
+
+
+struct MprVar mprCredentials(struct cli_credentials *creds)
+{
+ struct MprVar mpv = mprObject("credentials");
+
+ ejs_credentials_obj(&mpv, creds);
+
+ return mpv;
+}
+
+
+/*
+ initialise credentials ejs object
+*/
+static int ejs_credentials_init(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct cli_credentials *creds;
+ struct MprVar *obj = mprInitObject(eid, "credentials", argc, argv);
+
+ creds = cli_credentials_init(mprMemCtx());
+ if (creds == NULL) {
+ return -1;
+ }
+
+ cli_credentials_set_conf(creds, mprLpCtx());
+
+ return ejs_credentials_obj(obj, creds);
+}
+
+/*
+ initialise cmdline credentials ejs object
+*/
+int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *obj = mprInitObject(eid, "credentials", argc, argv);
+ if (talloc_reference(mprMemCtx(), cmdline_credentials) == NULL) {
+ return -1;
+ }
+ return ejs_credentials_obj(obj, cmdline_credentials);
+}
+
+/*
+ setup C functions that be called from ejs
+*/
+void smb_setup_ejs_credentials(void)
+{
+ ejsDefineCFunction(-1, "credentials_init", ejs_credentials_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+}
+
diff --git a/source4/scripting/ejs/smbcalls_ldb.c b/source4/scripting/ejs/smbcalls_ldb.c
new file mode 100644
index 0000000000..4a157945af
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_ldb.c
@@ -0,0 +1,772 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide hooks into smbd C calls from ejs scripts
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Jelmer Vernooij 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "scripting/ejs/smbcalls.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "ldb_wrap.h"
+#include "dsdb/samdb/samdb.h"
+#include "librpc/ndr/libndr.h"
+#include "libcli/security/security.h"
+
+/*
+ get the connected db
+ */
+static struct ldb_context *ejs_get_ldb_context(int eid)
+{
+ struct ldb_context *ldb = (struct ldb_context *)mprGetThisPtr(eid, "db");
+ if (ldb == NULL) {
+ ejsSetErrorMsg(eid, "invalid ldb connection");
+ }
+ return ldb;
+}
+
+/*
+ perform an ldb search, returning an array of results
+
+ syntax:
+ res = ldb.search("expression");
+ var attrs = new Array("attr1", "attr2", "attr3");
+ ldb.search("expression", attrs);
+ var basedn = "cn=this,dc=is,dc=a,dc=test";
+ ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs);
+ ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs, controls);
+*/
+static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ const char **attrs = NULL;
+ const char *expression;
+ const char *base = NULL;
+ struct ldb_dn *basedn = NULL;
+ int scope = LDB_SCOPE_DEFAULT;
+ TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
+ struct ldb_context *ldb;
+ int ret;
+ struct ldb_control **parsed_controls = NULL;
+ struct ldb_result *res=NULL;
+ struct ldb_request *req;
+
+ /* validate arguments */
+ if (argc < 1 || argc > 5) {
+ ejsSetErrorMsg(eid, "ldb.search invalid number of arguments");
+ goto failed;
+ }
+ if (argc > 3 && argv[3]->type != MPR_TYPE_OBJECT) {
+ ejsSetErrorMsg(eid, "ldb.search attributes must be an object");
+ goto failed;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ expression = mprToString(argv[0]);
+ if (argc > 1) {
+ base = mprToString(argv[1]);
+ /* a null basedn is valid */
+ }
+ if (base != NULL) {
+ basedn = ldb_dn_new(tmp_ctx, ldb, base);
+ if ( ! ldb_dn_validate(basedn)) {
+ ejsSetErrorMsg(eid, "ldb.search malformed base dn");
+ goto failed;
+ }
+ } else {
+ basedn = ldb_get_default_basedn(ldb);
+ }
+ if (argc > 2) {
+ scope = mprToInt(argv[2]);
+ switch (scope) {
+ case LDB_SCOPE_DEFAULT:
+ case LDB_SCOPE_BASE:
+ case LDB_SCOPE_ONELEVEL:
+ case LDB_SCOPE_SUBTREE:
+ break; /* ok */
+ default:
+ ejsSetErrorMsg(eid, "ldb.search invalid scope");
+ goto failed;
+ }
+ }
+ if (argc > 3) {
+ attrs = mprToList(tmp_ctx, argv[3]);
+ }
+ if (argc > 4) {
+ const char **controls;
+ controls = mprToList(tmp_ctx, argv[4]);
+ if (controls) {
+ parsed_controls = ldb_parse_control_strings(ldb, tmp_ctx, controls);
+ if (!parsed_controls) {
+ ejsSetErrorMsg(eid, "ldb.search cannot parse controls: %s",
+ ldb_errstring(ldb));
+ goto failed;
+ }
+ }
+ }
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (!res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&req, ldb, tmp_ctx,
+ basedn,
+ scope,
+ expression,
+ attrs,
+ parsed_controls,
+ res,
+ ldb_search_default_callback);
+
+ if (ret == LDB_SUCCESS) {
+
+ ldb_set_timeout(ldb, req, 0); /* use default timeout */
+
+ ret = ldb_request(ldb, req);
+
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+ }
+
+ if (ret != LDB_SUCCESS) {
+ ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb));
+ mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
+ } else {
+ mpr_Return(eid, mprLdbResult(ldb, ret, res));
+ }
+
+ talloc_free(tmp_ctx);
+ return 0;
+
+failed:
+ talloc_free(tmp_ctx);
+ return -1;
+}
+
+
+/*
+ perform an ldb add or modify
+*/
+static int ejs_ldbAddModify(MprVarHandle eid, int argc, struct MprVar **argv,
+ int fn(struct ldb_context *, const struct ldb_message *))
+{
+ const char *ldifstring;
+ struct ldb_context *ldb;
+ struct ldb_ldif *ldif;
+ int ret = 0, count=0;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments");
+ return -1;
+ }
+
+ ldifstring = mprToString(argv[0]);
+ if (ldifstring == NULL) {
+ ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ while ((ldif = ldb_ldif_read_string(ldb, &ldifstring))) {
+ count++;
+ ret = fn(ldb, ldif->msg);
+ talloc_free(ldif);
+ if (ret != 0) break;
+ }
+
+ if (count == 0) {
+ ejsSetErrorMsg(eid, "ldb.add/modify invalid ldif");
+ return -1;
+ }
+
+ mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
+ return 0;
+}
+
+
+/*
+ perform an ldb delete
+ usage:
+ ok = ldb.delete(dn);
+*/
+static int ejs_ldbDelete(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_dn *dn;
+ struct ldb_context *ldb;
+ int ret;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.delete invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ dn = ldb_dn_new(ldb, ldb, mprToString(argv[0]));
+ if ( ! ldb_dn_validate(dn)) {
+ ejsSetErrorMsg(eid, "ldb.delete malformed dn");
+ return -1;
+ }
+
+ ret = ldb_delete(ldb, dn);
+
+ talloc_free(dn);
+
+ mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
+ return 0;
+}
+
+/*
+ perform an ldb rename
+ usage:
+ ok = ldb.rename(dn1, dn2);
+*/
+static int ejs_ldbRename(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_dn *dn1, *dn2;
+ struct ldb_context *ldb;
+ int ret;
+
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "ldb.rename invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ dn1 = ldb_dn_new(ldb, ldb, mprToString(argv[0]));
+ dn2 = ldb_dn_new(ldb, ldb, mprToString(argv[1]));
+ if ( ! ldb_dn_validate(dn1) || ! ldb_dn_validate(dn2)) {
+ ejsSetErrorMsg(eid, "ldb.rename invalid or malformed arguments");
+ return -1;
+ }
+
+ ret = ldb_rename(ldb, dn1, dn2);
+
+ talloc_free(dn1);
+ talloc_free(dn2);
+
+ mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
+ return 0;
+}
+
+/*
+ get last error message
+ usage:
+ ok = ldb.errstring();
+*/
+static int ejs_ldbErrstring(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_context *ldb;
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ mpr_Return(eid, mprString(ldb_errstring(ldb)));
+ return 0;
+}
+
+/*
+ base64 encode
+ usage:
+ dataout = ldb.encode(datain)
+ */
+static int ejs_base64encode(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ char *ret;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count");
+ return -1;
+ }
+
+ if (argv[0]->type == MPR_TYPE_STRING) {
+ const char *orig = mprToString(argv[0]);
+ ret = ldb_base64_encode(mprMemCtx(), orig, strlen(orig));
+ } else {
+ DATA_BLOB *blob;
+
+ blob = mprToDataBlob(argv[0]);
+ mprAssert(blob);
+ ret = ldb_base64_encode(mprMemCtx(), (char *)blob->data, blob->length);
+ }
+
+ if (!ret) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ } else {
+ mpr_Return(eid, mprString(ret));
+ }
+
+ talloc_free(ret);
+
+ return 0;
+}
+
+/*
+ base64 decode
+ usage:
+ dataout = ldb.decode(datain)
+ */
+static int ejs_base64decode(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ char *tmp;
+ int ret;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count");
+ return -1;
+ }
+
+ tmp = talloc_strdup(mprMemCtx(), mprToString(argv[0]));
+ ret = ldb_base64_decode(tmp);
+ if (ret == -1) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ } else {
+ DATA_BLOB blob;
+ blob.data = (uint8_t *)tmp;
+ blob.length = ret;
+ mpr_Return(eid, mprDataBlob(blob));
+ }
+
+ talloc_free(tmp);
+
+ return 0;
+}
+
+/*
+ escape a DN
+ usage:
+ dataout = ldb.dn_escape(datain)
+ */
+static int ejs_dn_escape(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ char *ret;
+ struct ldb_val val;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.dn_escape invalid argument count");
+ return -1;
+ }
+
+ val = data_blob_string_const(mprToString(argv[0]));
+
+ ret = ldb_dn_escape_value(mprMemCtx(), val);
+ if (ret == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ } else {
+ mpr_Return(eid, mprString(ret));
+ talloc_free(ret);
+ }
+
+ return 0;
+}
+
+/*
+ perform an ldb add
+
+ syntax:
+ ok = ldb.add(ldifstring);
+*/
+static int ejs_ldbAdd(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ return ejs_ldbAddModify(eid, argc, argv, ldb_add);
+}
+
+/*
+ perform an ldb modify
+
+ syntax:
+ ok = ldb.modify(ldifstring);
+*/
+static int ejs_ldbModify(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ return ejs_ldbAddModify(eid, argc, argv, ldb_modify);
+}
+
+/*
+ connect to a database
+ usage:
+ ok = ldb.connect(dbfile);
+ ok = ldb.connect(dbfile, "modules:modlist");
+
+ ldb.credentials or ldb.session_info may be setup first
+
+*/
+static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv)
+{
+ struct ldb_context *ldb;
+ struct auth_session_info *session_info = NULL;
+ struct cli_credentials *creds = NULL;
+ struct MprVar *credentials, *session;
+ struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
+
+ const char *dbfile;
+
+ if (argc < 1) {
+ ejsSetErrorMsg(eid, "ldb.connect invalid arguments");
+ return -1;
+ }
+
+ credentials = mprGetProperty(this, "credentials", NULL);
+ if (credentials) {
+ creds = talloc_get_type(mprGetPtr(credentials, "creds"), struct cli_credentials);
+ }
+
+ session = mprGetProperty(this, "session_info", NULL);
+ if (session) {
+ session_info = talloc_get_type(mprGetPtr(session, "session_info"), struct auth_session_info);
+ }
+
+ dbfile = argv[0];
+
+ ldb = ldb_wrap_connect(mprMemCtx(), mprEventCtx(), mprLpCtx(), dbfile,
+ session_info, creds,
+ 0, (const char **)(argv+1));
+ if (ldb == NULL) {
+ ejsSetErrorMsg(eid, "ldb.connect failed to open %s", dbfile);
+ }
+
+ mprSetThisPtr(eid, "db", ldb);
+ mpr_Return(eid, mprCreateBoolVar(ldb != NULL));
+ return 0;
+}
+
+
+/*
+ close a db connection
+*/
+static int ejs_ldbClose(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_context *ldb;
+
+ if (argc != 0) {
+ ejsSetErrorMsg(eid, "ldb.close invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ mprSetThisPtr(eid, "db", NULL);
+ mpr_Return(eid, mprCreateBoolVar(true));
+ return 0;
+}
+
+
+/*
+ start a ldb transaction
+ usage:
+ ok = ldb.transaction_start();
+*/
+static int ejs_ldbTransactionStart(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_context *ldb;
+ int ret;
+
+ if (argc != 0) {
+ ejsSetErrorMsg(eid, "ldb.transaction_start invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ ret = ldb_transaction_start(ldb);
+
+ mpr_Return(eid, mprCreateBoolVar(ret == 0));
+ return 0;
+}
+
+/*
+ cancel a ldb transaction
+ usage:
+ ok = ldb.transaction_cancel();
+*/
+static int ejs_ldbTransactionCancel(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_context *ldb;
+ int ret;
+
+ if (argc != 0) {
+ ejsSetErrorMsg(eid, "ldb.transaction_cancel invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ ret = ldb_transaction_cancel(ldb);
+
+ mpr_Return(eid, mprCreateBoolVar(ret == 0));
+ return 0;
+}
+
+/*
+ commit a ldb transaction
+ usage:
+ ok = ldb.transaction_commit();
+*/
+static int ejs_ldbTransactionCommit(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct ldb_context *ldb;
+ int ret;
+
+ if (argc != 0) {
+ ejsSetErrorMsg(eid, "ldb.transaction_commit invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ ret = ldb_transaction_commit(ldb);
+
+ mpr_Return(eid, mprCreateBoolVar(ret == 0));
+ return 0;
+}
+
+/*
+ commit a ldb attach a dsdb_schema from ldif files
+ usage:
+ ok = ldb.attach_dsdb_schema_from_ldif("prefixMap ldif content", "definition ldif content")
+*/
+static int ejs_ldb_attach_dsdb_schema_from_ldif(MprVarHandle eid, int argc, char **argv)
+{
+ struct ldb_context *ldb;
+ WERROR status;
+ const char *pf;
+ const char *df;
+
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "ldb.attach_dsdb_schema_from_ldif invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ pf = argv[0];
+ df = argv[1];
+
+ status = dsdb_attach_schema_from_ldif_file(ldb, pf, df);
+
+ mpr_Return(eid, mprWERROR(status));
+ return 0;
+}
+
+/*
+ set a particular invocationId against the running LDB
+ usage:
+ ok = ldb.set_ntds_invocationId("7729aa4b-f990-41ad-b81a-8b6a14090f41");
+*/
+static int ejs_ldb_set_ntds_invocationId(MprVarHandle eid, int argc, char **argv)
+{
+ struct ldb_context *ldb;
+ NTSTATUS status;
+ struct GUID guid;
+ char *guid_str;
+ bool ok;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ guid_str = argv[0];
+
+ status = GUID_from_string(guid_str, &guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to parse GUID '%s' %s\n",
+ guid_str, nt_errstr(status));
+ return -1;
+ }
+
+ ok = samdb_set_ntds_invocation_id(ldb, &guid);
+ if (!ok) {
+ ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to set cached ntds invocationId\n");
+ return -1;
+ }
+
+ mpr_Return(eid, mprCreateBoolVar(ok));
+ return 0;
+}
+
+/*
+ attach a particular ntds objectGUID against the current ldb
+ usage:
+ ok = ldb.set_ntds_objectGUID("7729aa4b-f990-41ad-b81a-8b6a14090f41");
+*/
+static int ejs_ldb_set_ntds_objectGUID(MprVarHandle eid, int argc, char **argv)
+{
+ struct ldb_context *ldb;
+ NTSTATUS status;
+ struct GUID guid;
+ char *guid_str;
+ bool ok;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ guid_str = argv[0];
+
+ status = GUID_from_string(guid_str, &guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to parse GUID '%s' %s\n",
+ guid_str, nt_errstr(status));
+ return -1;
+ }
+
+ ok = samdb_set_ntds_invocation_id(ldb, &guid);
+ if (!ok) {
+ ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to set cached ntds invocationId\n");
+ return -1;
+ }
+
+ mpr_Return(eid, mprCreateBoolVar(ok));
+ return 0;
+}
+
+/*
+ attach a particular domain SID against the current ldb
+ usage:
+ ok = ldb.set_domain_sid("S-S-1-5-21-3065342217-3567412576-2214182334");
+*/
+static int ejs_ldb_set_domain_sid(MprVarHandle eid, int argc, char **argv)
+{
+ struct ldb_context *ldb;
+ struct dom_sid *dom_sid;
+ char *dom_sid_str;
+ bool ok;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "ldb.set_domain_sid invalid arguments");
+ return -1;
+ }
+
+ ldb = ejs_get_ldb_context(eid);
+ if (ldb == NULL) {
+ return -1;
+ }
+
+ dom_sid_str = argv[0];
+
+ dom_sid = dom_sid_parse_talloc(NULL, dom_sid_str);
+ if (!dom_sid) {
+ ejsSetErrorMsg(eid, "ldb.set_domain_sid - failed to parse domain sid '%s'\n",
+ dom_sid_str);
+ return -1;
+ }
+
+ ok = samdb_set_domain_sid(ldb, dom_sid);
+ talloc_free(dom_sid);
+ if (!ok) {
+ ejsSetErrorMsg(eid, "ldb.set_domain_sid - failed to set cached ntds invocationId\n");
+ return -1;
+ }
+
+ mpr_Return(eid, mprCreateBoolVar(ok));
+ return 0;
+}
+
+/*
+ initialise ldb ejs subsystem
+*/
+static int ejs_ldb_init(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *ldb = mprInitObject(eid, "ldb", argc, argv);
+
+ mprSetStringCFunction(ldb, "connect", ejs_ldbConnect);
+ mprSetCFunction(ldb, "search", ejs_ldbSearch);
+ mprSetCFunction(ldb, "add", ejs_ldbAdd);
+ mprSetCFunction(ldb, "modify", ejs_ldbModify);
+ mprSetCFunction(ldb, "del", ejs_ldbDelete);
+ mprSetCFunction(ldb, "rename", ejs_ldbRename);
+ mprSetCFunction(ldb, "errstring", ejs_ldbErrstring);
+ mprSetCFunction(ldb, "encode", ejs_base64encode);
+ mprSetCFunction(ldb, "decode", ejs_base64decode);
+ mprSetCFunction(ldb, "dn_escape", ejs_dn_escape);
+ mprSetCFunction(ldb, "close", ejs_ldbClose);
+ mprSetCFunction(ldb, "transaction_start", ejs_ldbTransactionStart);
+ mprSetCFunction(ldb, "transaction_cancel", ejs_ldbTransactionCancel);
+ mprSetCFunction(ldb, "transaction_commit", ejs_ldbTransactionCommit);
+ mprSetStringCFunction(ldb, "attach_dsdb_schema_from_ldif",
+ ejs_ldb_attach_dsdb_schema_from_ldif);
+ mprSetStringCFunction(ldb, "set_ntds_invocationId",
+ ejs_ldb_set_ntds_invocationId);
+ mprSetStringCFunction(ldb, "set_ntds_objectGUID",
+ ejs_ldb_set_ntds_objectGUID);
+ mprSetStringCFunction(ldb, "set_domain_sid",
+ ejs_ldb_set_domain_sid);
+ mprSetVar(ldb, "SCOPE_BASE", mprCreateNumberVar(LDB_SCOPE_BASE));
+ mprSetVar(ldb, "SCOPE_ONE", mprCreateNumberVar(LDB_SCOPE_ONELEVEL));
+ mprSetVar(ldb, "SCOPE_SUBTREE", mprCreateNumberVar(LDB_SCOPE_SUBTREE));
+ mprSetVar(ldb, "SCOPE_DEFAULT", mprCreateNumberVar(LDB_SCOPE_DEFAULT));
+
+ return 0;
+}
+
+
+/*
+ setup C functions that be called from ejs
+*/
+NTSTATUS smb_setup_ejs_ldb(void)
+{
+ ejsDefineCFunction(-1, "ldb_init", ejs_ldb_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+ return NT_STATUS_OK;
+}
diff --git a/source4/scripting/ejs/smbcalls_options.c b/source4/scripting/ejs/smbcalls_options.c
new file mode 100644
index 0000000000..93872baa40
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_options.c
@@ -0,0 +1,193 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide a command line options parsing function for ejs
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "scripting/ejs/smbcalls.h"
+
+
+/*
+ usage:
+ options = GetOptions(argv,
+ "realm=s",
+ "enablexx",
+ "myint=i");
+
+ the special options POPT_COMMON_* options are recognised and replaced
+ with the Samba internal options
+
+ resulting parsed options are placed in the options object
+
+ additional command line arguments are placed in options.ARGV
+*/
+
+static int ejs_GetOptions(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ poptContext pc;
+ int opt;
+ struct {
+ const char *name;
+ struct poptOption *table;
+ const char *description;
+ } tables[] = {
+ { "POPT_AUTOHELP", poptHelpOptions, "Help options:" },
+ { "POPT_COMMON_SAMBA", popt_common_samba, "Common Samba options:" },
+ { "POPT_COMMON_CONNECTION", popt_common_connection, "Connection options:" },
+ { "POPT_COMMON_CREDENTIALS", popt_common_credentials, "Authentication options:" },
+ { "POPT_COMMON_VERSION", popt_common_version, "Common Samba options:" }
+ };
+
+ struct MprVar *options = mprInitObject(eid, "options", 0, NULL);
+
+ TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
+ struct poptOption *long_options = NULL;
+ int i, num_options = 0;
+ int opt_argc;
+ const char **opt_argv;
+ const char **opt_names = NULL;
+ const int BASE_OPTNUM = 0x100000;
+
+ /* validate arguments */
+ if (argc < 1 || argv[0]->type != MPR_TYPE_OBJECT) {
+ ejsSetErrorMsg(eid, "GetOptions invalid arguments");
+ return -1;
+ }
+
+ opt_argv = mprToArray(tmp_ctx, argv[0]);
+ opt_argc = str_list_length(opt_argv);
+
+ long_options = talloc_array(tmp_ctx, struct poptOption, 1);
+ if (long_options == NULL) {
+ return -1;
+ }
+
+ /* create the long_options array */
+ for (i=1;i<argc;i++) {
+ const char *optstr = mprToString(argv[i]);
+ int t, opt_type = POPT_ARG_NONE;
+ const char *s;
+ if (argv[i]->type != MPR_TYPE_STRING) {
+ ejsSetErrorMsg(eid, "GetOptions string argument");
+ return -1;
+ }
+
+ long_options = talloc_realloc(tmp_ctx, long_options,
+ struct poptOption, num_options+2);
+ if (long_options == NULL) {
+ return -1;
+ }
+ ZERO_STRUCT(long_options[num_options]);
+
+ /* see if its one of the special samba option tables */
+ for (t=0;t<ARRAY_SIZE(tables);t++) {
+ if (strcmp(tables[t].name, optstr) == 0) {
+ break;
+ }
+ }
+ if (t < ARRAY_SIZE(tables)) {
+ opt_names = str_list_add(opt_names, optstr);
+ talloc_steal(tmp_ctx, opt_names);
+ long_options[num_options].argInfo = POPT_ARG_INCLUDE_TABLE;
+ long_options[num_options].arg = tables[t].table;
+ long_options[num_options].descrip = tables[t].description;
+ num_options++;
+ continue;
+ }
+
+ s = strchr(optstr, '=');
+ if (s) {
+ char *name = talloc_strndup(tmp_ctx, optstr, (int)(s-optstr));
+ opt_names = str_list_add(opt_names, name);
+ if (s[1] == 's') {
+ opt_type = POPT_ARG_STRING;
+ } else if (s[1] == 'i') {
+ opt_type = POPT_ARG_INT;
+ } else {
+ ejsSetErrorMsg(eid, "GetOptions invalid option type");
+ return -1;
+ }
+ talloc_free(name);
+ } else {
+ opt_names = str_list_add(opt_names, optstr);
+ }
+ talloc_steal(tmp_ctx, opt_names);
+ if (strlen(opt_names[num_options]) == 1) {
+ long_options[num_options].shortName = opt_names[num_options][0];
+ } else {
+ long_options[num_options].longName = opt_names[num_options];
+ }
+ long_options[num_options].argInfo = opt_type;
+ long_options[num_options].val = num_options + BASE_OPTNUM;
+ num_options++;
+ }
+
+ ZERO_STRUCT(long_options[num_options]);
+
+ pc = poptGetContext("smbscript", opt_argc, opt_argv, long_options, 0);
+
+ /* parse the options */
+ while((opt = poptGetNextOpt(pc)) != -1) {
+ const char *arg;
+
+ if (opt < BASE_OPTNUM || opt >= num_options + BASE_OPTNUM) {
+ char *err;
+ err = talloc_asprintf(tmp_ctx, "%s: %s",
+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
+ poptStrerror(opt));
+ mprSetVar(options, "ERROR", mprString(err));
+ talloc_free(tmp_ctx);
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ opt -= BASE_OPTNUM;
+ arg = poptGetOptArg(pc);
+ if (arg == NULL) {
+ mprSetVar(options, opt_names[opt], mprCreateBoolVar(1));
+ } else if (long_options[opt].argInfo == POPT_ARG_INT) {
+ int v = strtol(arg, NULL, 0);
+ mprSetVar(options, opt_names[opt], mprCreateIntegerVar(v));
+ } else {
+ mprSetVar(options, opt_names[opt], mprString(arg));
+ }
+ }
+
+ /* setup options.argv list */
+ mprSetVar(options, "ARGV", mprList("ARGV", poptGetArgs(pc)));
+
+ poptFreeContext(pc);
+
+ talloc_free(tmp_ctx);
+
+ /* setup methods */
+ mprSetCFunction(options, "get_credentials", ejs_credentials_cmdline);
+
+ return 0;
+}
+
+
+
+/*
+ setup C functions that be called from ejs
+*/
+void smb_setup_ejs_options(void)
+{
+ ejsDefineCFunction(-1, "GetOptions", ejs_GetOptions, NULL, MPR_VAR_SCRIPT_HANDLE);
+}
diff --git a/source4/scripting/ejs/smbcalls_string.c b/source4/scripting/ejs/smbcalls_string.c
new file mode 100644
index 0000000000..541303ff2d
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_string.c
@@ -0,0 +1,529 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide access to string functions
+
+ Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Jelmer Vernooij 2005 (substr)
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "scripting/ejs/smbcalls.h"
+#include "lib/appweb/ejs/ejs.h"
+
+/*
+ usage:
+ var len = strlen(str);
+*/
+static int ejs_strlen(MprVarHandle eid, int argc, char **argv)
+{
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "strlen invalid arguments");
+ return -1;
+ }
+ mpr_Return(eid, mprCreateIntegerVar(strlen_m(argv[0])));
+ return 0;
+}
+
+/*
+ usage:
+ var s = strlower("UPPER");
+*/
+static int ejs_strlower(MprVarHandle eid, int argc, char **argv)
+{
+ char *s;
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "strlower invalid arguments");
+ return -1;
+ }
+ s = strlower_talloc(mprMemCtx(), argv[0]);
+ mpr_Return(eid, mprString(s));
+ talloc_free(s);
+ return 0;
+}
+
+/*
+ usage:
+ var s = strupper("lower");
+*/
+static int ejs_strupper(MprVarHandle eid, int argc, char **argv)
+{
+ char *s;
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "strupper invalid arguments");
+ return -1;
+ }
+ s = strupper_talloc(mprMemCtx(), argv[0]);
+ mpr_Return(eid, mprString(s));
+ talloc_free(s);
+ return 0;
+}
+
+/*
+ usage:
+ var s = strstr(string, substring);
+*/
+static int ejs_strstr(MprVarHandle eid, int argc, char **argv)
+{
+ char *s;
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "strstr invalid arguments");
+ return -1;
+ }
+ s = strstr(argv[0], argv[1]);
+ mpr_Return(eid, mprString(s));
+ return 0;
+}
+
+/*
+ usage:
+ var s = strspn(string, legal_chars_string);
+*/
+static int ejs_strspn(MprVarHandle eid, int argc, char **argv)
+{
+ int len;
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "strspn invalid arguments");
+ return -1;
+ }
+ len = strspn(argv[0], argv[1]);
+ mpr_Return(eid, mprCreateIntegerVar(len));
+ return 0;
+}
+
+/*
+ usage:
+ list = split(".", "a.foo.bar");
+ list = split(".", "a.foo.bar", count);
+
+ count is an optional count of how many splits to make
+
+ NOTE: does not take a regular expression, unlike perl split()
+*/
+static int ejs_split(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ const char *separator, *s;
+ char *p;
+ struct MprVar ret;
+ int count = 0, maxcount=0;
+ TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
+ if (argc < 2 ||
+ argv[0]->type != MPR_TYPE_STRING ||
+ argv[1]->type != MPR_TYPE_STRING) {
+ ejsSetErrorMsg(eid, "split invalid arguments");
+ return -1;
+ }
+ separator = mprToString(argv[0]);
+ s = mprToString(argv[1]);
+ if (argc == 3) {
+ maxcount = mprToInt(argv[2]);
+ }
+
+ ret = mprArray("list");
+
+ while ((p = strstr(s, separator))) {
+ char *s2 = talloc_strndup(tmp_ctx, s, (int)(p-s));
+ mprAddArray(&ret, count++, mprString(s2));
+ talloc_free(s2);
+ s = p + strlen(separator);
+ if (maxcount != 0 && count >= maxcount) {
+ break;
+ }
+ }
+ if (*s) {
+ mprAddArray(&ret, count++, mprString(s));
+ }
+ talloc_free(tmp_ctx);
+ mpr_Return(eid, ret);
+ return 0;
+}
+
+/*
+ usage:
+ str = substr(orig[, start_offset[, length]]);
+
+ special cases:
+ if start_offset < 0 then start_offset+=strlen(orig)
+ if length < 0 then length+=strlen(orig)-start_offset
+
+ (as found in many other languages)
+*/
+static int ejs_substr(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ int start_offset = 0;
+ int length = 0;
+ const char *orig;
+ char *target;
+
+ if (argc < 1 || argc > 3 ||
+ argv[0]->type != MPR_TYPE_STRING) {
+ ejsSetErrorMsg(eid, "substr invalid arguments");
+ return -1;
+ }
+
+ if (argc == 1) {
+ mpr_Return(eid, *argv[0]);
+ return 0;
+ }
+
+ orig = mprToString(argv[0]);
+ start_offset = mprToInt(argv[1]);
+ length = strlen(orig);
+ if (start_offset < 0) start_offset += strlen(orig);
+ if (start_offset < 0 || start_offset > strlen(orig)) {
+ ejsSetErrorMsg(eid, "substr arg 2 out of bounds ([%s], %d)", orig, start_offset);
+ return -1;
+ }
+
+ if (argc == 3) {
+ length = mprToInt(argv[2]);
+ if (length < 0) length += strlen(orig) - start_offset;
+ if (length < 0 || length+start_offset > strlen(orig)) {
+ ejsSetErrorMsg(eid, "substr arg 3 out of bounds ([%s], %d, %d)", orig, start_offset, length);
+ return -1;
+ }
+ }
+
+ target = talloc_strndup(mprMemCtx(), orig+start_offset, length);
+
+ mpr_Return(eid, mprString(target));
+
+ talloc_free(target);
+
+ return 0;
+}
+
+/*
+ usage:
+ str = join("DC=", list);
+*/
+static int ejs_join(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ int i;
+ const char *separator;
+ char *ret = NULL;
+ const char **list;
+ TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
+ if (argc != 2 ||
+ argv[0]->type != MPR_TYPE_STRING ||
+ argv[1]->type != MPR_TYPE_OBJECT) {
+ ejsSetErrorMsg(eid, "join invalid arguments");
+ return -1;
+ }
+
+ separator = mprToString(argv[0]);
+ list = mprToArray(tmp_ctx, argv[1]);
+
+ if (list == NULL || list[0] == NULL) {
+ talloc_free(tmp_ctx);
+ mpr_Return(eid, mprString(NULL));
+ return 0;
+ }
+
+ ret = talloc_strdup(tmp_ctx, list[0]);
+ if (ret == NULL) {
+ goto failed;
+ }
+ for (i=1;list[i];i++) {
+ ret = talloc_asprintf_append_buffer(ret, "%s%s", separator, list[i]);
+ if (ret == NULL) {
+ goto failed;
+ }
+ }
+ mpr_Return(eid, mprString(ret));
+ talloc_free(tmp_ctx);
+ return 0;
+failed:
+ ejsSetErrorMsg(eid, "out of memory");
+ return -1;
+}
+
+
+/*
+ blergh, C certainly makes this hard!
+ usage:
+ str = sprintf("i=%d s=%7s", 7, "foo");
+*/
+typedef char *(*_asprintf_append_t)(char *, const char *, ...);
+static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ const char *format;
+ const char *p;
+ char *ret;
+ int a = 1;
+ _asprintf_append_t _asprintf_append;
+ TALLOC_CTX *tmp_ctx;
+ if (argc < 1 || argv[0]->type != MPR_TYPE_STRING) {
+ ejsSetErrorMsg(eid, "sprintf invalid arguments");
+ return -1;
+ }
+ format = mprToString(argv[0]);
+ tmp_ctx = talloc_new(mprMemCtx());
+ ret = talloc_strdup(tmp_ctx, "");
+
+ /* avoid all the format string warnings */
+ _asprintf_append = (_asprintf_append_t)talloc_asprintf_append_buffer;
+
+ /*
+ hackity hack ...
+ */
+ while ((p = strchr(format, '%'))) {
+ char *fmt2;
+ int len, len_count=0;
+ char *tstr;
+ ret = talloc_asprintf_append_buffer(ret, "%*.*s",
+ (int)(p-format), (int)(p-format),
+ format);
+ if (ret == NULL) goto failed;
+ format += (int)(p-format);
+ len = strcspn(p+1, "dxuiofgGpXeEFcs%") + 1;
+ fmt2 = talloc_strndup(tmp_ctx, p, len+1);
+ if (fmt2 == NULL) goto failed;
+ len_count = count_chars(fmt2, '*');
+ /* find the type string */
+ tstr = &fmt2[len];
+ while (tstr > fmt2 && isalpha((unsigned char)tstr[-1])) {
+ tstr--;
+ }
+ if (strcmp(tstr, "%") == 0) {
+ ret = talloc_asprintf_append_buffer(ret, "%%");
+ if (ret == NULL) {
+ goto failed;
+ }
+ format += len+1;
+ continue;
+ }
+ if (len_count > 2 ||
+ argc < a + len_count + 1) {
+ ejsSetErrorMsg(eid, "sprintf: not enough arguments for format");
+ goto failed;
+ }
+#define FMT_ARG(fn, type) do { \
+ switch (len_count) { \
+ case 0: \
+ ret = _asprintf_append(ret, fmt2, \
+ (type)fn(argv[a])); \
+ break; \
+ case 1: \
+ ret = _asprintf_append(ret, fmt2, \
+ (int)mprVarToNumber(argv[a]), \
+ (type)fn(argv[a+1])); \
+ break; \
+ case 2: \
+ ret = _asprintf_append(ret, fmt2, \
+ (int)mprVarToNumber(argv[a]), \
+ (int)mprVarToNumber(argv[a+1]), \
+ (type)fn(argv[a+2])); \
+ break; \
+ } \
+ a += len_count + 1; \
+ if (ret == NULL) { \
+ goto failed; \
+ } \
+} while (0)
+
+ if (strcmp(tstr, "s")==0) FMT_ARG(mprToString, const char *);
+ else if (strcmp(tstr, "c")==0) FMT_ARG(*mprToString, char);
+ else if (strcmp(tstr, "d")==0) FMT_ARG(mprVarToNumber, int);
+ else if (strcmp(tstr, "ld")==0) FMT_ARG(mprVarToNumber, long);
+ else if (strcmp(tstr, "lld")==0) FMT_ARG(mprVarToNumber, long long);
+ else if (strcmp(tstr, "x")==0) FMT_ARG(mprVarToNumber, int);
+ else if (strcmp(tstr, "lx")==0) FMT_ARG(mprVarToNumber, long);
+ else if (strcmp(tstr, "llx")==0) FMT_ARG(mprVarToNumber, long long);
+ else if (strcmp(tstr, "X")==0) FMT_ARG(mprVarToNumber, int);
+ else if (strcmp(tstr, "lX")==0) FMT_ARG(mprVarToNumber, long);
+ else if (strcmp(tstr, "llX")==0) FMT_ARG(mprVarToNumber, long long);
+ else if (strcmp(tstr, "u")==0) FMT_ARG(mprVarToNumber, int);
+ else if (strcmp(tstr, "lu")==0) FMT_ARG(mprVarToNumber, long);
+ else if (strcmp(tstr, "llu")==0) FMT_ARG(mprVarToNumber, long long);
+ else if (strcmp(tstr, "i")==0) FMT_ARG(mprVarToNumber, int);
+ else if (strcmp(tstr, "li")==0) FMT_ARG(mprVarToNumber, long);
+ else if (strcmp(tstr, "lli")==0) FMT_ARG(mprVarToNumber, long long);
+ else if (strcmp(tstr, "o")==0) FMT_ARG(mprVarToNumber, int);
+ else if (strcmp(tstr, "lo")==0) FMT_ARG(mprVarToNumber, long);
+ else if (strcmp(tstr, "llo")==0) FMT_ARG(mprVarToNumber, long long);
+ else if (strcmp(tstr, "f")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "lf")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "g")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "lg")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "e")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "le")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "E")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "lE")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "F")==0) FMT_ARG(mprVarToFloat, double);
+ else if (strcmp(tstr, "lF")==0) FMT_ARG(mprVarToFloat, double);
+ else {
+ ejsSetErrorMsg(eid, "sprintf: unknown format string '%s'", fmt2);
+ goto failed;
+ }
+ format += len+1;
+ }
+
+ ret = talloc_asprintf_append_buffer(ret, "%s", format);
+ mpr_Return(eid, mprString(ret));
+ talloc_free(tmp_ctx);
+ return 0;
+
+failed:
+ talloc_free(tmp_ctx);
+ return -1;
+}
+
+/*
+ used to build your own print function
+ str = vsprintf(args);
+*/
+static int ejs_vsprintf(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar **args, *len, *v;
+ int i, ret, length;
+ if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) {
+ ejsSetErrorMsg(eid, "vsprintf invalid arguments");
+ return -1;
+ }
+ v = argv[0];
+ len = mprGetProperty(v, "length", NULL);
+ if (len == NULL) {
+ ejsSetErrorMsg(eid, "vsprintf takes an array");
+ return -1;
+ }
+ length = mprToInt(len);
+ args = talloc_array(mprMemCtx(), struct MprVar *, length);
+ if (args == NULL) {
+ return -1;
+ }
+
+ for (i=0;i<length;i++) {
+ char idx[16];
+ mprItoa(i, idx, sizeof(idx));
+ args[i] = mprGetProperty(v, idx, NULL);
+ }
+
+ ret = ejs_sprintf(eid, length, args);
+ talloc_free(args);
+ return ret;
+}
+
+
+/*
+ encode a string, replacing all non-alpha with %02x form
+*/
+static int ejs_encodeURIComponent(MprVarHandle eid, int argc, char **argv)
+{
+ int i, j, count=0;
+ const char *s;
+ char *ret;
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "encodeURIComponent invalid arguments");
+ return -1;
+ }
+
+ s = argv[0];
+
+ for (i=0;s[i];i++) {
+ if (!isalnum(s[i])) count++;
+ }
+
+ ret = talloc_array(mprMemCtx(), char, i + count*2 + 1);
+ if (ret == NULL) {
+ return -1;
+ }
+ for (i=j=0;s[i];i++,j++) {
+ if (!isalnum(s[i])) {
+ snprintf(ret+j, 4, "%%%02X", (unsigned)s[i]);
+ j += 2;
+ } else {
+ ret[j] = s[i];
+ }
+ }
+ ret[j] = 0;
+ mpr_Return(eid, mprString(ret));
+ talloc_free(ret);
+ return 0;
+}
+
+/*
+ encode a string, replacing all non-alpha of %02x form
+*/
+static int ejs_decodeURIComponent(MprVarHandle eid, int argc, char **argv)
+{
+ int i, j, count=0;
+ const char *s;
+ char *ret;
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "decodeURIComponent invalid arguments");
+ return -1;
+ }
+
+ s = argv[0];
+
+ ret = talloc_array(mprMemCtx(), char, strlen(s) + 1);
+ if (ret == NULL) {
+ return -1;
+ }
+
+ for (i=j=0;s[i];i++,j++) {
+ if (s[i] == '%') {
+ unsigned c;
+ if (sscanf(s+i+1, "%02X", &c) != 1) {
+ ejsSetErrorMsg(eid, "decodeURIComponent bad format");
+ return -1;
+ }
+ ret[j] = c;
+ i += 2;
+ } else {
+ ret[j] = s[i];
+ }
+ if (!isalnum(s[i])) count++;
+ }
+
+ ret[j] = 0;
+ mpr_Return(eid, mprString(ret));
+ talloc_free(ret);
+ return 0;
+}
+
+/*
+ initialise string ejs subsystem
+*/
+static int ejs_string_init(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *obj = mprInitObject(eid, "string", argc, argv);
+
+ mprSetCFunction(obj, "substr", ejs_substr);
+ mprSetStringCFunction(obj, "strlen", ejs_strlen);
+ mprSetStringCFunction(obj, "strlower", ejs_strlower);
+ mprSetStringCFunction(obj, "strupper", ejs_strupper);
+ mprSetStringCFunction(obj, "strstr", ejs_strstr);
+ mprSetStringCFunction(obj, "strspn", ejs_strspn);
+ mprSetCFunction(obj, "split", ejs_split);
+ mprSetCFunction(obj, "join", ejs_join);
+ mprSetCFunction(obj, "sprintf", ejs_sprintf);
+ mprSetCFunction(obj, "vsprintf", ejs_vsprintf);
+ mprSetStringCFunction(obj, "encodeURIComponent", ejs_encodeURIComponent);
+ mprSetStringCFunction(obj, "decodeURIComponent", ejs_decodeURIComponent);
+
+ return 0;
+}
+
+/*
+ setup C functions that be called from ejs
+*/
+NTSTATUS smb_setup_ejs_string(void)
+{
+ ejsDefineCFunction(-1, "string_init", ejs_string_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+ return NT_STATUS_OK;
+}
diff --git a/source4/scripting/ejs/smbcalls_sys.c b/source4/scripting/ejs/smbcalls_sys.c
new file mode 100644
index 0000000000..00599a55bc
--- /dev/null
+++ b/source4/scripting/ejs/smbcalls_sys.c
@@ -0,0 +1,494 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provide access to system functions
+
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "scripting/ejs/smbcalls.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "lib/ldb/include/ldb.h"
+#include "system/time.h"
+#include "system/network.h"
+#include "lib/socket/netif.h"
+
+/*
+ return the list of configured network interfaces
+*/
+static int ejs_sys_interfaces(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ int i, count;
+ struct MprVar ret = mprArray("interfaces");
+ struct interface *ifaces;
+
+ load_interfaces(NULL, lp_interfaces(mprLpCtx()), &ifaces);
+
+ count = iface_count(ifaces);
+ for (i=0;i<count;i++) {
+ mprAddArray(&ret, i, mprString(iface_n_ip(ifaces, i)));
+ }
+
+ talloc_free(ifaces);
+ mpr_Return(eid, ret);
+ return 0;
+}
+
+/*
+ return the hostname from gethostname()
+*/
+static int ejs_sys_hostname(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ char name[200];
+ if (gethostname(name, sizeof(name)-1) == -1) {
+ ejsSetErrorMsg(eid, "gethostname failed - %s", strerror(errno));
+ return -1;
+ }
+ mpr_Return(eid, mprString(name));
+ return 0;
+}
+
+
+/*
+ return current time as seconds and microseconds
+*/
+static int ejs_sys_gettimeofday(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct timeval tv = timeval_current();
+ struct MprVar v = mprObject("timeval");
+ struct MprVar sec = mprCreateIntegerVar(tv.tv_sec);
+ struct MprVar usec = mprCreateIntegerVar(tv.tv_usec);
+
+ mprCreateProperty(&v, "sec", &sec);
+ mprCreateProperty(&v, "usec", &usec);
+ mpr_Return(eid, v);
+ return 0;
+}
+
+/*
+ return current time as a 64 bit nttime value
+*/
+static int ejs_sys_nttime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct timeval tv = timeval_current();
+ struct MprVar v = mprCreateNumberVar(timeval_to_nttime(&tv));
+ mpr_Return(eid, v);
+ return 0;
+}
+
+/*
+ return time as a 64 bit nttime value from a 32 bit time_t value
+*/
+static int ejs_sys_unix2nttime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ NTTIME nt;
+ struct MprVar v;
+ if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_unix2nttime invalid arguments");
+ return -1;
+ }
+ unix_to_nt_time(&nt, mprVarToNumber(argv[0]));
+ v = mprCreateNumberVar(nt);
+ mpr_Return(eid, v);
+ return 0;
+}
+
+/*
+ return the GMT time represented by the struct tm argument, as a time_t value
+*/
+static int ejs_sys_gmmktime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *o;
+ struct tm tm;
+ if (argc != 1 || !mprVarIsObject(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_gmmktime invalid arguments");
+ return -1;
+ }
+
+ o = argv[0];
+#define TM_EL(n) tm.n = mprVarToNumber(mprGetProperty(o, #n, NULL))
+ TM_EL(tm_sec);
+ TM_EL(tm_min);
+ TM_EL(tm_hour);
+ TM_EL(tm_mday);
+ TM_EL(tm_mon);
+ TM_EL(tm_year);
+ TM_EL(tm_wday);
+ TM_EL(tm_yday);
+ TM_EL(tm_isdst);
+#undef TM_EL
+
+ mpr_Return(eid, mprCreateIntegerVar(mktime(&tm)));
+ return 0;
+}
+
+/*
+ return the given time as a gmtime structure
+*/
+static int ejs_sys_gmtime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ time_t t;
+ struct MprVar ret;
+ struct tm *tm;
+ if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_gmtime invalid arguments");
+ return -1;
+ }
+ t = (time_t) mprVarToNumber(argv[0]);
+ tm = gmtime(&t);
+ if (tm == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ ret = mprObject("gmtime");
+#define TM_EL(n) mprSetVar(&ret, #n, mprCreateIntegerVar(tm->n))
+ TM_EL(tm_sec);
+ TM_EL(tm_min);
+ TM_EL(tm_hour);
+ TM_EL(tm_mday);
+ TM_EL(tm_mon);
+ TM_EL(tm_year);
+ TM_EL(tm_wday);
+ TM_EL(tm_yday);
+ TM_EL(tm_isdst);
+#undef TM_EL
+
+ mpr_Return(eid, ret);
+ return 0;
+}
+
+/*
+ return the given NT time as a time_t value
+*/
+static int ejs_sys_nttime2unix(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ time_t t;
+ struct MprVar v;
+ if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_ntgmtime invalid arguments");
+ return -1;
+ }
+ t = nt_time_to_unix(mprVarToNumber(argv[0]));
+ v = mprCreateNumberVar(t);
+ mpr_Return(eid, v);
+ return 0;
+}
+
+/*
+ return the given NT time as a gmtime structure
+*/
+static int ejs_sys_ntgmtime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ time_t t;
+ struct MprVar ret;
+ struct tm *tm;
+ if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_ntgmtime invalid arguments");
+ return -1;
+ }
+ t = nt_time_to_unix(mprVarToNumber(argv[0]));
+ tm = gmtime(&t);
+ if (tm == NULL) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ return 0;
+ }
+ ret = mprObject("gmtime");
+#define TM_EL(n) mprSetVar(&ret, #n, mprCreateIntegerVar(tm->n))
+ TM_EL(tm_sec);
+ TM_EL(tm_min);
+ TM_EL(tm_hour);
+ TM_EL(tm_mday);
+ TM_EL(tm_mon);
+ TM_EL(tm_year);
+ TM_EL(tm_wday);
+ TM_EL(tm_yday);
+ TM_EL(tm_isdst);
+#undef TM_EL
+
+ mpr_Return(eid, ret);
+ return 0;
+}
+
+/*
+ return a ldap time string from a nttime
+*/
+static int ejs_sys_ldaptime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ char *s;
+ time_t t;
+ if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_ldaptime invalid arguments");
+ return -1;
+ }
+ t = nt_time_to_unix(mprVarToNumber(argv[0]));
+ s = ldb_timestring(mprMemCtx(), t);
+ mpr_Return(eid, mprString(s));
+ talloc_free(s);
+ return 0;
+}
+
+/*
+ return a http time string from a nttime
+*/
+static int ejs_sys_httptime(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ char *s;
+ time_t t;
+ if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_httptime invalid arguments");
+ return -1;
+ }
+ t = nt_time_to_unix(mprVarToNumber(argv[0]));
+ s = http_timestring(mprMemCtx(), t);
+ mpr_Return(eid, mprString(s));
+ talloc_free(s);
+ return 0;
+}
+
+/*
+ unlink a file
+ ok = sys.unlink(fname);
+*/
+static int ejs_sys_unlink(MprVarHandle eid, int argc, char **argv)
+{
+ int ret;
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "sys_unlink invalid arguments");
+ return -1;
+ }
+ ret = unlink(argv[0]);
+ mpr_Return(eid, mprCreateBoolVar(ret == 0));
+ return 0;
+}
+
+/*
+ load a file as a string
+ usage:
+ string = sys.file_load(filename);
+*/
+static int ejs_sys_file_load(MprVarHandle eid, int argc, char **argv)
+{
+ char *s;
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "sys_file_load invalid arguments");
+ return -1;
+ }
+
+ s = file_load(argv[0], NULL, mprMemCtx());
+ mpr_Return(eid, mprString(s));
+ talloc_free(s);
+ return 0;
+}
+
+/*
+ save a file from a string
+ usage:
+ ok = sys.file_save(filename, str);
+*/
+static int ejs_sys_file_save(MprVarHandle eid, int argc, char **argv)
+{
+ bool ret;
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "sys_file_save invalid arguments");
+ return -1;
+ }
+ ret = file_save(argv[0], argv[1], strlen(argv[1]));
+ mpr_Return(eid, mprCreateBoolVar(ret));
+ return 0;
+}
+
+/*
+ mkdir()
+ usage:
+ ok = sys.mkdir(dirname, mode);
+*/
+static int ejs_sys_mkdir(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ bool ret;
+ char *name;
+ if (argc != 2) {
+ ejsSetErrorMsg(eid, "sys_mkdir invalid arguments, need mkdir(dirname, mode)");
+ return -1;
+ }
+ if (!mprVarIsString(argv[0]->type)) {
+ ejsSetErrorMsg(eid, "sys_mkdir dirname not a string");
+ return -1;
+ }
+ if (!mprVarIsNumber(argv[1]->type)) {
+ ejsSetErrorMsg(eid, "sys_mkdir mode not a number");
+ return -1;
+ }
+ mprVarToString(&name, 0, NULL, argv[0]);
+ ret = mkdir(name, mprVarToNumber(argv[1]));
+ mpr_Return(eid, mprCreateBoolVar(ret == 0));
+ return 0;
+}
+
+
+/*
+ return fields of a stat() call
+*/
+static struct MprVar mpr_stat(struct stat *st)
+{
+ struct MprVar ret;
+ ret = mprObject("stat");
+
+#define ST_EL(n) mprSetVar(&ret, #n, mprCreateNumberVar(st->n))
+ ST_EL(st_dev);
+ ST_EL(st_ino);
+ ST_EL(st_mode);
+ ST_EL(st_nlink);
+ ST_EL(st_uid);
+ ST_EL(st_gid);
+ ST_EL(st_rdev);
+ ST_EL(st_size);
+ ST_EL(st_blksize);
+ ST_EL(st_blocks);
+ ST_EL(st_atime);
+ ST_EL(st_mtime);
+ ST_EL(st_ctime);
+
+ return ret;
+}
+
+/*
+ usage:
+ var st = sys.stat(filename);
+ returns an object containing struct stat elements
+*/
+static int ejs_sys_stat(MprVarHandle eid, int argc, char **argv)
+{
+ struct stat st;
+ /* validate arguments */
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "sys.stat invalid arguments");
+ return -1;
+ }
+ if (stat(argv[0], &st) != 0) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ } else {
+ mpr_Return(eid, mpr_stat(&st));
+ }
+ return 0;
+}
+
+/*
+ usage:
+ var st = sys.lstat(filename);
+ returns an object containing struct stat elements
+*/
+static int ejs_sys_lstat(MprVarHandle eid, int argc, char **argv)
+{
+ struct stat st;
+ /* validate arguments */
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "sys.stat invalid arguments");
+ return -1;
+ }
+ if (lstat(argv[0], &st) != 0) {
+ mpr_Return(eid, mprCreateUndefinedVar());
+ } else {
+ mpr_Return(eid, mpr_stat(&st));
+ }
+ return 0;
+}
+
+/*
+ bitwise AND
+ usage:
+ var z = sys.bitAND(x, 0x70);
+*/
+static int ejs_sys_bitAND(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ int x, y, z;
+
+ if (argc != 2 ||
+ !mprVarIsNumber(argv[0]->type) ||
+ !mprVarIsNumber(argv[1]->type)) {
+ ejsSetErrorMsg(eid, "bitand invalid arguments");
+ return -1;
+ }
+ x = mprToInt(argv[0]);
+ y = mprToInt(argv[1]);
+ z = x & y;
+
+ mpr_Return(eid, mprCreateIntegerVar(z));
+ return 0;
+}
+
+/*
+ bitwise OR
+ usage:
+ var z = sys.bitOR(x, 0x70);
+*/
+static int ejs_sys_bitOR(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ int x, y, z;
+
+ if (argc != 2 ||
+ !mprVarIsNumber(argv[0]->type) ||
+ !mprVarIsNumber(argv[1]->type)) {
+ ejsSetErrorMsg(eid, "bitand invalid arguments");
+ return -1;
+ }
+ x = mprToInt(argv[0]);
+ y = mprToInt(argv[1]);
+ z = x | y;
+
+ mpr_Return(eid, mprCreateIntegerVar(z));
+ return 0;
+}
+
+/*
+ initialise sys ejs subsystem
+*/
+static int ejs_sys_init(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ struct MprVar *obj = mprInitObject(eid, "sys", argc, argv);
+
+ mprSetCFunction(obj, "interfaces", ejs_sys_interfaces);
+ mprSetCFunction(obj, "hostname", ejs_sys_hostname);
+ mprSetCFunction(obj, "nttime", ejs_sys_nttime);
+ mprSetCFunction(obj, "gettimeofday", ejs_sys_gettimeofday);
+ mprSetCFunction(obj, "unix2nttime", ejs_sys_unix2nttime);
+ mprSetCFunction(obj, "gmmktime", ejs_sys_gmmktime);
+ mprSetCFunction(obj, "gmtime", ejs_sys_gmtime);
+ mprSetCFunction(obj, "nttime2unix", ejs_sys_nttime2unix);
+ mprSetCFunction(obj, "ntgmtime", ejs_sys_ntgmtime);
+ mprSetCFunction(obj, "ldaptime", ejs_sys_ldaptime);
+ mprSetCFunction(obj, "httptime", ejs_sys_httptime);
+ mprSetCFunction(obj, "mkdir", ejs_sys_mkdir);
+ mprSetStringCFunction(obj, "unlink", ejs_sys_unlink);
+ mprSetStringCFunction(obj, "file_load", ejs_sys_file_load);
+ mprSetStringCFunction(obj, "file_save", ejs_sys_file_save);
+ mprSetStringCFunction(obj, "stat", ejs_sys_stat);
+ mprSetStringCFunction(obj, "lstat", ejs_sys_lstat);
+ mprSetCFunction(obj, "bitAND", ejs_sys_bitAND);
+ mprSetCFunction(obj, "bitOR", ejs_sys_bitOR);
+
+ return 0;
+}
+
+
+/*
+ setup C functions that be called from ejs
+*/
+NTSTATUS smb_setup_ejs_system(void)
+{
+ ejsDefineCFunction(-1, "sys_init", ejs_sys_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+ return NT_STATUS_OK;
+}
diff --git a/source4/scripting/ejs/smbscript.c b/source4/scripting/ejs/smbscript.c
new file mode 100644
index 0000000000..db9fc9affa
--- /dev/null
+++ b/source4/scripting/ejs/smbscript.c
@@ -0,0 +1,129 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Standalone client for ejs scripting.
+
+ Copyright (C) Tim Potter <tpot@samba.org> 2005
+ Copyright (C) Andrew Tridgell 2005
+
+ 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 3 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "lib/appweb/ejs/ejsInternal.h"
+#include "scripting/ejs/smbcalls.h"
+#include "auth/gensec/gensec.h"
+#include "ldb/include/ldb.h"
+#include "dynconfig/dynconfig.h"
+
+static EjsId eid;
+
+_NORETURN_ static void smbscript_ejs_exception(const char *reason)
+{
+ Ejs *ep = ejsPtr(eid);
+ ejsSetErrorMsg(eid, "%s", reason);
+ fprintf(stderr, "%s", ep->error);
+ exit(127);
+}
+
+int main(int argc, const char **argv)
+{
+ EjsHandle handle = 0;
+ MprVar result;
+ char *emsg, *script;
+ size_t script_size;
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
+ const char **argv_list = NULL;
+ const char *fname;
+ struct MprVar *return_var;
+ int exit_status, i;
+ struct loadparm_context *lp_ctx;
+
+ fault_setup(argv[0]);
+
+ global_loadparm = lp_ctx = loadparm_init(talloc_autofree_context());
+
+ if (getenv("SMB_CONF_PATH")) {
+ lp_load(lp_ctx, getenv("SMB_CONF_PATH"));
+ } else {
+ lp_load(lp_ctx, dyn_CONFIGFILE);
+ }
+
+ gensec_init(lp_ctx);
+ mprSetCtx(mem_ctx);
+
+
+ if (argc < 2) {
+ fprintf(stderr, "You must supply a script name\n");
+ exit(1);
+ }
+
+ fname = argv[1];
+
+ if (ejsOpen(NULL, NULL, NULL) != 0) {
+ fprintf(stderr, "smbscript: ejsOpen(): unable to initialise "
+ "EJS subsystem\n");
+ exit(127);
+ }
+
+ smb_setup_ejs_functions(smbscript_ejs_exception);
+
+ if ((eid = ejsOpenEngine(handle, 0)) == (EjsId)-1) {
+ fprintf(stderr, "smbscript: ejsOpenEngine(): unable to "
+ "initialise an EJS engine\n");
+ exit(127);
+ }
+
+ /* setup ARGV[] in the ejs environment */
+ for (i=1;argv[i];i++) {
+ argv_list = str_list_add(argv_list, argv[i]);
+ }
+ talloc_steal(mem_ctx, argv_list);
+ mprSetVar(ejsGetGlobalObject(eid), "ARGV", mprList("ARGV", argv_list));
+
+ /* load the script and advance past interpreter line*/
+ script = file_load(fname, &script_size, mem_ctx);
+
+ if (!script) {
+ fprintf(stderr, "Unable to load script from '%s'\n", fname);
+ exit(1);
+ }
+
+ /* allow scriptable js */
+ if (strncmp(script, "#!", 2) == 0) {
+ script += strcspn(script, "\r\n");
+ script += strspn(script, "\r\n");
+ }
+ /* and this copes with the ugly exec hack */
+ if (strncmp(script, "exec ", 5) == 0) {
+ script += strcspn(script, "\r\n");
+ script += strspn(script, "\r\n");
+ }
+
+ /* run the script */
+ if (ejsEvalScript(eid, script, &result, &emsg) == -1) {
+ fprintf(stderr, "smbscript: ejsEvalScript(): %s\n", emsg);
+ exit(127);
+ }
+
+ return_var = ejsGetReturnValue(eid);
+ exit_status = mprVarToNumber(return_var);
+
+ ejsClose();
+
+ talloc_free(mem_ctx);
+
+ return exit_status;
+}