summaryrefslogtreecommitdiff
path: root/source4/scripting/ejs
diff options
context:
space:
mode:
Diffstat (limited to 'source4/scripting/ejs')
-rw-r--r--source4/scripting/ejs/ejsnet/mpr_user.c165
-rw-r--r--source4/scripting/ejs/ejsnet/net_ctx.c209
-rw-r--r--source4/scripting/ejs/ejsnet/net_user.c277
3 files changed, 651 insertions, 0 deletions
diff --git a/source4/scripting/ejs/ejsnet/mpr_user.c b/source4/scripting/ejs/ejsnet/mpr_user.c
new file mode 100644
index 0000000000..9a49262dc6
--- /dev/null
+++ b/source4/scripting/ejs/ejsnet/mpr_user.c
@@ -0,0 +1,165 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provides interfaces to libnet calls from ejs scripts
+
+ Copyright (C) Rafal Szczesniak 2005-2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "libnet/libnet.h"
+#include "scripting/ejs/smbcalls.h"
+#include "events/events.h"
+#include "auth/credentials/credentials.h"
+
+
+/*
+ Properties:
+ UserInfo.AccountName
+ UserInfo.FullName
+ UserInfo.Description
+ UserInfo.HomeDirectory
+ UserInfo.HomeDrive
+ UserInfo.Comment
+ UserInfo.LogonScript
+ UserInfo.AcctExpiry
+ UserInfo.AllowPasswordChange
+ UserInfo.ForcePasswordChange
+ */
+struct MprVar mprCreateUserInfo(TALLOC_CTX *mem_ctx, struct libnet_UserInfo *info)
+{
+ const char *name = "UserInfo";
+ NTSTATUS status;
+ struct MprVar mprUserInfo;
+ struct MprVar mprAccountName, mprFullName, mprDescription;
+ struct MprVar mprHomeDir, mprHomeDrive, mprComment;
+ struct MprVar mprLogonScript;
+ struct MprVar mprAcctExpiry, mprAllowPassChange, mprForcePassChange;
+
+ if (info == NULL || mem_ctx == NULL) {
+ mprUserInfo = mprCreateNullVar();
+ goto done;
+ }
+
+ mprUserInfo = mprObject(name);
+
+ mprAccountName = mprString(info->out.account_name);
+ mprFullName = mprString(info->out.full_name);
+ mprDescription = mprString(info->out.description);
+ mprHomeDir = mprString(info->out.home_directory);
+ mprHomeDrive = mprString(info->out.home_drive);
+ mprComment = mprString(info->out.comment);
+ mprLogonScript = mprString(info->out.logon_script);
+ mprAcctExpiry = mprString(timestring(mem_ctx, info->out.acct_expiry->tv_sec));
+ mprAllowPassChange = mprString(timestring(mem_ctx, info->out.allow_password_change->tv_sec));
+ mprForcePassChange = mprString(timestring(mem_ctx, info->out.force_password_change->tv_sec));
+
+ status = mprSetVar(&mprUserInfo, "AccountName", mprAccountName);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "FullName", mprFullName);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "Description", mprDescription);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "HomeDirectory", mprHomeDir);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "HomeDrive", mprHomeDrive);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "Comment", mprComment);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "LogonScript", mprLogonScript);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "AcctExpiry", mprAcctExpiry);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "AllowPasswordChange", mprAllowPassChange);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprUserInfo, "ForcePasswordChange", mprForcePassChange);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+
+done:
+ return mprUserInfo;
+}
+
+
+/*
+ Properties:
+ UserListCtx.Users[]
+ UserListCtx.ResumeIndex
+ UserListCtx.Count
+ */
+struct MprVar mprUserListCtx(TALLOC_CTX *mem_ctx, struct libnet_UserList *list)
+{
+ const char *name = "UserListCtx";
+ NTSTATUS status;
+ struct MprVar mprListCtx, mprUserList;
+ struct MprVar mprUser, mprSid, mprUsername;
+ int i;
+
+ if (list == NULL || mem_ctx == NULL) {
+ mprListCtx = mprCreateNullVar();
+ goto done;
+ }
+
+ mprUserList = mprArray("Users");
+ for (i = 0; i < list->out.count; i++) {
+ struct userlist u = list->out.users[i];
+
+ /* get userlist fields */
+ mprSid = mprString(u.sid);
+ mprUsername = mprString(u.username);
+
+ /* create userlist object */
+ mprUser = mprObject("User");
+ mprSetVar(&mprUser, "Username", mprUsername);
+ mprSetVar(&mprUser, "SID", mprSid);
+
+ /* add the object to the array being constructed */
+ mprAddArray(&mprUserList, 0, mprUser);
+ }
+
+ mprListCtx = mprObject(name);
+ status = mprSetVar(&mprListCtx, "Users", mprUserList);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprListCtx, "Count", mprCreateIntegerVar(list->out.count));
+ if (!NT_STATUS_IS_OK(status)) goto done;
+ status = mprSetVar(&mprListCtx, "ResumeIndex", mprCreateIntegerVar((int)list->out.resume_index));
+ if (!NT_STATUS_IS_OK(status)) goto done;
+
+done:
+ return mprListCtx;
+}
+
+
+/*
+ Returns UserListCtx.ResumeIndex out of passed UserListCtx
+ */
+unsigned int mprListGetResumeIndex(struct MprVar *listCtx)
+{
+ NTSTATUS status;
+ unsigned int resume = 0;
+ struct MprVar *mprResumeIndex;
+ if (listCtx == NULL) return 0;
+
+ mprResumeIndex = listCtx;
+ status = mprGetVar(&mprResumeIndex, "ResumeIndex");
+ if (!NT_STATUS_IS_OK(status)) goto done;
+
+ resume = (unsigned int) mprVarToInteger(mprResumeIndex);
+
+done:
+ return resume;
+}
diff --git a/source4/scripting/ejs/ejsnet/net_ctx.c b/source4/scripting/ejs/ejsnet/net_ctx.c
new file mode 100644
index 0000000000..42c64540fb
--- /dev/null
+++ b/source4/scripting/ejs/ejsnet/net_ctx.c
@@ -0,0 +1,209 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provides interfaces to libnet calls from ejs scripts
+
+ Copyright (C) Rafal Szczesniak 2005-2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "scripting/ejs/smbcalls.h"
+#include "libnet/libnet.h"
+#include "events/events.h"
+#include "auth/credentials/credentials.h"
+
+
+int ejs_net_userman(MprVarHandle eid, int argc, struct MprVar** argv);
+
+static int ejs_net_join_domain(MprVarHandle eid, int argc, struct MprVar **argv);
+static int ejs_net_samsync_ldb(MprVarHandle eid, int argc, struct MprVar **argv);
+
+/*
+ Usage:
+ net = NetContext(credentials);
+*/
+
+static int ejs_net_context(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ TALLOC_CTX *event_mem_ctx = talloc_new(mprMemCtx());
+ struct cli_credentials *creds;
+ struct libnet_context *ctx;
+ struct MprVar obj;
+ struct event_context *ev;
+
+ if (!event_mem_ctx) {
+ ejsSetErrorMsg(eid, "talloc_new() failed");
+ return -1;
+ }
+ ev = event_context_find(event_mem_ctx);
+ ctx = libnet_context_init(ev);
+ /* IF we generated a new event context, it will be under here,
+ * and we need it to last as long as the libnet context, so
+ * make it a child */
+ talloc_steal(ctx, event_mem_ctx);
+
+ if (argc == 0 || (argc == 1 && argv[0]->type == MPR_TYPE_NULL)) {
+ creds = cli_credentials_init(ctx);
+ if (creds == NULL) {
+ ejsSetErrorMsg(eid, "cli_credential_init() failed");
+ talloc_free(ctx);
+ return -1;
+ }
+ cli_credentials_set_conf(creds);
+ cli_credentials_set_anonymous(creds);
+
+ } else if (argc == 1 && argv[0]->type == MPR_TYPE_OBJECT) {
+ /* get credential values from credentials object */
+ creds = mprGetPtr(argv[0], "creds");
+ if (creds == NULL) {
+ ejsSetErrorMsg(eid, "userAuth requires a 'creds' first parameter");
+ talloc_free(ctx);
+ return -1;
+ }
+
+ } else {
+ ejsSetErrorMsg(eid, "NetContext invalid arguments, this function requires an object.");
+ talloc_free(ctx);
+ return -1;
+ }
+
+ ctx->cred = creds;
+
+ obj = mprObject("NetCtx");
+ mprSetPtrChild(&obj, "ctx", ctx);
+
+ mprSetCFunction(&obj, "UserMgr", ejs_net_userman);
+ mprSetCFunction(&obj, "JoinDomain", ejs_net_join_domain);
+ mprSetCFunction(&obj, "SamSyncLdb", ejs_net_samsync_ldb);
+ mpr_Return(eid, obj);
+
+ return 0;
+}
+
+
+static int ejs_net_join_domain(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ TALLOC_CTX *mem_ctx;
+ struct libnet_context *ctx;
+ struct libnet_Join *join;
+ NTSTATUS status;
+ ctx = mprGetThisPtr(eid, "ctx");
+ mem_ctx = talloc_new(mprMemCtx());
+
+ join = talloc(mem_ctx, struct libnet_Join);
+ if (!join) {
+ talloc_free(mem_ctx);
+ return -1;
+ }
+
+ /* prepare parameters for the join */
+ join->in.netbios_name = NULL;
+ join->in.join_type = SEC_CHAN_WKSTA;
+ join->in.domain_name = cli_credentials_get_domain(ctx->cred);
+ join->in.level = LIBNET_JOIN_AUTOMATIC;
+ join->out.error_string = NULL;
+
+ if (argc == 1 && argv[0]->type == MPR_TYPE_OBJECT) {
+ MprVar *netbios_name = mprGetProperty(argv[0], "netbios_name", NULL);
+ MprVar *domain_name = mprGetProperty(argv[0], "domain_name", NULL);
+ MprVar *join_type = mprGetProperty(argv[0], "join_type", NULL);
+ if (netbios_name) {
+ join->in.netbios_name = mprToString(netbios_name);
+ }
+ if (domain_name) {
+ join->in.domain_name = mprToString(domain_name);
+ }
+ if (join_type) {
+ join->in.join_type = mprToInt(join_type);
+ }
+ }
+
+ if (!join->in.domain_name) {
+ ejsSetErrorMsg(eid, "a domain must be specified for to join");
+ talloc_free(mem_ctx);
+ return -1;
+ }
+
+ /* do the domain join */
+ status = libnet_Join(ctx, join, join);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ MprVar error_string = mprString(join->out.error_string);
+
+ mprSetPropertyValue(argv[0], "error_string", error_string);
+ mpr_Return(eid, mprCreateBoolVar(False));
+ } else {
+ mpr_Return(eid, mprCreateBoolVar(True));
+ }
+ talloc_free(mem_ctx);
+ return 0;
+}
+
+
+static int ejs_net_samsync_ldb(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ TALLOC_CTX *mem_ctx;
+ struct libnet_context *ctx;
+ struct libnet_samsync_ldb *samsync;
+ NTSTATUS status;
+ ctx = mprGetThisPtr(eid, "ctx");
+ mem_ctx = talloc_new(mprMemCtx());
+
+ samsync = talloc(mem_ctx, struct libnet_samsync_ldb);
+ if (!samsync) {
+ talloc_free(mem_ctx);
+ return -1;
+ }
+
+ /* prepare parameters for the samsync */
+ samsync->in.machine_account = NULL;
+ samsync->in.session_info = NULL;
+ samsync->in.binding_string = NULL;
+ samsync->out.error_string = NULL;
+
+ if (argc == 1 && argv[0]->type == MPR_TYPE_OBJECT) {
+ MprVar *credentials = mprGetProperty(argv[0], "machine_account", NULL);
+ MprVar *session_info = mprGetProperty(argv[0], "session_info", NULL);
+ if (credentials) {
+ samsync->in.machine_account = talloc_get_type(mprGetPtr(credentials, "creds"), struct cli_credentials);
+ }
+ if (session_info) {
+ samsync->in.session_info = talloc_get_type(mprGetPtr(session_info, "session_info"), struct auth_session_info);
+ }
+ }
+
+ /* do the domain samsync */
+ status = libnet_samsync_ldb(ctx, samsync, samsync);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ MprVar error_string = mprString(samsync->out.error_string);
+
+ mprSetPropertyValue(argv[0], "error_string", error_string);
+ mpr_Return(eid, mprCreateBoolVar(False));
+ } else {
+ mpr_Return(eid, mprCreateBoolVar(True));
+ }
+ talloc_free(mem_ctx);
+ return 0;
+}
+
+
+void ejsnet_setup(void)
+{
+ ejsDefineCFunction(-1, "NetContext", ejs_net_context, NULL, MPR_VAR_SCRIPT_HANDLE);
+}
diff --git a/source4/scripting/ejs/ejsnet/net_user.c b/source4/scripting/ejs/ejsnet/net_user.c
new file mode 100644
index 0000000000..731b4b9203
--- /dev/null
+++ b/source4/scripting/ejs/ejsnet/net_user.c
@@ -0,0 +1,277 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ provides interfaces to libnet calls from ejs scripts
+
+ Copyright (C) Rafal Szczesniak 2005-2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/appweb/ejs/ejs.h"
+#include "libnet/libnet.h"
+#include "proto.h"
+#include "scripting/ejs/smbcalls.h"
+#include "events/events.h"
+#include "auth/credentials/credentials.h"
+
+
+static int ejs_net_createuser(MprVarHandle eid, int argc, char **argv);
+static int ejs_net_deleteuser(MprVarHandle eid, int argc, char **argv);
+static int ejs_net_userinfo(MprVarHandle eid, int argc, char **argv);
+static int ejs_net_userlist(MprVarHandle eid, int argc, struct MprVar **argv);
+
+
+/*
+ Usage:
+ usrCtx = net.UserMgr(domain);
+*/
+int ejs_net_userman(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ TALLOC_CTX *mem_ctx;
+ struct libnet_context *ctx;
+ const char *userman_domain = NULL;
+ struct MprVar *obj = NULL;
+
+ ctx = mprGetThisPtr(eid, "ctx");
+ mem_ctx = talloc_new(mprMemCtx());
+
+ if (argc == 0) {
+ userman_domain = cli_credentials_get_domain(ctx->cred);
+
+ } else if (argc == 1 && mprVarIsString(argv[0]->type)) {
+ userman_domain = talloc_strdup(ctx, mprToString(argv[0]));
+
+ } else {
+ ejsSetErrorMsg(eid, "too many arguments");
+ goto done;
+ }
+
+ if (!userman_domain) {
+ ejsSetErrorMsg(eid, "a domain must be specified for user management");
+ goto done;
+ }
+
+ obj = mprInitObject(eid, "NetUsrCtx", argc, argv);
+ mprSetPtrChild(obj, "ctx", ctx);
+ mprSetPtrChild(obj, "domain", userman_domain);
+
+ mprSetStringCFunction(obj, "Create", ejs_net_createuser);
+ mprSetStringCFunction(obj, "Delete", ejs_net_deleteuser);
+ mprSetStringCFunction(obj, "Info", ejs_net_userinfo);
+ mprSetCFunction(obj, "List", ejs_net_userlist);
+
+ return 0;
+done:
+ talloc_free(mem_ctx);
+ return -1;
+}
+
+
+static int ejs_net_createuser(MprVarHandle eid, int argc, char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *mem_ctx;
+ struct libnet_context *ctx;
+ const char *userman_domain = NULL;
+ struct libnet_CreateUser req;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "argument 1 must be a string");
+ return -1;
+ }
+
+ ctx = mprGetThisPtr(eid, "ctx");
+ if (!ctx) {
+ ejsSetErrorMsg(eid, "ctx property returns null pointer");
+ return -1;
+ }
+
+ userman_domain = mprGetThisPtr(eid, "domain");
+ if (!userman_domain) {
+ ejsSetErrorMsg(eid, "domain property returns null pointer");
+ return -1;
+ }
+
+ mem_ctx = talloc_new(mprMemCtx());
+
+ req.in.domain_name = userman_domain;
+ req.in.user_name = argv[0];
+
+ status = libnet_CreateUser(ctx, mem_ctx, &req);
+ if (!NT_STATUS_IS_OK(status)) {
+ ejsSetErrorMsg(eid, "%s", req.out.error_string);
+ }
+
+ talloc_free(mem_ctx);
+ mpr_Return(eid, mprNTSTATUS(status));
+ return 0;
+}
+
+
+static int ejs_net_deleteuser(MprVarHandle eid, int argc, char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *mem_ctx;
+ struct libnet_context *ctx;
+ const char *userman_domain = NULL;
+ struct libnet_DeleteUser req;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "argument 1 must be a string");
+ return -1;
+ }
+
+ ctx = mprGetThisPtr(eid, "ctx");
+ if (!ctx) {
+ ejsSetErrorMsg(eid, "ctx property returns null pointer");
+ return -1;
+ }
+
+ userman_domain = mprGetThisPtr(eid, "domain");
+ if (!userman_domain) {
+ ejsSetErrorMsg(eid, "domain property returns null pointer");
+ return -1;
+ }
+
+ mem_ctx = talloc_new(mprMemCtx());
+
+ req.in.domain_name = userman_domain;
+ req.in.user_name = argv[0];
+
+ status = libnet_DeleteUser(ctx, mem_ctx, &req);
+ if (!NT_STATUS_IS_OK(status)) {
+ ejsSetErrorMsg(eid, "%s", req.out.error_string);
+ }
+
+ talloc_free(mem_ctx);
+ mpr_Return(eid, mprNTSTATUS(status));
+ return 0;
+}
+
+
+static int ejs_net_userinfo(MprVarHandle eid, int argc, char **argv)
+{
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+ TALLOC_CTX *mem_ctx;
+ struct libnet_context *ctx;
+ const char *userman_domain;
+ struct libnet_UserInfo req;
+ struct MprVar mprUserInfo;
+
+ if (argc != 1) {
+ ejsSetErrorMsg(eid, "argument 1 must be a string");
+ return -1;
+ }
+
+ ctx = mprGetThisPtr(eid, "ctx");
+ if (ctx == NULL) {
+ ejsSetErrorMsg(eid, "ctx property returns null pointer");
+ return -1;
+ }
+
+ userman_domain = mprGetThisPtr(eid, "domain");
+ if (userman_domain == NULL) {
+ ejsSetErrorMsg(eid, "domain property returns null pointer");
+ return -1;
+ }
+
+ mem_ctx = talloc_new(mprMemCtx());
+
+ req.in.domain_name = userman_domain;
+ req.in.user_name = argv[0];
+
+ status = libnet_UserInfo(ctx, mem_ctx, &req);
+ if (!NT_STATUS_IS_OK(status)) {
+ ejsSetErrorMsg(eid, "%s", req.out.error_string);
+
+ /* create null object to return */
+ mprUserInfo = mprCreateNullVar();
+ goto done;
+ }
+
+ /* create UserInfo object */
+ mprUserInfo = mprCreateUserInfo(ctx, &req);
+
+done:
+ talloc_free(mem_ctx);
+ mpr_Return(eid, mprUserInfo);
+ return 0;
+}
+
+
+static int ejs_net_userlist(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ struct libnet_context *ctx;
+ const char *userlist_domain;
+ struct libnet_UserList req;
+ struct MprVar mprListCtx, *mprInListCtx;
+
+ mem_ctx = talloc_new(mprMemCtx());
+
+ if (argc == 0) {
+ ejsSetErrorMsg(eid, "too little arguments");
+
+ } else if (argc == 1) {
+ if (mprVarIsObject(argv[0]->type)) {
+ /* this is a continuation call */
+ mprInListCtx = argv[0];
+ req.in.resume_index = mprListGetResumeIndex(mprInListCtx);
+
+ } else {
+ req.in.resume_index = 0;
+ }
+
+ } else {
+ ejsSetErrorMsg(eid, "too many arguments");
+ goto done;
+ }
+
+ ctx = mprGetThisPtr(eid, "ctx");
+ if (!ctx) {
+ ejsSetErrorMsg(eid, "ctx property returns null pointer");
+ return -1;
+ }
+
+ userlist_domain = mprGetThisPtr(eid, "domain");
+ if (!userlist_domain) {
+ ejsSetErrorMsg(eid, "domain property returns null pointer");
+ return -1;
+ }
+
+ req.in.domain_name = userlist_domain;
+ req.in.page_size = 10; /* TODO: this should be specified in a nicer way */
+
+ status = libnet_UserList(ctx, mem_ctx, &req);
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
+
+ ejsSetErrorMsg(eid, "%s", req.out.error_string);
+
+ mprListCtx = mprCreateNullVar();
+ goto done;
+ }
+
+ mprListCtx = mprUserListCtx(mem_ctx, &req);
+
+done:
+ talloc_free(mem_ctx);
+ mpr_Return(eid, mprListCtx);
+ return 0;
+}