wmi-1.3.16 from opsview.com
This commit is contained in:
Executable
+234
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
exec smbscript "$0" ${1+"$@"}
|
||||
/*
|
||||
Dump Samba3 data
|
||||
Copyright Jelmer Vernooij 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
options = GetOptions(ARGV,
|
||||
"POPT_AUTOHELP",
|
||||
"POPT_COMMON_SAMBA",
|
||||
"POPT_COMMON_VERSION",
|
||||
'format=s',
|
||||
'quiet', 'blank');
|
||||
|
||||
if (options == undefined) {
|
||||
println("Failed to parse options");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (options.format == undefined) {
|
||||
options.format = "summary";
|
||||
}
|
||||
|
||||
if (options.format != "summary" && options.format != "full") {
|
||||
printf("Unknown format %s\n", options.format);
|
||||
return -1;
|
||||
}
|
||||
|
||||
libinclude("base.js");
|
||||
|
||||
if (options.ARGV.length != 2) {
|
||||
println("Usage: samba3dump <libdir> <smb.conf>");
|
||||
return -1;
|
||||
}
|
||||
|
||||
function print_header(txt)
|
||||
{
|
||||
printf("\n%s\n", txt);
|
||||
println("==========================================");
|
||||
}
|
||||
|
||||
function print_samba3_policy(pol)
|
||||
{
|
||||
print_header("Account Policies");
|
||||
printf("Min password length: %d\n", pol.min_password_length);
|
||||
printf("Password history length: %d\n", pol.password_history);
|
||||
printf("User must logon to change password: %d\n", pol.user_must_logon_to_change_password);
|
||||
printf("Maximum password age: %d\n", pol.maximum_password_age);
|
||||
printf("Minimum password age: %d\n", pol.minimum_password_age);
|
||||
printf("Lockout duration: %d\n", pol.lockout_duration);
|
||||
printf("Reset Count Minutes: %d\n", pol.reset_count_minutes);
|
||||
printf("Bad Lockout Minutes: %d\n", pol.bad_lockout_minutes);
|
||||
printf("Disconnect Time: %d\n", pol.disconnect_time);
|
||||
printf("Refuse Machine Password Change: %d\n", pol.refuse_machine_password_change);
|
||||
}
|
||||
|
||||
function print_samba3_sam(samba3)
|
||||
{
|
||||
var i;
|
||||
print_header("SAM Database");
|
||||
|
||||
for (i in samba3.samaccounts) {
|
||||
var a = samba3.samaccounts[i];
|
||||
printf("%d: %s\n", a.user_rid, a.username);
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_shares(samba3)
|
||||
{
|
||||
var i, j;
|
||||
print_header("Configured shares");
|
||||
for (i in samba3.shares) {
|
||||
var s = samba3.shares[i];
|
||||
printf("--- %s ---\n", s.name);
|
||||
|
||||
for (j in s.parameters) {
|
||||
var p = s.parameters[j];
|
||||
printf("\t%s = %s\n", p.name, p.value);
|
||||
}
|
||||
|
||||
println("");
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_secrets(secrets)
|
||||
{
|
||||
var i;
|
||||
print_header("Secrets");
|
||||
|
||||
println("IPC Credentials:");
|
||||
if (secrets.ipc_cred.username_obtained)
|
||||
printf(" User: %s\n", secrets.ipc_cred.get_username);
|
||||
if (secrets.ipc_cred.password_obtained)
|
||||
printf(" Password: %s\n", secrets.ipc_cred.get_password);
|
||||
|
||||
if (secrets.ipc_cred.domain_obtained)
|
||||
printf(" Domain: %s\n\n", secrets.ipc_cred.get_domain);
|
||||
|
||||
println("LDAP passwords:");
|
||||
for (i in secrets.ldappws) {
|
||||
var pw = secrets.ldappws[i];
|
||||
printf("\t%s -> %s\n", pw.dn, pw.password);
|
||||
}
|
||||
println("");
|
||||
|
||||
println("Domains:");
|
||||
for (i in secrets.domains) {
|
||||
var d = secrets.domains[i];
|
||||
printf("\t--- %s ---\n", d.name);
|
||||
printf("\tSID: %s\n", d.sid);
|
||||
printf("\tGUID: %s\n", d.guid);
|
||||
printf("\tPlaintext pwd: %s\n", d.plaintext_pw);
|
||||
printf("\tLast Changed: %lu\n", d.last_change_time);
|
||||
printf("\tSecure Channel Type: %d\n\n", d.sec_channel_type);
|
||||
}
|
||||
|
||||
println("Trusted domains:");
|
||||
for (i in secrets.trusted_domains) {
|
||||
var td = secrets.trusted_domains[i];
|
||||
for (j = 0; j < td.uni_name_len; j++) {
|
||||
printf("\t--- %s ---\n", td.uni_name[j]);
|
||||
}
|
||||
printf("\tPassword: %s\n", td.pass);
|
||||
printf("\tModified: %lu\n", td.mod_time);
|
||||
printf("\tSID: %s\n", td.domain_sid);
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_regdb(regdb)
|
||||
{
|
||||
var i, j;
|
||||
print_header("Registry");
|
||||
|
||||
for (i in regdb.keys) {
|
||||
var k = regdb.keys[i];
|
||||
printf("%s\n", k.name);
|
||||
for (j in k.values) {
|
||||
var v = k.values[j];
|
||||
printf("\t%s: type %d, length %d\n", v.name, v.type, v.data.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_winsdb(samba3)
|
||||
{
|
||||
var i;
|
||||
print_header("WINS Database");
|
||||
|
||||
for (i in samba3.winsentries) {
|
||||
var e = samba3.winsentries[i];
|
||||
printf("%s, nb_flags: %x, type: %d, ttl: %lu, %d ips, fst: %s\n", e.name, e.nb_flags, e.type, e.ttl, e.ips.length, e.ips[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_groupmappings(groupdb)
|
||||
{
|
||||
print_header("Group Mappings");
|
||||
|
||||
for (var i in groupdb.groupmappings) {
|
||||
var g = groupdb.groupmappings[i];
|
||||
printf("\t--- Group: %s ---\n", g.nt_name);
|
||||
printf("\tComment: %s\n", g.comment);
|
||||
printf("\tGID: %d\n", g.gid);
|
||||
printf("\tSID Name Use: %d\n", g.sid_name_use);
|
||||
printf("\tSID: %s\n\n", g.sid);
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_aliases(groupdb)
|
||||
{
|
||||
var i, j;
|
||||
for (i in groupdb.aliases) {
|
||||
var a = groupdb.aliases[i];
|
||||
printf("\t--- Alias: %s ---\n", a.sid);
|
||||
for (j in a.members) {
|
||||
printf("\t%s\n", a.members[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3_idmapdb(idmapdb)
|
||||
{
|
||||
var i;
|
||||
print_header("Winbindd SID<->GID/UID mappings");
|
||||
|
||||
printf("User High Water Mark: %d\n", idmapdb.user_hwm);
|
||||
printf("Group High Water Mark: %d\n\n", idmapdb.group_hwm);
|
||||
|
||||
for (i in idmapdb.mappings) {
|
||||
var e = idmapdb.mappings[i];
|
||||
printf("%s -> ", e.sid);
|
||||
|
||||
if (e.type == e.IDMAP_GROUP) {
|
||||
printf("GID %d\n", e.unix_id);
|
||||
} else {
|
||||
printf("UID %d\n", e.unix_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function print_samba3(samba3)
|
||||
{
|
||||
print_samba3_sam(samba3);
|
||||
print_samba3_policy(samba3.policy);
|
||||
print_samba3_shares(samba3);
|
||||
print_samba3_winsdb(samba3);
|
||||
print_samba3_regdb(samba3.registry);
|
||||
print_samba3_secrets(samba3.secrets);
|
||||
print_samba3_groupmappings(samba3);
|
||||
print_samba3_aliases(samba3);
|
||||
print_samba3_idmapdb(samba3.idmapdb);
|
||||
}
|
||||
|
||||
function print_samba3_summary(samba3)
|
||||
{
|
||||
printf("WINS db entries: %d\n", samba3.winsentries.length);
|
||||
printf("SAM Accounts: %d\n", samba3.samaccounts.length);
|
||||
printf("Registry key count: %d\n", samba3.registry.keys.length);
|
||||
printf("Shares (including [global]): %d\n", samba3.shares.length);
|
||||
printf("Groupmap count: %d\n", samba3.groupmappings.length);
|
||||
printf("Alias count: %d\n", samba3.aliases.length);
|
||||
printf("Idmap count: %d\n", samba3.idmapdb.mappings.length);
|
||||
}
|
||||
|
||||
samba3 = samba3_read(options.ARGV[0], options.ARGV[1]);
|
||||
|
||||
if (options.format == "summary") {
|
||||
print_samba3_summary(samba3);
|
||||
} else if (options.format == "full") {
|
||||
print_samba3(samba3);
|
||||
}
|
||||
|
||||
return 0;
|
||||
Executable
+96
@@ -0,0 +1,96 @@
|
||||
#!/bin/sh
|
||||
exec smbscript "$0" ${1+"$@"}
|
||||
/*
|
||||
provide information on connected users and open files
|
||||
Copyright Andrew Tridgell 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
libinclude("base.js");
|
||||
libinclude("management.js");
|
||||
|
||||
var options = new Object();
|
||||
|
||||
options = GetOptions(ARGV,
|
||||
"POPT_AUTOHELP",
|
||||
"POPT_COMMON_SAMBA",
|
||||
"POPT_COMMON_VERSION",
|
||||
"nbt");
|
||||
if (options == undefined) {
|
||||
println("Failed to parse options: " + options.ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
show open sessions
|
||||
*/
|
||||
function show_sessions()
|
||||
{
|
||||
var sessions = smbsrv_sessions();
|
||||
var i;
|
||||
var sys = sys_init();
|
||||
if (sessions == undefined) {
|
||||
println("No sessions open");
|
||||
return;
|
||||
}
|
||||
printf("User Client Connected at\n");
|
||||
printf("-------------------------------------------------------------------------------\n");
|
||||
for (i=0;i<sessions.length;i++) {
|
||||
var info = sessions[i];
|
||||
var fulluser = sprintf("%s/%s", info.account_name, info.domain_name);
|
||||
printf("%-30s %16s %s\n",
|
||||
fulluser, info.client_ip, sys.httptime(info.connect_time));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
show open tree connects
|
||||
*/
|
||||
function show_tcons()
|
||||
{
|
||||
var tcons = smbsrv_tcons();
|
||||
var sys = sys_init();
|
||||
if (tcons == undefined) {
|
||||
println("No tree connects");
|
||||
return;
|
||||
}
|
||||
printf("Share Client Connected at\n");
|
||||
printf("-------------------------------------------------------------------------------\n");
|
||||
for (i=0;i<tcons.length;i++) {
|
||||
var info = tcons[i];
|
||||
printf("%-30s %16s %s\n",
|
||||
info.share_name, info.client_ip, sys.httptime(info.connect_time));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
show nbtd information
|
||||
*/
|
||||
function show_nbt()
|
||||
{
|
||||
var stats = nbtd_statistics();
|
||||
if (stats == undefined) {
|
||||
println("nbt server not running");
|
||||
return;
|
||||
}
|
||||
var r;
|
||||
println("NBT server statistics:");
|
||||
for (r in stats) {
|
||||
print("\t" + r + ":\t" + stats[r] + "\n");
|
||||
}
|
||||
println("");
|
||||
}
|
||||
|
||||
var lp = loadparm_init();
|
||||
|
||||
printf("%s\n\n", lp.get("server string"));
|
||||
|
||||
if (options['nbt'] != undefined) {
|
||||
show_nbt();
|
||||
} else {
|
||||
show_sessions();
|
||||
show_tcons();
|
||||
}
|
||||
|
||||
return 0;
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#!/bin/sh
|
||||
exec smbscript "$0" ${1+"$@"}
|
||||
/*
|
||||
tool to manipulate a remote registry
|
||||
Copyright Andrew Tridgell 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
var options = GetOptions(ARGV,
|
||||
"POPT_AUTOHELP",
|
||||
"POPT_COMMON_SAMBA",
|
||||
"POPT_COMMON_CREDENTIALS",
|
||||
"createkey=s");
|
||||
if (options == undefined) {
|
||||
println("Failed to parse options");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libinclude("base.js");
|
||||
libinclude("winreg.js");
|
||||
|
||||
if (options.ARGV.length < 1) {
|
||||
println("Usage: winreg.js <BINDING> [path]");
|
||||
return -1;
|
||||
}
|
||||
var binding = options.ARGV[0];
|
||||
reg = winregObj();
|
||||
|
||||
print("Connecting to " + binding + "\n");
|
||||
status = reg.connect(binding);
|
||||
if (status.is_ok != true) {
|
||||
print("Failed to connect to " + binding + " - " + status.errstr + "\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
function list_values(path) {
|
||||
var list = reg.enum_values(path);
|
||||
var i;
|
||||
if (list == undefined) {
|
||||
return;
|
||||
}
|
||||
for (i=0;i<list.length;i++) {
|
||||
var v = list[i];
|
||||
printf("\ttype=%-30s size=%4d '%s'\n", reg.typestring(v.type), v.size, v.name);
|
||||
if (v.type == reg.REG_SZ || v.type == reg.REG_EXPAND_SZ) {
|
||||
printf("\t\t'%s'\n", v.value);
|
||||
}
|
||||
if (v.type == reg.REG_MULTI_SZ) {
|
||||
var j;
|
||||
for (j in v.value) {
|
||||
printf("\t\t'%s'\n", v.value[j]);
|
||||
}
|
||||
}
|
||||
if (v.type == reg.REG_DWORD || v.type == reg.REG_DWORD_BIG_ENDIAN) {
|
||||
printf("\t\t0x%08x (%d)\n", v.value, v.value);
|
||||
}
|
||||
if (v.type == reg.REG_QWORD) {
|
||||
printf("\t\t0x%llx (%lld)\n", v.value, v.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function list_path(path) {
|
||||
var count = 0;
|
||||
var list = reg.enum_path(path);
|
||||
if (list == undefined) {
|
||||
println("Unable to list " + path);
|
||||
return 0;
|
||||
}
|
||||
var i;
|
||||
list_values(path);
|
||||
count = count + list.length;
|
||||
for (i=0;i<list.length;i++) {
|
||||
var npath;
|
||||
if (path) {
|
||||
npath = path + "\\" + list[i];
|
||||
} else {
|
||||
npath = list[i];
|
||||
}
|
||||
println(npath);
|
||||
count = count + list_path(npath);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
var root;
|
||||
|
||||
if (options.ARGV.length > 1) {
|
||||
root = options.ARGV[1];
|
||||
} else {
|
||||
root = '';
|
||||
}
|
||||
|
||||
if (options.createkey) {
|
||||
var ok = reg.create_key("HKLM\\SOFTWARE", options.createkey);
|
||||
if (!ok) {
|
||||
println("Failed to create key");
|
||||
}
|
||||
} else {
|
||||
printf("Listing registry tree '%s'\n", root);
|
||||
var count = list_path(root);
|
||||
if (count == 0) {
|
||||
println("No entries found");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -0,0 +1,95 @@
|
||||
#######################
|
||||
# Start LIBRARY EJSRPC
|
||||
[SUBSYSTEM::EJSRPC]
|
||||
OBJ_FILES = \
|
||||
ejsrpc.o
|
||||
# End SUBSYSTEM EJSRPC
|
||||
#######################
|
||||
|
||||
[MODULE::smbcalls_config]
|
||||
OBJ_FILES = smbcalls_config.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_config
|
||||
|
||||
[MODULE::smbcalls_ldb]
|
||||
OBJ_FILES = smbcalls_ldb.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_ldb
|
||||
|
||||
[MODULE::smbcalls_nbt]
|
||||
OBJ_FILES = smbcalls_nbt.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_nbt
|
||||
|
||||
[MODULE::smbcalls_samba3]
|
||||
OBJ_FILES = smbcalls_samba3.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_samba3
|
||||
PUBLIC_DEPENDENCIES = LIBSAMBA3
|
||||
|
||||
[MODULE::smbcalls_rand]
|
||||
OBJ_FILES = smbcalls_rand.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_random
|
||||
|
||||
[MODULE::smbcalls_nss]
|
||||
OBJ_FILES = smbcalls_nss.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_nss
|
||||
|
||||
[MODULE::smbcalls_data]
|
||||
OBJ_FILES = smbcalls_data.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_datablob
|
||||
|
||||
[MODULE::smbcalls_auth]
|
||||
OBJ_FILES = smbcalls_auth.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_auth
|
||||
PUBLIC_DEPENDENCIES = auth
|
||||
|
||||
[MODULE::smbcalls_string]
|
||||
OBJ_FILES = smbcalls_string.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_string
|
||||
|
||||
[MODULE::smbcalls_sys]
|
||||
OBJ_FILES = smbcalls_sys.o
|
||||
SUBSYSTEM = smbcalls
|
||||
INIT_FUNCTION = smb_setup_ejs_system
|
||||
|
||||
#######################
|
||||
# Start LIBRARY smbcalls
|
||||
[LIBRARY::smbcalls]
|
||||
SO_VERSION = 0
|
||||
VERSION = 0.0.1
|
||||
PRIVATE_PROTO_HEADER = proto.h
|
||||
OBJ_FILES = \
|
||||
smbcalls.o \
|
||||
smbcalls_cli.o \
|
||||
smbcalls_rpc.o \
|
||||
smbcalls_options.o \
|
||||
smbcalls_creds.o \
|
||||
smbcalls_param.o \
|
||||
ejsnet.o \
|
||||
mprutil.o \
|
||||
literal.o
|
||||
PUBLIC_DEPENDENCIES = \
|
||||
EJS LIBSAMBA-UTIL \
|
||||
EJSRPC MESSAGING \
|
||||
LIBSAMBA-NET LIBCLI_SMB LIBPOPT \
|
||||
CREDENTIALS POPT_CREDENTIALS POPT_SAMBA \
|
||||
dcerpc \
|
||||
NDR_TABLE
|
||||
# End SUBSYSTEM smbcalls
|
||||
#######################
|
||||
|
||||
#######################
|
||||
# Start BINARY SMBSCRIPT
|
||||
[BINARY::smbscript]
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = \
|
||||
smbscript.o
|
||||
PRIVATE_DEPENDENCIES = EJS LIBSAMBA-UTIL smbcalls LIBSAMBA-CONFIG
|
||||
# End BINARY SMBSCRIPT
|
||||
#######################
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide interfaces to libnet calls from ejs scripts
|
||||
|
||||
Copyright (C) Rafal Szczesniak 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 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 "scripting/ejs/ejsnet.h"
|
||||
#include "libnet/libnet.h"
|
||||
#include "events/events.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
|
||||
static int ejs_net_userman(MprVarHandle eid, int argc, struct MprVar** argv);
|
||||
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_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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Usage:
|
||||
usrCtx = net.UserMgr(domain);
|
||||
*/
|
||||
static 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);
|
||||
|
||||
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 = NULL;
|
||||
struct libnet_UserInfo 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_UserInfo(ctx, mem_ctx, &req);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ejsSetErrorMsg(eid, "%s", req.out.error_string);
|
||||
}
|
||||
|
||||
/* TODO: create user info object and pass received properties */
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ejsnet_setup(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "NetContext", ejs_net_context, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide interfaces to libnet calls from ejs scripts
|
||||
|
||||
Copyright (C) Rafal Szczesniak 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 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 "lib/appweb/ejs/ejs.h"
|
||||
|
||||
|
||||
void ejsnet_setup(void);
|
||||
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide interfaces to rpc 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 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 "librpc/gen_ndr/lsa.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
#include "scripting/ejs/ejsrpc.h"
|
||||
#include "libcli/security/security.h"
|
||||
|
||||
/*
|
||||
set the switch var to be used by the next union switch
|
||||
*/
|
||||
void ejs_set_switch(struct ejs_rpc *ejs, uint32_t switch_var)
|
||||
{
|
||||
ejs->switch_var = switch_var;
|
||||
}
|
||||
|
||||
/*
|
||||
panic in the ejs wrapper code
|
||||
*/
|
||||
NTSTATUS ejs_panic(struct ejs_rpc *ejs, const char *why)
|
||||
{
|
||||
ejsSetErrorMsg(ejs->eid, "rpc_call '%s' failed - %s", ejs->callname, why);
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
start the ejs pull process for a structure
|
||||
*/
|
||||
NTSTATUS ejs_pull_struct_start(struct ejs_rpc *ejs, struct MprVar **v, const char *name)
|
||||
{
|
||||
return mprGetVar(v, name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
start the ejs push process for a structure
|
||||
*/
|
||||
NTSTATUS ejs_push_struct_start(struct ejs_rpc *ejs, struct MprVar **v, const char *name)
|
||||
{
|
||||
NDR_CHECK(mprSetVar(*v, name, mprObject(name)));
|
||||
return mprGetVar(v, name);
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint8 from a mpr variable to a C element
|
||||
*/
|
||||
NTSTATUS ejs_pull_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint8_t *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToInteger(v);
|
||||
return NT_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint8_t *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateIntegerVar(*r));
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint16 from a mpr variable to a C element
|
||||
*/
|
||||
NTSTATUS ejs_pull_uint16(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint16_t *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToInteger(v);
|
||||
return NT_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_uint16(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint16_t *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateIntegerVar(*r));
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint32 from a mpr variable to a C element
|
||||
*/
|
||||
NTSTATUS ejs_pull_uint32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint32_t *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToInteger(v);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_uint32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint32_t *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateIntegerVar(*r));
|
||||
}
|
||||
|
||||
/*
|
||||
pull a int32 from a mpr variable to a C element
|
||||
*/
|
||||
NTSTATUS ejs_pull_int32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, int32_t *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToInteger(v);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_int32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const int32_t *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateIntegerVar(*r));
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint32 from a mpr variable to a C element
|
||||
*/
|
||||
NTSTATUS ejs_pull_time_t(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, time_t *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToInteger(v);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_time_t(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const time_t *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateIntegerVar(*r));
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_hyper(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint64_t *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToNumber(v);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_hyper(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint64_t *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateNumberVar(*r));
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_dlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, int64_t *r)
|
||||
{
|
||||
return ejs_pull_hyper(ejs, v, name, (uint64_t *)r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_dlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const int64_t *r)
|
||||
{
|
||||
return ejs_push_hyper(ejs, v, name, (const uint64_t *)r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_udlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint64_t *r)
|
||||
{
|
||||
return ejs_pull_hyper(ejs, v, name, r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_udlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint64_t *r)
|
||||
{
|
||||
return ejs_push_hyper(ejs, v, name, r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_NTTIME(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint64_t *r)
|
||||
{
|
||||
return ejs_pull_hyper(ejs, v, name, r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_NTTIME(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint64_t *r)
|
||||
{
|
||||
return ejs_push_hyper(ejs, v, name, r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_WERROR(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const WERROR *r)
|
||||
{
|
||||
return ejs_push_string(ejs, v, name, win_errstr(*r));
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_NTSTATUS(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const NTSTATUS *r)
|
||||
{
|
||||
return ejs_push_string(ejs, v, name, nt_errstr(*r));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
pull a enum from a mpr variable to a C element
|
||||
a enum is just treating as an unsigned integer at this level
|
||||
*/
|
||||
NTSTATUS ejs_pull_enum(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, unsigned *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToInteger(v);
|
||||
return NT_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_enum(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const unsigned *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateIntegerVar(*r));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
pull a string
|
||||
*/
|
||||
NTSTATUS ejs_pull_string(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char **s)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*s = mprToString(v);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
push a string
|
||||
*/
|
||||
NTSTATUS ejs_push_string(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char *s)
|
||||
{
|
||||
return mprSetVar(v, name, mprString(s));
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_dom_sid(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct dom_sid *r)
|
||||
{
|
||||
struct dom_sid *sid;
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
sid = dom_sid_parse_talloc(ejs, mprToString(v));
|
||||
NT_STATUS_HAVE_NO_MEMORY(sid);
|
||||
*r = *sid;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_dom_sid(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct dom_sid *r)
|
||||
{
|
||||
char *sidstr = dom_sid_string(ejs, r);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sidstr);
|
||||
return mprSetVar(v, name, mprString(sidstr));
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_GUID(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct GUID *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
return GUID_from_string(mprToString(v), r);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_GUID(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct GUID *r)
|
||||
{
|
||||
char *guid = GUID_string(ejs, r);
|
||||
NT_STATUS_HAVE_NO_MEMORY(guid);
|
||||
return mprSetVar(v, name, mprString(guid));
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_null(struct ejs_rpc *ejs, struct MprVar *v, const char *name)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreatePtrVar(NULL));
|
||||
}
|
||||
|
||||
BOOL ejs_pull_null(struct ejs_rpc *ejs, struct MprVar *v, const char *name)
|
||||
{
|
||||
NTSTATUS status = mprGetVar(&v, name);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return False;
|
||||
}
|
||||
if (v->type == MPR_TYPE_PTR && v->ptr == NULL) {
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*
|
||||
pull a lsa_String
|
||||
*/
|
||||
NTSTATUS ejs_pull_lsa_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct lsa_String *r)
|
||||
{
|
||||
return ejs_pull_string(ejs, v, name, &r->string);
|
||||
}
|
||||
|
||||
/*
|
||||
push a lsa_String
|
||||
*/
|
||||
NTSTATUS ejs_push_lsa_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct lsa_String *r)
|
||||
{
|
||||
return ejs_push_string(ejs, v, name, r->string);
|
||||
}
|
||||
|
||||
/*
|
||||
pull a winreg_String
|
||||
*/
|
||||
NTSTATUS ejs_pull_winreg_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct winreg_String *r)
|
||||
{
|
||||
return ejs_pull_string(ejs, v, name, &r->name);
|
||||
}
|
||||
|
||||
/*
|
||||
push a winreg_String
|
||||
*/
|
||||
NTSTATUS ejs_push_winreg_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct winreg_String *r)
|
||||
{
|
||||
return ejs_push_string(ejs, v, name, r->name);
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_DATA_BLOB(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, DATA_BLOB *r)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_DATA_BLOB(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name,
|
||||
const DATA_BLOB *r)
|
||||
{
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_pull_BOOL(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, BOOL *r)
|
||||
{
|
||||
NDR_CHECK(mprGetVar(&v, name));
|
||||
*r = mprVarToBool(v);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_BOOL(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const BOOL *r)
|
||||
{
|
||||
return mprSetVar(v, name, mprCreateBoolVar(*r));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
pull a uint8 array from a mpr variable to a C element - treating as a data blob
|
||||
*/
|
||||
NTSTATUS ejs_pull_array_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name,
|
||||
uint8_t *r, uint32_t length)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DATA_BLOB *blob;
|
||||
|
||||
status = mprGetVar(&v, name);
|
||||
NT_STATUS_NOT_OK_RETURN(status);
|
||||
|
||||
blob = mprToDataBlob(v);
|
||||
if (blob == NULL) {
|
||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
if (blob->length != length) {
|
||||
return NT_STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
memcpy(r, blob->data, length);
|
||||
return NT_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS ejs_push_array_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name,
|
||||
const uint8_t *r, uint32_t length)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
blob.data = discard_const(r);
|
||||
blob.length = length;
|
||||
mprSetVar(v, name, mprDataBlob(blob));
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
ejs <-> rpc interface definitions
|
||||
|
||||
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 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 "librpc/gen_ndr/security.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
|
||||
struct ejs_rpc {
|
||||
int eid;
|
||||
const char *callname;
|
||||
/* as ejs does only one pass, we can use a single var for switch
|
||||
handling */
|
||||
uint32_t switch_var;
|
||||
};
|
||||
|
||||
typedef NTSTATUS (*ejs_pull_t)(struct ejs_rpc *, struct MprVar *, const char *, void *);
|
||||
typedef NTSTATUS (*ejs_push_t)(struct ejs_rpc *, struct MprVar *, const char *, const void *);
|
||||
typedef NTSTATUS (*ejs_pull_function_t)(struct ejs_rpc *, struct MprVar *, void *);
|
||||
typedef NTSTATUS (*ejs_push_function_t)(struct ejs_rpc *, struct MprVar *, const void *);
|
||||
|
||||
NTSTATUS ejs_panic(struct ejs_rpc *ejs, const char *why);
|
||||
void ejs_set_switch(struct ejs_rpc *ejs, uint32_t switch_var);
|
||||
|
||||
NTSTATUS smbcalls_register_ejs(const char *name, MprCFunction fn);
|
||||
|
||||
|
||||
int ejs_rpc_call(int eid, int argc, struct MprVar **argv,
|
||||
const struct dcerpc_interface_table *iface, int callnum,
|
||||
ejs_pull_function_t ejs_pull, ejs_push_function_t ejs_push);
|
||||
|
||||
NTSTATUS ejs_pull_struct_start(struct ejs_rpc *ejs, struct MprVar **v, const char *name);
|
||||
NTSTATUS ejs_push_struct_start(struct ejs_rpc *ejs, struct MprVar **v, const char *name);
|
||||
|
||||
NTSTATUS ejs_pull_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint8_t *r);
|
||||
NTSTATUS ejs_push_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint8_t *r);
|
||||
NTSTATUS ejs_pull_uint16(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint16_t *r);
|
||||
NTSTATUS ejs_push_uint16(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint16_t *r);
|
||||
NTSTATUS ejs_pull_uint32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint32_t *r);
|
||||
NTSTATUS ejs_push_int32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const int32_t *r);
|
||||
NTSTATUS ejs_pull_int32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, int32_t *r);
|
||||
NTSTATUS ejs_push_uint32(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint32_t *r);
|
||||
NTSTATUS ejs_pull_hyper(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint64_t *r);
|
||||
NTSTATUS ejs_push_hyper(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint64_t *r);
|
||||
NTSTATUS ejs_pull_dlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, int64_t *r);
|
||||
NTSTATUS ejs_push_dlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const int64_t *r);
|
||||
NTSTATUS ejs_pull_udlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint64_t *r);
|
||||
NTSTATUS ejs_push_udlong(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint64_t *r);
|
||||
NTSTATUS ejs_pull_NTTIME(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, uint64_t *r);
|
||||
NTSTATUS ejs_push_NTTIME(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const uint64_t *r);
|
||||
NTSTATUS ejs_pull_time_t(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, time_t *r);
|
||||
NTSTATUS ejs_push_time_t(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const time_t *r);
|
||||
NTSTATUS ejs_pull_enum(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, unsigned *r);
|
||||
NTSTATUS ejs_push_enum(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const unsigned *r);
|
||||
NTSTATUS ejs_pull_string(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char **s);
|
||||
NTSTATUS ejs_push_string(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const char *s);
|
||||
void ejs_set_constant_int(int eid, const char *name, int value);
|
||||
void ejs_set_constant_string(int eid, const char *name, const char *value);
|
||||
|
||||
NTSTATUS ejs_pull_dom_sid(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct dom_sid *r);
|
||||
NTSTATUS ejs_push_dom_sid(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct dom_sid *r);
|
||||
NTSTATUS ejs_push_null(struct ejs_rpc *ejs, struct MprVar *v, const char *name);
|
||||
BOOL ejs_pull_null(struct ejs_rpc *ejs, struct MprVar *v, const char *name);
|
||||
NTSTATUS ejs_push_WERROR(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const WERROR *r);
|
||||
NTSTATUS ejs_push_NTSTATUS(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const NTSTATUS *r);
|
||||
NTSTATUS ejs_pull_DATA_BLOB(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, DATA_BLOB *r);
|
||||
NTSTATUS ejs_push_DATA_BLOB(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const DATA_BLOB *r);
|
||||
NTSTATUS ejs_pull_BOOL(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, BOOL *r);
|
||||
NTSTATUS ejs_push_BOOL(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const BOOL *r);
|
||||
|
||||
NTSTATUS ejs_pull_array_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name,
|
||||
uint8_t *r, uint32_t length);
|
||||
NTSTATUS ejs_push_array_uint8(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name,
|
||||
const uint8_t *r, uint32_t length);
|
||||
|
||||
NTSTATUS ejs_pull_GUID(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct GUID *r);
|
||||
NTSTATUS ejs_push_GUID(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct GUID *r);
|
||||
|
||||
struct lsa_String;
|
||||
NTSTATUS ejs_pull_lsa_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct lsa_String *r);
|
||||
NTSTATUS ejs_push_lsa_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct lsa_String *r);
|
||||
|
||||
struct winreg_String;
|
||||
NTSTATUS ejs_pull_winreg_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, struct winreg_String *r);
|
||||
NTSTATUS ejs_push_winreg_String(struct ejs_rpc *ejs,
|
||||
struct MprVar *v, const char *name, const struct winreg_String *r);
|
||||
|
||||
#define EJS_ALLOC(ejs, s) do { \
|
||||
(s) = talloc_ptrtype(ejs, (s)); \
|
||||
if (!(s)) return ejs_panic(ejs, "out of memory"); \
|
||||
} while (0)
|
||||
|
||||
#define EJS_ALLOC_N(ejs, s, n) do { \
|
||||
(s) = talloc_array_ptrtype(ejs, (s), n); \
|
||||
if (!(s)) return ejs_panic(ejs, "out of memory"); \
|
||||
} while (0)
|
||||
|
||||
/* some types are equivalent for ejs */
|
||||
#define ejs_pull_dom_sid2 ejs_pull_dom_sid
|
||||
#define ejs_push_dom_sid2 ejs_push_dom_sid
|
||||
#define ejs_pull_dom_sid28 ejs_pull_dom_sid
|
||||
#define ejs_push_dom_sid28 ejs_push_dom_sid
|
||||
#define ejs_pull_NTTIME_hyper ejs_pull_NTTIME
|
||||
#define ejs_push_NTTIME_hyper ejs_push_NTTIME
|
||||
#define ejs_pull_NTTIME_1sec ejs_pull_NTTIME
|
||||
#define ejs_push_NTTIME_1sec ejs_push_NTTIME
|
||||
|
||||
@@ -0,0 +1,813 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
|
||||
* Michael Clark <michael@metaparadigm.com>
|
||||
* Copyright (c) 2006 Derrell Lipman
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See COPYING for details.
|
||||
*
|
||||
* Derrell Lipman:
|
||||
* This version is modified from the original. It has been modified to
|
||||
* natively use EJS variables rather than the original C object interface, and
|
||||
* to use the talloc() family of functions for memory allocation.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "scripting/ejs/smbcalls.h"
|
||||
|
||||
enum json_tokener_error {
|
||||
json_tokener_success,
|
||||
json_tokener_error_oom, /* out of memory */
|
||||
json_tokener_error_parse_unexpected,
|
||||
json_tokener_error_parse_null,
|
||||
json_tokener_error_parse_date,
|
||||
json_tokener_error_parse_boolean,
|
||||
json_tokener_error_parse_number,
|
||||
json_tokener_error_parse_array,
|
||||
json_tokener_error_parse_object,
|
||||
json_tokener_error_parse_string,
|
||||
json_tokener_error_parse_comment,
|
||||
json_tokener_error_parse_eof
|
||||
};
|
||||
|
||||
enum json_tokener_state {
|
||||
json_tokener_state_eatws,
|
||||
json_tokener_state_start,
|
||||
json_tokener_state_finish,
|
||||
json_tokener_state_null,
|
||||
json_tokener_state_date,
|
||||
json_tokener_state_comment_start,
|
||||
json_tokener_state_comment,
|
||||
json_tokener_state_comment_eol,
|
||||
json_tokener_state_comment_end,
|
||||
json_tokener_state_string,
|
||||
json_tokener_state_string_escape,
|
||||
json_tokener_state_escape_unicode,
|
||||
json_tokener_state_boolean,
|
||||
json_tokener_state_number,
|
||||
json_tokener_state_array,
|
||||
json_tokener_state_datelist,
|
||||
json_tokener_state_array_sep,
|
||||
json_tokener_state_datelist_sep,
|
||||
json_tokener_state_object,
|
||||
json_tokener_state_object_field_start,
|
||||
json_tokener_state_object_field,
|
||||
json_tokener_state_object_field_end,
|
||||
json_tokener_state_object_value,
|
||||
json_tokener_state_object_sep
|
||||
};
|
||||
|
||||
enum date_field {
|
||||
date_field_year,
|
||||
date_field_month,
|
||||
date_field_day,
|
||||
date_field_hour,
|
||||
date_field_minute,
|
||||
date_field_second,
|
||||
date_field_millisecond
|
||||
};
|
||||
|
||||
struct json_tokener
|
||||
{
|
||||
char *source;
|
||||
int pos;
|
||||
void *ctx;
|
||||
void *pb;
|
||||
};
|
||||
|
||||
static const char *json_number_chars = "0123456789.+-e";
|
||||
static const char *json_hex_chars = "0123456789abcdef";
|
||||
|
||||
#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
|
||||
|
||||
extern struct MprVar json_tokener_parse(char *s);
|
||||
static struct MprVar json_tokener_do_parse(struct json_tokener *this,
|
||||
enum json_tokener_error *err_p);
|
||||
|
||||
/*
|
||||
* literal_to_var() parses a string into an ejs variable. The ejs
|
||||
* variable is returned. Upon error, the javascript variable will be
|
||||
* `undefined`. This was created for parsing JSON, but is generally useful
|
||||
* for parsing the literal forms of objects and arrays, since ejs doesn't
|
||||
* procide that functionality.
|
||||
*/
|
||||
int literal_to_var(int eid, int argc, char **argv)
|
||||
{
|
||||
struct json_tokener tok;
|
||||
struct MprVar obj;
|
||||
enum json_tokener_error err = json_tokener_success;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid,
|
||||
"literal_to_var() requires one parameter: "
|
||||
"the string to be parsed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tok.source = argv[0];
|
||||
tok.pos = 0;
|
||||
tok.ctx = talloc_new(mprMemCtx());
|
||||
if (tok.ctx == NULL) {
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
return 0;
|
||||
}
|
||||
tok.pb = talloc_zero_size(tok.ctx, 1);
|
||||
if (tok.pb == NULL) {
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
return 0;
|
||||
}
|
||||
obj = json_tokener_do_parse(&tok, &err);
|
||||
talloc_free(tok.pb);
|
||||
if (err != json_tokener_success) {
|
||||
mprDestroyVar(&obj);
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
return 0;
|
||||
}
|
||||
mpr_Return(eid, obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *append_string(void *ctx,
|
||||
char *orig,
|
||||
char *append,
|
||||
int size)
|
||||
{
|
||||
char c;
|
||||
char *end_p = append + size;
|
||||
void *ret;
|
||||
|
||||
/*
|
||||
* We need to null terminate the string to be copied. Save character at
|
||||
* the size limit of the source string.
|
||||
*/
|
||||
c = *end_p;
|
||||
|
||||
/* Temporarily null-terminate it */
|
||||
*end_p = '\0';
|
||||
|
||||
/* Append the requested data */
|
||||
ret = talloc_append_string(ctx, orig, append);
|
||||
|
||||
/* Restore the original character in place of our temporary null byte */
|
||||
*end_p = c;
|
||||
|
||||
/* Give 'em what they came for */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct MprVar json_tokener_do_parse(struct json_tokener *this,
|
||||
enum json_tokener_error *err_p)
|
||||
{
|
||||
enum json_tokener_state state;
|
||||
enum json_tokener_state saved_state;
|
||||
enum date_field date_field;
|
||||
struct MprVar current = mprCreateUndefinedVar();
|
||||
struct MprVar tempObj;
|
||||
struct MprVar obj;
|
||||
enum json_tokener_error err = json_tokener_success;
|
||||
char date_script[] = "JSON_Date.create(0);";
|
||||
char *obj_field_name = NULL;
|
||||
char *emsg = NULL;
|
||||
char quote_char;
|
||||
int deemed_double;
|
||||
int start_offset;
|
||||
char c;
|
||||
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_start;
|
||||
|
||||
|
||||
do {
|
||||
c = this->source[this->pos];
|
||||
switch(state) {
|
||||
|
||||
case json_tokener_state_eatws:
|
||||
if(isspace(c)) {
|
||||
this->pos++;
|
||||
} else if(c == '/') {
|
||||
state = json_tokener_state_comment_start;
|
||||
start_offset = this->pos++;
|
||||
} else {
|
||||
state = saved_state;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_start:
|
||||
switch(c) {
|
||||
case '{':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_object;
|
||||
current = mprObject(NULL);
|
||||
this->pos++;
|
||||
break;
|
||||
case '[':
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_array;
|
||||
current = mprArray(NULL);
|
||||
this->pos++;
|
||||
break;
|
||||
case 'N':
|
||||
case 'n':
|
||||
start_offset = this->pos++;
|
||||
if (this->source[this->pos] == 'e') {
|
||||
state = json_tokener_state_date;
|
||||
} else {
|
||||
state = json_tokener_state_null;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
case '\'':
|
||||
quote_char = c;
|
||||
talloc_free(this->pb);
|
||||
this->pb = talloc_zero_size(this->ctx, 1);
|
||||
if (this->pb == NULL) {
|
||||
*err_p = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
state = json_tokener_state_string;
|
||||
start_offset = ++this->pos;
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
case 'F':
|
||||
case 'f':
|
||||
state = json_tokener_state_boolean;
|
||||
start_offset = this->pos++;
|
||||
break;
|
||||
#if defined(__GNUC__)
|
||||
case '0' ... '9':
|
||||
#else
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
#endif
|
||||
case '-':
|
||||
deemed_double = 0;
|
||||
state = json_tokener_state_number;
|
||||
start_offset = this->pos++;
|
||||
break;
|
||||
default:
|
||||
err = json_tokener_error_parse_unexpected;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_finish:
|
||||
goto out;
|
||||
|
||||
case json_tokener_state_null:
|
||||
if(strncasecmp("null",
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset)) {
|
||||
*err_p = json_tokener_error_parse_null;
|
||||
mprDestroyVar(¤t);
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
|
||||
if(this->pos - start_offset == 4) {
|
||||
mprDestroyVar(¤t);
|
||||
current = mprCreateNullVar();
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
this->pos++;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_date:
|
||||
if (this->pos - start_offset <= 18) {
|
||||
if (strncasecmp("new Date(Date.UTC(",
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset)) {
|
||||
*err_p = json_tokener_error_parse_date;
|
||||
mprDestroyVar(¤t);
|
||||
return mprCreateUndefinedVar();
|
||||
} else {
|
||||
this->pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->pos--; /* we went one too far */
|
||||
state = json_tokener_state_eatws;
|
||||
saved_state = json_tokener_state_datelist;
|
||||
|
||||
/* Create a JsonDate object */
|
||||
if (ejsEvalScript(0,
|
||||
date_script,
|
||||
&tempObj,
|
||||
&emsg) != 0) {
|
||||
*err_p = json_tokener_error_parse_date;
|
||||
mprDestroyVar(¤t);
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
mprDestroyVar(¤t);
|
||||
mprCopyVar(¤t, &tempObj, MPR_DEEP_COPY);
|
||||
date_field = date_field_year;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_start:
|
||||
if(c == '*') {
|
||||
state = json_tokener_state_comment;
|
||||
} else if(c == '/') {
|
||||
state = json_tokener_state_comment_eol;
|
||||
} else {
|
||||
err = json_tokener_error_parse_comment;
|
||||
goto out;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment:
|
||||
if(c == '*') state = json_tokener_state_comment_end;
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_eol:
|
||||
if(c == '\n') {
|
||||
state = json_tokener_state_eatws;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_comment_end:
|
||||
if(c == '/') {
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
state = json_tokener_state_comment;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_string:
|
||||
if(c == quote_char) {
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
current = mprString(this->pb);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == '\\') {
|
||||
saved_state = json_tokener_state_string;
|
||||
state = json_tokener_state_string_escape;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_string_escape:
|
||||
switch(c) {
|
||||
case '"':
|
||||
case '\\':
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset - 1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
start_offset = this->pos++;
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'b':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 't':
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset - 1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
if (c == 'b') {
|
||||
/*
|
||||
* second param to append_string()
|
||||
* gets temporarily modified; can't
|
||||
* pass string constant.
|
||||
*/
|
||||
char buf[] = "\b";
|
||||
this->pb = append_string(this->ctx,
|
||||
this->pb,
|
||||
buf,
|
||||
1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
} else if (c == 'n') {
|
||||
char buf[] = "\n";
|
||||
this->pb = append_string(this->ctx,
|
||||
this->pb,
|
||||
buf,
|
||||
1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
} else if (c == 'r') {
|
||||
char buf[] = "\r";
|
||||
this->pb = append_string(this->ctx,
|
||||
this->pb,
|
||||
buf,
|
||||
1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
} else if (c == 't') {
|
||||
char buf[] = "\t";
|
||||
this->pb = append_string(this->ctx,
|
||||
this->pb,
|
||||
buf,
|
||||
1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
start_offset = ++this->pos;
|
||||
state = saved_state;
|
||||
break;
|
||||
case 'u':
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset - 1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
start_offset = ++this->pos;
|
||||
state = json_tokener_state_escape_unicode;
|
||||
break;
|
||||
default:
|
||||
err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_escape_unicode:
|
||||
if(strchr(json_hex_chars, c)) {
|
||||
this->pos++;
|
||||
if(this->pos - start_offset == 4) {
|
||||
unsigned char utf_out[3];
|
||||
unsigned int ucs_char =
|
||||
(hexdigit(*(this->source + start_offset)) << 12) +
|
||||
(hexdigit(*(this->source + start_offset + 1)) << 8) +
|
||||
(hexdigit(*(this->source + start_offset + 2)) << 4) +
|
||||
hexdigit(*(this->source + start_offset + 3));
|
||||
if (ucs_char < 0x80) {
|
||||
utf_out[0] = ucs_char;
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
(char *) utf_out,
|
||||
1);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
} else if (ucs_char < 0x800) {
|
||||
utf_out[0] = 0xc0 | (ucs_char >> 6);
|
||||
utf_out[1] = 0x80 | (ucs_char & 0x3f);
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
(char *) utf_out,
|
||||
2);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
utf_out[0] = 0xe0 | (ucs_char >> 12);
|
||||
utf_out[1] = 0x80 | ((ucs_char >> 6) & 0x3f);
|
||||
utf_out[2] = 0x80 | (ucs_char & 0x3f);
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
(char *) utf_out,
|
||||
3);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
start_offset = this->pos;
|
||||
state = saved_state;
|
||||
}
|
||||
} else {
|
||||
err = json_tokener_error_parse_string;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_boolean:
|
||||
if(strncasecmp("true", this->source + start_offset,
|
||||
this->pos - start_offset) == 0) {
|
||||
if(this->pos - start_offset == 4) {
|
||||
current = mprCreateBoolVar(1);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
this->pos++;
|
||||
}
|
||||
} else if(strncasecmp("false", this->source + start_offset,
|
||||
this->pos - start_offset) == 0) {
|
||||
if(this->pos - start_offset == 5) {
|
||||
current = mprCreateBoolVar(0);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
this->pos++;
|
||||
}
|
||||
} else {
|
||||
err = json_tokener_error_parse_boolean;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_number:
|
||||
if(!c || !strchr(json_number_chars, c)) {
|
||||
int numi;
|
||||
double numd;
|
||||
char *tmp = talloc_strndup(
|
||||
this->ctx,
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
if (tmp == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
if(!deemed_double && sscanf(tmp, "%d", &numi) == 1) {
|
||||
current = mprCreateIntegerVar(numi);
|
||||
} else if(deemed_double && sscanf(tmp, "%lf", &numd) == 1) {
|
||||
current = mprCreateFloatVar(numd);
|
||||
} else {
|
||||
talloc_free(tmp);
|
||||
err = json_tokener_error_parse_number;
|
||||
goto out;
|
||||
}
|
||||
talloc_free(tmp);
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
if(c == '.' || c == 'e') deemed_double = 1;
|
||||
this->pos++;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_array:
|
||||
if(c == ']') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
int oldlen;
|
||||
char idx[16];
|
||||
|
||||
obj = json_tokener_do_parse(this, &err);
|
||||
if (err != json_tokener_success) {
|
||||
goto out;
|
||||
}
|
||||
oldlen = mprToInt(mprGetProperty(¤t,
|
||||
"length",
|
||||
NULL));
|
||||
mprItoa(oldlen, idx, sizeof(idx));
|
||||
mprSetVar(¤t, idx, obj);
|
||||
saved_state = json_tokener_state_array_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_datelist:
|
||||
if(c == ')') {
|
||||
if (this->source[this->pos+1] == ')') {
|
||||
this->pos += 2;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
err = json_tokener_error_parse_date;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
obj = json_tokener_do_parse(this, &err);
|
||||
if (err != json_tokener_success) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* date list items must be integers */
|
||||
if (obj.type != MPR_TYPE_INT) {
|
||||
err = json_tokener_error_parse_date;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch(date_field) {
|
||||
case date_field_year:
|
||||
mprSetVar(¤t, "year", obj);
|
||||
break;
|
||||
case date_field_month:
|
||||
mprSetVar(¤t, "month", obj);
|
||||
break;
|
||||
case date_field_day:
|
||||
mprSetVar(¤t, "day", obj);
|
||||
break;
|
||||
case date_field_hour:
|
||||
mprSetVar(¤t, "hour", obj);
|
||||
break;
|
||||
case date_field_minute:
|
||||
mprSetVar(¤t, "minute", obj);
|
||||
break;
|
||||
case date_field_second:
|
||||
mprSetVar(¤t, "second", obj);
|
||||
break;
|
||||
case date_field_millisecond:
|
||||
mprSetVar(¤t, "millisecond", obj);
|
||||
break;
|
||||
default:
|
||||
err = json_tokener_error_parse_date;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* advance to the next date field */
|
||||
date_field++;
|
||||
|
||||
saved_state = json_tokener_state_datelist_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_array_sep:
|
||||
if(c == ']') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == ',') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_array;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
*err_p = json_tokener_error_parse_array;
|
||||
mprDestroyVar(¤t);
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_datelist_sep:
|
||||
if(c == ')') {
|
||||
if (this->source[this->pos+1] == ')') {
|
||||
this->pos += 2;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
err = json_tokener_error_parse_date;
|
||||
goto out;
|
||||
}
|
||||
} else if(c == ',') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_datelist;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
*err_p = json_tokener_error_parse_date;
|
||||
mprDestroyVar(¤t);
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object:
|
||||
state = json_tokener_state_object_field_start;
|
||||
start_offset = this->pos;
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field_start:
|
||||
if(c == '}') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if (c == '"' || c == '\'') {
|
||||
quote_char = c;
|
||||
talloc_free(this->pb);
|
||||
this->pb = talloc_zero_size(this->ctx, 1);
|
||||
if (this->pb == NULL) {
|
||||
*err_p = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
state = json_tokener_state_object_field;
|
||||
start_offset = ++this->pos;
|
||||
} else {
|
||||
err = json_tokener_error_parse_object;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field:
|
||||
if(c == quote_char) {
|
||||
this->pb = append_string(
|
||||
this->ctx,
|
||||
this->pb,
|
||||
this->source + start_offset,
|
||||
this->pos - start_offset);
|
||||
if (this->pb == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
obj_field_name = talloc_strdup(this->ctx,
|
||||
this->pb);
|
||||
if (obj_field_name == NULL) {
|
||||
err = json_tokener_error_oom;
|
||||
goto out;
|
||||
}
|
||||
saved_state = json_tokener_state_object_field_end;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == '\\') {
|
||||
saved_state = json_tokener_state_object_field;
|
||||
state = json_tokener_state_string_escape;
|
||||
}
|
||||
this->pos++;
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_field_end:
|
||||
if(c == ':') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_object_value;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
*err_p = json_tokener_error_parse_object;
|
||||
mprDestroyVar(¤t);
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_value:
|
||||
obj = json_tokener_do_parse(this, &err);
|
||||
if (err != json_tokener_success) {
|
||||
goto out;
|
||||
}
|
||||
mprSetVar(¤t, obj_field_name, obj);
|
||||
talloc_free(obj_field_name);
|
||||
obj_field_name = NULL;
|
||||
saved_state = json_tokener_state_object_sep;
|
||||
state = json_tokener_state_eatws;
|
||||
break;
|
||||
|
||||
case json_tokener_state_object_sep:
|
||||
if(c == '}') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_finish;
|
||||
state = json_tokener_state_eatws;
|
||||
} else if(c == ',') {
|
||||
this->pos++;
|
||||
saved_state = json_tokener_state_object;
|
||||
state = json_tokener_state_eatws;
|
||||
} else {
|
||||
err = json_tokener_error_parse_object;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
} while(c);
|
||||
|
||||
if(state != json_tokener_state_finish &&
|
||||
saved_state != json_tokener_state_finish)
|
||||
err = json_tokener_error_parse_eof;
|
||||
|
||||
out:
|
||||
talloc_free(obj_field_name);
|
||||
if(err == json_tokener_success) {
|
||||
return current;
|
||||
} else {
|
||||
mprDestroyVar(¤t);
|
||||
*err_p = err;
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void smb_setup_ejs_literal(void)
|
||||
{
|
||||
ejsDefineStringCFunction(-1,
|
||||
"literal_to_var",
|
||||
literal_to_var,
|
||||
NULL,
|
||||
MPR_VAR_SCRIPT_HANDLE);
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
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 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 "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_attrib_handler *attr;
|
||||
struct ldb_val v;
|
||||
|
||||
attr = ldb_attrib_handler(ldb, el->name);
|
||||
if (attr == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (el->num_values == 1 &&
|
||||
!str_list_check_ci(multivalued, el->name)) {
|
||||
if (attr->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 (attr->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();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
turn an array of ldb_messages into a ejs object variable
|
||||
*/
|
||||
struct MprVar mprLdbArray(struct ldb_context *ldb,
|
||||
struct ldb_message **msg, int count, const char *name)
|
||||
{
|
||||
struct MprVar res;
|
||||
int i;
|
||||
|
||||
res = mprArray(name);
|
||||
for (i=0;i<count;i++) {
|
||||
mprAddArray(&res, i, mprLdbMessage(ldb, msg[i]));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
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 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 "build.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();
|
||||
|
||||
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];
|
||||
|
||||
for (j=0;js_include[j];j++) {
|
||||
char *path;
|
||||
path = talloc_asprintf(mprMemCtx(), "%s/%s", js_include[j], script);
|
||||
if (path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (file_exist(path)) {
|
||||
int ret;
|
||||
struct MprVar result;
|
||||
char *emsg;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* jsonrpc_include() allows you to include jsonrpc files from a path based at
|
||||
* "jsonrpc services directory =" in smb.conf.
|
||||
*/
|
||||
static int jsonrpc_include(int eid, int argc, char **argv)
|
||||
{
|
||||
int ret = -1;
|
||||
char *path;
|
||||
char *emsg;
|
||||
const char *jsonrpc_services_dir = lp_jsonrpc_services_dir();
|
||||
struct MprVar result;
|
||||
|
||||
|
||||
if (jsonrpc_services_dir == NULL || jsonrpc_services_dir == NULL) {
|
||||
ejsSetErrorMsg(eid, "'jsonrpc services directory' not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
mpr_Return(eid, mprCreateIntegerVar(-1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
path = talloc_asprintf(mprMemCtx(), "%s/%s",
|
||||
jsonrpc_services_dir,
|
||||
argv[0]);
|
||||
if (path == NULL) {
|
||||
mpr_Return(eid, mprCreateIntegerVar(-1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (file_exist(path)) {
|
||||
ret = ejsEvalFile(eid, path, &result, &emsg);
|
||||
if (ret < 0) {
|
||||
ejsSetErrorMsg(eid, "Could not eval file");
|
||||
printf("file found; ret=%d (%s)\n", ret, emsg);
|
||||
}
|
||||
}
|
||||
|
||||
mpr_Return(eid, mprCreateIntegerVar(ret));
|
||||
talloc_free(path);
|
||||
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 *))
|
||||
{
|
||||
init_module_fn static_init[] = STATIC_smbcalls_MODULES;
|
||||
init_module_fn *shared_init;
|
||||
|
||||
ejs_exception_handler = exception_handler;
|
||||
|
||||
smb_setup_ejs_cli();
|
||||
smb_setup_ejs_options();
|
||||
smb_setup_ejs_credentials();
|
||||
smb_setup_ejs_param();
|
||||
smb_setup_ejs_literal();
|
||||
|
||||
ejsnet_setup();
|
||||
|
||||
shared_init = load_samba_modules(NULL, "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);
|
||||
ejsDefineStringCFunction(-1, "jsonrpc_include", jsonrpc_include, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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 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 "lib/appweb/ejs/ejs.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 "scripting/ejs/proto.h"
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
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 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 "auth/auth.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "scripting/ejs/smbcalls.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "lib/messaging/irpc.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;
|
||||
|
||||
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 = event_context_find(tmp_ctx);
|
||||
msg = messaging_client_init(tmp_ctx, ev);
|
||||
}
|
||||
|
||||
nt_status = auth_context_create(tmp_ctx, auth_types, ev, msg, &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, 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;
|
||||
}
|
||||
|
||||
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 = 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, lp_auth_methods());
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,718 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide hooks into smbd C calls from ejs scripts
|
||||
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "libcli/smb_composite/smb_composite.h"
|
||||
#include "libcli/libcli.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include "librpc/gen_ndr/ndr_nbt.h"
|
||||
|
||||
/* Connect to a server */
|
||||
|
||||
static int ejs_cli_connect(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct smbcli_socket *sock;
|
||||
struct smbcli_transport *transport;
|
||||
struct nbt_name calling, called;
|
||||
NTSTATUS result;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "connect invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Socket connect */
|
||||
|
||||
sock = smbcli_sock_init(NULL, NULL);
|
||||
|
||||
if (!sock) {
|
||||
ejsSetErrorMsg(eid, "socket initialisation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!smbcli_sock_connect_byname(sock, argv[0], 0)) {
|
||||
ejsSetErrorMsg(eid, "socket connect failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
transport = smbcli_transport_init(sock, sock, False);
|
||||
|
||||
if (!transport) {
|
||||
ejsSetErrorMsg(eid, "transport init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Send a netbios session request */
|
||||
|
||||
make_nbt_name_client(&calling, lp_netbios_name());
|
||||
|
||||
nbt_choose_called_name(NULL, &called, argv[0], NBT_NAME_SERVER);
|
||||
|
||||
if (!smbcli_transport_connect(transport, &calling, &called)) {
|
||||
ejsSetErrorMsg(eid, "transport establishment failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = smb_raw_negotiate(transport, lp_maxprotocol());
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a socket object */
|
||||
|
||||
mpr_Return(eid, mprCreatePtrVar(transport));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform a session setup:
|
||||
|
||||
session_setup(conn, "DOMAIN\\USERNAME%PASSWORD");
|
||||
session_setup(conn, USERNAME, PASSWORD);
|
||||
session_setup(conn, DOMAIN, USERNAME, PASSWORD);
|
||||
session_setup(conn); // anonymous
|
||||
|
||||
*/
|
||||
|
||||
static int ejs_cli_ssetup(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_transport *transport;
|
||||
struct smbcli_session *session;
|
||||
struct smb_composite_sesssetup setup;
|
||||
struct cli_credentials *creds;
|
||||
NTSTATUS status;
|
||||
int result = -1;
|
||||
|
||||
/* Argument parsing */
|
||||
|
||||
if (argc < 1 || argc > 4) {
|
||||
ejsSetErrorMsg(eid, "session_setup invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mprVarIsPtr(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a connect handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
transport = argv[0]->ptr;
|
||||
creds = cli_credentials_init(transport);
|
||||
cli_credentials_set_conf(creds);
|
||||
|
||||
if (argc == 4) {
|
||||
|
||||
/* DOMAIN, USERNAME, PASSWORD form */
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 1 must be a string");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cli_credentials_set_domain(creds, argv[1]->string,
|
||||
CRED_SPECIFIED);
|
||||
|
||||
if (!mprVarIsString(argv[2]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 2 must be a string");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cli_credentials_set_username(creds, argv[2]->string,
|
||||
CRED_SPECIFIED);
|
||||
|
||||
if (!mprVarIsString(argv[3]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 3 must be a string");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cli_credentials_set_password(creds, argv[3]->string,
|
||||
CRED_SPECIFIED);
|
||||
|
||||
} else if (argc == 3) {
|
||||
|
||||
/* USERNAME, PASSWORD form */
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg1 must be a string");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cli_credentials_set_username(creds, argv[1]->string,
|
||||
CRED_SPECIFIED);
|
||||
|
||||
if (!mprVarIsString(argv[2]->type)) {
|
||||
|
||||
ejsSetErrorMsg(eid, "arg2 must be a string");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cli_credentials_set_password(creds, argv[2]->string,
|
||||
CRED_SPECIFIED);
|
||||
|
||||
} else if (argc == 2) {
|
||||
|
||||
/* DOMAIN/USERNAME%PASSWORD form */
|
||||
|
||||
cli_credentials_parse_string(creds, argv[1]->string,
|
||||
CRED_SPECIFIED);
|
||||
|
||||
} else {
|
||||
|
||||
/* Anonymous connection */
|
||||
|
||||
cli_credentials_set_anonymous(creds);
|
||||
}
|
||||
|
||||
/* Do session setup */
|
||||
|
||||
session = smbcli_session_init(transport, transport, False);
|
||||
|
||||
if (!session) {
|
||||
ejsSetErrorMsg(eid, "session init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
setup.in.sesskey = transport->negotiate.sesskey;
|
||||
setup.in.capabilities = transport->negotiate.capabilities;
|
||||
setup.in.credentials = creds;
|
||||
setup.in.workgroup = lp_workgroup();
|
||||
|
||||
status = smb_composite_sesssetup(session, &setup);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ejsSetErrorMsg(eid, "session_setup: %s", nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->vuid = setup.out.vuid;
|
||||
|
||||
/* Return a session object */
|
||||
|
||||
mpr_Return(eid, mprCreatePtrVar(session));
|
||||
|
||||
result = 0;
|
||||
|
||||
done:
|
||||
talloc_free(creds);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Perform a tree connect
|
||||
|
||||
tree_connect(session, SHARE);
|
||||
|
||||
*/
|
||||
|
||||
static int ejs_cli_tree_connect(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_session *session;
|
||||
struct smbcli_tree *tree;
|
||||
union smb_tcon tcon;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
NTSTATUS status;
|
||||
const char *password = "";
|
||||
|
||||
/* Argument parsing */
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "tree_connect invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mprVarIsPtr(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a session handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
session = argv[0]->ptr;
|
||||
tree = smbcli_tree_init(session, session, False);
|
||||
|
||||
if (!tree) {
|
||||
ejsSetErrorMsg(eid, "tree init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mem_ctx = talloc_init("tcon");
|
||||
if (!mem_ctx) {
|
||||
ejsSetErrorMsg(eid, "talloc_init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Do tree connect */
|
||||
|
||||
tcon.generic.level = RAW_TCON_TCONX;
|
||||
tcon.tconx.in.flags = 0;
|
||||
|
||||
if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
|
||||
tcon.tconx.in.password = data_blob(NULL, 0);
|
||||
} else if (session->transport->negotiate.sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
|
||||
tcon.tconx.in.password = data_blob_talloc(mem_ctx, NULL, 24);
|
||||
if (session->transport->negotiate.secblob.length < 8) {
|
||||
ejsSetErrorMsg(eid, "invalid security blob");
|
||||
return -1;
|
||||
}
|
||||
SMBencrypt(password, session->transport->negotiate.secblob.data, tcon.tconx.in.password.data);
|
||||
} else {
|
||||
tcon.tconx.in.password = data_blob_talloc(mem_ctx, password, strlen(password)+1);
|
||||
}
|
||||
|
||||
tcon.tconx.in.path = argv[1]->string;
|
||||
tcon.tconx.in.device = "?????";
|
||||
|
||||
status = smb_tree_connect(tree, mem_ctx, &tcon);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ejsSetErrorMsg(eid, "tree_connect: %s", nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree->tid = tcon.tconx.out.tid;
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
mpr_Return(eid, mprCreatePtrVar(tree));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform a tree disconnect
|
||||
|
||||
tree_disconnect(tree);
|
||||
|
||||
*/
|
||||
static int ejs_cli_tree_disconnect(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
NTSTATUS status;
|
||||
|
||||
/* Argument parsing */
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "tree_disconnect invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mprVarIsPtr(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = argv[0]->ptr;
|
||||
|
||||
status = smb_tree_disconnect(tree);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ejsSetErrorMsg(eid, "tree_disconnect: %s", nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
talloc_free(tree);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform a ulogoff
|
||||
|
||||
session_logoff(session);
|
||||
|
||||
*/
|
||||
static int ejs_cli_session_logoff(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_session *session;
|
||||
NTSTATUS status;
|
||||
|
||||
/* Argument parsing */
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "session_logoff invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mprVarIsPtr(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a session handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
session = argv[0]->ptr;
|
||||
|
||||
status = smb_raw_ulogoff(session);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
ejsSetErrorMsg(eid, "session_logoff: %s", nt_errstr(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
talloc_free(session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform a connection close
|
||||
|
||||
disconnect(conn);
|
||||
|
||||
*/
|
||||
static int ejs_cli_disconnect(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_sock *sock;
|
||||
|
||||
/* Argument parsing */
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "disconnect invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mprVarIsPtr(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a connect handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = argv[0]->ptr;
|
||||
|
||||
talloc_free(sock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Perform a tree connect:
|
||||
|
||||
tree_handle = tree_connect("\\\\frogurt\\homes", "user%pass");
|
||||
*/
|
||||
|
||||
static int ejs_tree_connect(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct cli_credentials *creds;
|
||||
struct smb_composite_connect io;
|
||||
struct smbcli_tree *tree;
|
||||
char *hostname, *sharename;
|
||||
NTSTATUS result;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "tree_connect(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up host, share destination */
|
||||
|
||||
mem_ctx = talloc_new(mprMemCtx());
|
||||
smbcli_parse_unc(argv[0], mem_ctx, &hostname, &sharename);
|
||||
|
||||
/* Set up credentials */
|
||||
|
||||
creds = cli_credentials_init(NULL);
|
||||
cli_credentials_set_conf(creds);
|
||||
cli_credentials_parse_string(creds, argv[1], CRED_SPECIFIED);
|
||||
|
||||
/* Do connect */
|
||||
|
||||
io.in.dest_host = hostname;
|
||||
io.in.port = 0;
|
||||
io.in.called_name = strupper_talloc(mem_ctx, hostname);
|
||||
io.in.service = sharename;
|
||||
io.in.service_type = "?????";
|
||||
io.in.credentials = creds;
|
||||
io.in.fallback_to_anonymous = False;
|
||||
io.in.workgroup = lp_workgroup();
|
||||
|
||||
result = smb_composite_connect(&io, mem_ctx, NULL);
|
||||
tree = io.out.tree;
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
if (!NT_STATUS_IS_OK(result)) {
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpr_Return(eid, mprCreatePtrVar(tree));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define IS_TREE_HANDLE(x) (mprVarIsPtr((x)->type) && \
|
||||
talloc_check_name((x)->ptr, "struct smbcli_tree"))
|
||||
|
||||
/* Perform a tree disconnect:
|
||||
|
||||
tree_disconnect(tree_handle);
|
||||
*/
|
||||
|
||||
static int ejs_tree_disconnect(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
NTSTATUS result;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid,
|
||||
"tree_disconnect(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_TREE_HANDLE(argv[0])) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = talloc_check_name(argv[0]->ptr, "struct smbcli_tree");
|
||||
|
||||
result = smb_tree_disconnect(tree);
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a directory:
|
||||
|
||||
result = mkdir(tree_handle, DIRNAME);
|
||||
*/
|
||||
|
||||
static int ejs_mkdir(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
NTSTATUS result;
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "mkdir(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_TREE_HANDLE(argv[0])) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = argv[0]->ptr;
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 2 must be a string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = smbcli_mkdir(tree, argv[1]->string);
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove a directory:
|
||||
|
||||
result = rmdir(tree_handle, DIRNAME);
|
||||
*/
|
||||
|
||||
static int ejs_rmdir(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
NTSTATUS result;
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "rmdir(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_TREE_HANDLE(argv[0])) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = argv[0]->ptr;
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 2 must be a string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = smbcli_rmdir(tree, argv[1]->string);
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rename a file or directory:
|
||||
|
||||
result = rename(tree_handle, SRCFILE, DESTFILE);
|
||||
*/
|
||||
|
||||
static int ejs_rename(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
NTSTATUS result;
|
||||
|
||||
if (argc != 3) {
|
||||
ejsSetErrorMsg(eid, "rename(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_TREE_HANDLE(argv[0])) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = argv[0]->ptr;
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 2 must be a string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mprVarIsString(argv[2]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 3 must be a string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = smbcli_rename(tree, argv[1]->string, argv[2]->string);
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unlink a file or directory:
|
||||
|
||||
result = unlink(tree_handle, FILENAME);
|
||||
*/
|
||||
|
||||
static int ejs_unlink(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
NTSTATUS result;
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "unlink(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_TREE_HANDLE(argv[0])) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = argv[0]->ptr;
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 2 must be a string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = smbcli_unlink(tree, argv[1]->string);
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(result));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* List directory contents
|
||||
|
||||
result = list(tree_handle, ARG1, ...);
|
||||
*/
|
||||
|
||||
static void ejs_list_helper(struct clilist_file_info *info, const char *mask,
|
||||
void *state)
|
||||
|
||||
{
|
||||
MprVar *result = (MprVar *)state;
|
||||
char idx[16];
|
||||
|
||||
mprItoa(result->properties->numDataItems, idx, sizeof(idx));
|
||||
mprSetVar(result, idx, mprString(info->name));
|
||||
}
|
||||
|
||||
static int ejs_list(MprVarHandle eid, int argc, MprVar **argv)
|
||||
{
|
||||
struct smbcli_tree *tree;
|
||||
char *mask;
|
||||
uint16_t attribute;
|
||||
MprVar result;
|
||||
|
||||
if (argc != 3) {
|
||||
ejsSetErrorMsg(eid, "list(): invalid number of args");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_TREE_HANDLE(argv[0])) {
|
||||
ejsSetErrorMsg(eid, "first arg is not a tree handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = argv[0]->ptr;
|
||||
|
||||
if (!mprVarIsString(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 2 must be a string");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mask = argv[1]->string;
|
||||
|
||||
if (!mprVarIsNumber(argv[2]->type)) {
|
||||
ejsSetErrorMsg(eid, "arg 3 must be a number");
|
||||
return -1;
|
||||
}
|
||||
|
||||
attribute = mprVarToInteger(argv[2]);
|
||||
|
||||
result = mprObject("list");
|
||||
|
||||
smbcli_list(tree, mask, attribute, ejs_list_helper, &result);
|
||||
|
||||
mpr_Return(eid, result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
void smb_setup_ejs_cli(void)
|
||||
{
|
||||
ejsDefineStringCFunction(-1, "tree_connect", ejs_tree_connect, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "tree_disconnect", ejs_tree_disconnect, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
|
||||
ejsDefineCFunction(-1, "mkdir", ejs_mkdir, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "rmdir", ejs_rmdir, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "rename", ejs_rename, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "unlink", ejs_unlink, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "list", ejs_list, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
|
||||
|
||||
#if 0
|
||||
ejsDefineStringCFunction(-1, "connect", ejs_cli_connect, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "session_setup", ejs_cli_ssetup, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "tree_connect", ejs_cli_tree_connect, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "tree_disconnect", ejs_cli_tree_disconnect, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "session_logoff", ejs_cli_session_logoff, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
ejsDefineCFunction(-1, "disconnect", ejs_cli_disconnect, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "param/loadparm.h"
|
||||
#include "system/network.h"
|
||||
#include "lib/socket/netif.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();i++) {
|
||||
list = str_list_add(list, lp_servicename(i));
|
||||
}
|
||||
talloc_steal(mprMemCtx(), list);
|
||||
mpr_Return(eid, mprList("services", list));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return a list of parameter categories
|
||||
*/
|
||||
static int ejs_lpCategories(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct parm_struct *parm_table = lp_parm_table();
|
||||
int i;
|
||||
const char **list = NULL;
|
||||
if (argc != 0) return -1;
|
||||
|
||||
for (i=0;parm_table[i].label;i++) {
|
||||
if (parm_table[i].class == P_SEPARATOR) {
|
||||
list = str_list_add(list, parm_table[i].label);
|
||||
}
|
||||
}
|
||||
talloc_steal(mprMemCtx(), list);
|
||||
mpr_Return(eid, mprList("categories", list));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
allow access to loadparm variables from inside ejs scripts in swat
|
||||
|
||||
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) {
|
||||
/* its a share parameter */
|
||||
int snum = lp_servicenumber(argv[0]);
|
||||
if (snum == -1) {
|
||||
return -1;
|
||||
}
|
||||
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) return -1;
|
||||
value = lp_get_parametric(snum, type, option);
|
||||
if (value == NULL) return -1;
|
||||
mpr_ReturnString(eid, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
parm = lp_parm_struct(argv[1]);
|
||||
if (parm == NULL || parm->class == P_GLOBAL) {
|
||||
return -1;
|
||||
}
|
||||
parm_ptr = lp_parm_ptr(snum, 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) return -1;
|
||||
value = lp_get_parametric(-1, type, option);
|
||||
if (value == NULL) return -1;
|
||||
mpr_ReturnString(eid, value);
|
||||
return 0;
|
||||
} else {
|
||||
/* its a global parameter */
|
||||
parm = lp_parm_struct(argv[0]);
|
||||
if (parm == NULL) return -1;
|
||||
parm_ptr = lp_parm_ptr(-1, parm);
|
||||
}
|
||||
|
||||
if (parm == NULL || parm_ptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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_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;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
case P_LIST:
|
||||
mpr_Return(eid, mprList(parm->label, *(const char ***)parm_ptr));
|
||||
break;
|
||||
case P_SEP:
|
||||
return -1;
|
||||
}
|
||||
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(argv[0], argv[1])));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
reload smb.conf
|
||||
|
||||
ok = lp.reload();
|
||||
*/
|
||||
static int ejs_lpReload(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
BOOL ret = lp_load();
|
||||
if (ret) {
|
||||
unload_interfaces();
|
||||
}
|
||||
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, "categories", ejs_lpCategories);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
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 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 "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 = 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))) {
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int ejs_credentials_update_all_keytabs(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
if (!NT_STATUS_IS_OK(cli_credentials_update_all_keytabs(mprMemCtx()))) {
|
||||
mpr_Return(eid, mprCreateBoolVar(False));
|
||||
} else {
|
||||
mpr_Return(eid, mprCreateBoolVar(True));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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);
|
||||
ejsDefineCFunction(-1, "credentials_update_all_keytabs", ejs_credentials_update_all_keytabs, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide access to data blobs
|
||||
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
|
||||
/*
|
||||
create a data blob object from a ejs array of integers
|
||||
*/
|
||||
static int ejs_blobFromArray(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct MprVar *array, *v;
|
||||
unsigned length, i;
|
||||
DATA_BLOB blob;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "blobFromArray invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
array = argv[0];
|
||||
|
||||
v = mprGetProperty(array, "length", NULL);
|
||||
if (v == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
length = mprToInt(v);
|
||||
|
||||
blob = data_blob_talloc(mprMemCtx(), NULL, length);
|
||||
if (length != 0 && blob.data == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for (i=0;i<length;i++) {
|
||||
struct MprVar *vs;
|
||||
char idx[16];
|
||||
mprItoa(i, idx, sizeof(idx));
|
||||
vs = mprGetProperty(array, idx, NULL);
|
||||
if (vs == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
blob.data[i] = mprVarToNumber(vs);
|
||||
}
|
||||
|
||||
mpr_Return(eid, mprDataBlob(blob));
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
create a ejs array of integers from a data blob
|
||||
*/
|
||||
static int ejs_blobToArray(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
DATA_BLOB *blob;
|
||||
struct MprVar array;
|
||||
int i;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "blobToArray invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
blob = mprToDataBlob(argv[0]);
|
||||
if (blob == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
array = mprArray("array");
|
||||
|
||||
for (i=0;i<blob->length;i++) {
|
||||
mprAddArray(&array, i, mprCreateNumberVar(blob->data[i]));
|
||||
}
|
||||
mpr_Return(eid, array);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
compare two data blobs
|
||||
*/
|
||||
static int ejs_blobCompare(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
DATA_BLOB *blob1, *blob2;
|
||||
BOOL ret = False;
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "blobCompare invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
blob1 = mprToDataBlob(argv[0]);
|
||||
blob2 = mprToDataBlob(argv[1]);
|
||||
|
||||
if (blob1 == blob2) {
|
||||
ret = True;
|
||||
goto done;
|
||||
}
|
||||
if (blob1 == NULL || blob2 == NULL) {
|
||||
ret = False;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (blob1->length != blob2->length) {
|
||||
ret = False;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (memcmp(blob1->data, blob2->data, blob1->length) != 0) {
|
||||
ret = False;
|
||||
goto done;
|
||||
}
|
||||
ret = True;
|
||||
|
||||
done:
|
||||
mpr_Return(eid, mprCreateBoolVar(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
convert a blob in winreg format to a mpr variable
|
||||
|
||||
usage:
|
||||
v = data.regToVar(blob, type);
|
||||
*/
|
||||
static int ejs_regToVar(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
DATA_BLOB *blob;
|
||||
enum winreg_Type type;
|
||||
struct MprVar v;
|
||||
|
||||
if (argc != 2) {
|
||||
ejsSetErrorMsg(eid, "regToVar invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
blob = mprToDataBlob(argv[0]);
|
||||
type = mprToInt(argv[1]);
|
||||
|
||||
if (blob == NULL) {
|
||||
ejsSetErrorMsg(eid, "regToVar null data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case REG_NONE:
|
||||
v = mprCreateUndefinedVar();
|
||||
break;
|
||||
|
||||
case REG_SZ:
|
||||
case REG_EXPAND_SZ: {
|
||||
char *s;
|
||||
ssize_t len;
|
||||
len = convert_string_talloc(mprMemCtx(), CH_UTF16, CH_UNIX,
|
||||
blob->data, blob->length, (void **)&s);
|
||||
if (len == -1) {
|
||||
ejsSetErrorMsg(eid, "regToVar invalid REG_SZ string");
|
||||
return -1;
|
||||
}
|
||||
v = mprString(s);
|
||||
talloc_free(s);
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_DWORD: {
|
||||
if (blob->length != 4) {
|
||||
ejsSetErrorMsg(eid, "regToVar invalid REG_DWORD length %ld", (long)blob->length);
|
||||
return -1;
|
||||
}
|
||||
v = mprCreateNumberVar(IVAL(blob->data, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_DWORD_BIG_ENDIAN: {
|
||||
if (blob->length != 4) {
|
||||
ejsSetErrorMsg(eid, "regToVar invalid REG_DWORD_BIG_ENDIAN length %ld", (long)blob->length);
|
||||
return -1;
|
||||
}
|
||||
v = mprCreateNumberVar(RIVAL(blob->data, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_QWORD: {
|
||||
if (blob->length != 8) {
|
||||
ejsSetErrorMsg(eid, "regToVar invalid REG_QWORD length %ld", (long)blob->length);
|
||||
return -1;
|
||||
}
|
||||
v = mprCreateNumberVar(BVAL(blob->data, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_MULTI_SZ: {
|
||||
DATA_BLOB b = *blob;
|
||||
const char **list = NULL;
|
||||
while (b.length > 0) {
|
||||
char *s;
|
||||
ssize_t len;
|
||||
size_t slen = utf16_len_n(b.data, b.length);
|
||||
if (slen == 2 && b.length == 2 && SVAL(b.data, 0) == 0) {
|
||||
break;
|
||||
}
|
||||
len = convert_string_talloc(mprMemCtx(), CH_UTF16, CH_UNIX,
|
||||
b.data, slen, (void **)&s);
|
||||
if (len == -1) {
|
||||
ejsSetErrorMsg(eid, "regToVar invalid REG_MULTI_SZ string");
|
||||
return -1;
|
||||
}
|
||||
list = str_list_add(list, s);
|
||||
talloc_free(s);
|
||||
talloc_steal(mprMemCtx(), list);
|
||||
b.data += slen;
|
||||
b.length -= slen;
|
||||
}
|
||||
v = mprList("REG_MULTI_SZ", list);
|
||||
talloc_free(list);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case REG_FULL_RESOURCE_DESCRIPTOR:
|
||||
case REG_RESOURCE_LIST:
|
||||
case REG_BINARY:
|
||||
case REG_RESOURCE_REQUIREMENTS_LIST:
|
||||
case REG_LINK:
|
||||
return ejs_blobToArray(eid, 1, argv);
|
||||
|
||||
default:
|
||||
ejsSetErrorMsg(eid, "regToVar invalid type %d", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpr_Return(eid, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
initialise datablob ejs subsystem
|
||||
*/
|
||||
static int ejs_datablob_init(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct MprVar *obj = mprInitObject(eid, "datablob", argc, argv);
|
||||
|
||||
mprSetCFunction(obj, "blobFromArray", ejs_blobFromArray);
|
||||
mprSetCFunction(obj, "blobToArray", ejs_blobToArray);
|
||||
mprSetCFunction(obj, "blobCompare", ejs_blobCompare);
|
||||
mprSetCFunction(obj, "regToVar", ejs_regToVar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
NTSTATUS smb_setup_ejs_datablob(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "datablob_init", ejs_datablob_init, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "lib/ldb/include/ldb.h"
|
||||
#include "lib/ldb/include/ldb_errors.h"
|
||||
#include "db_wrap.h"
|
||||
|
||||
/*
|
||||
get the connected db
|
||||
*/
|
||||
static struct ldb_context *ejs_get_ldb_context(int eid)
|
||||
{
|
||||
struct ldb_context *ldb = 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);
|
||||
*/
|
||||
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_result *res=NULL;
|
||||
|
||||
/* validate arguments */
|
||||
if (argc < 1 || argc > 4) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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]);
|
||||
}
|
||||
ret = ldb_search(ldb, basedn, scope, expression, attrs, &res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb));
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
} else {
|
||||
mpr_Return(eid, mprLdbArray(ldb, res->msgs, res->count, "ldb_message"));
|
||||
talloc_free(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, mprCreateBoolVar(ret == 0));
|
||||
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, mprCreateBoolVar(ret == 0));
|
||||
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, mprCreateBoolVar(ret == 0));
|
||||
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(), 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;
|
||||
}
|
||||
|
||||
/*
|
||||
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);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide hooks into smbd C calls from ejs scripts
|
||||
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "librpc/gen_ndr/nbt.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "libcli/resolve/resolve.h"
|
||||
|
||||
/*
|
||||
look up a netbios name
|
||||
|
||||
syntax:
|
||||
resolveName(result, "frogurt");
|
||||
resolveName(result, "frogurt", 0x1c);
|
||||
*/
|
||||
|
||||
static int ejs_resolve_name(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
int result = -1;
|
||||
struct nbt_name name;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
|
||||
NTSTATUS nt_status;
|
||||
const char *reply_addr;
|
||||
|
||||
/* validate arguments */
|
||||
if (argc < 2 || argc > 3) {
|
||||
ejsSetErrorMsg(eid, "resolveName invalid arguments");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (argv[0]->type != MPR_TYPE_OBJECT) {
|
||||
ejsSetErrorMsg(eid, "resolvename invalid arguments");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (argv[1]->type != MPR_TYPE_STRING) {
|
||||
ejsSetErrorMsg(eid, "resolveName invalid arguments");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
make_nbt_name_client(&name, mprToString(argv[1]));
|
||||
} else {
|
||||
if (!mprVarIsNumber(argv[1]->type)) {
|
||||
ejsSetErrorMsg(eid, "resolveName invalid arguments");
|
||||
goto done;
|
||||
}
|
||||
make_nbt_name(&name, mprToString(argv[1]), mprToInt(argv[2]));
|
||||
}
|
||||
|
||||
result = 0;
|
||||
|
||||
nt_status = resolve_name(&name, tmp_ctx, &reply_addr, event_context_find(tmp_ctx));
|
||||
|
||||
if (NT_STATUS_IS_OK(nt_status)) {
|
||||
mprSetPropertyValue(argv[0], "value", mprString(reply_addr));
|
||||
}
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(nt_status));
|
||||
|
||||
done:
|
||||
talloc_free(tmp_ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
NTSTATUS smb_setup_ejs_nbt(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "resolveName", ejs_resolve_name, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide access to getpwnam() and related 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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "system/passwd.h"
|
||||
|
||||
|
||||
/*
|
||||
return a struct passwd as an object
|
||||
*/
|
||||
static struct MprVar mpr_passwd(struct passwd *pwd)
|
||||
{
|
||||
struct MprVar ret;
|
||||
if (pwd == NULL) {
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
ret = mprObject("passwd");
|
||||
|
||||
mprSetVar(&ret, "pw_name", mprString(pwd->pw_name));
|
||||
mprSetVar(&ret, "pw_passwd", mprString(pwd->pw_passwd));
|
||||
mprSetVar(&ret, "pw_uid", mprCreateIntegerVar(pwd->pw_uid));
|
||||
mprSetVar(&ret, "pw_gid", mprCreateIntegerVar(pwd->pw_gid));
|
||||
mprSetVar(&ret, "pw_gecos", mprString(pwd->pw_gecos));
|
||||
mprSetVar(&ret, "pw_dir", mprString(pwd->pw_dir));
|
||||
mprSetVar(&ret, "pw_shell", mprString(pwd->pw_shell));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
return a struct passwd as an object
|
||||
*/
|
||||
static struct MprVar mpr_group(struct group *grp)
|
||||
{
|
||||
struct MprVar ret;
|
||||
if (grp == NULL) {
|
||||
return mprCreateUndefinedVar();
|
||||
}
|
||||
ret = mprObject("group");
|
||||
|
||||
mprSetVar(&ret, "gr_name", mprString(grp->gr_name));
|
||||
mprSetVar(&ret, "gr_passwd", mprString(grp->gr_passwd));
|
||||
mprSetVar(&ret, "gr_gid", mprCreateIntegerVar(grp->gr_gid));
|
||||
mprSetVar(&ret, "gr_mem", mprList("gr_mem", (const char **)grp->gr_mem));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
usage:
|
||||
var pw = nss.getpwnam("root");
|
||||
|
||||
returns an object containing struct passwd entries
|
||||
*/
|
||||
static int ejs_getpwnam(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
/* validate arguments */
|
||||
if (argc != 1 || argv[0]->type != MPR_TYPE_STRING) {
|
||||
ejsSetErrorMsg(eid, "getpwnam invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpr_Return(eid, mpr_passwd(getpwnam(mprToString(argv[0]))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
usage:
|
||||
var pw = nss.getpwuid(0);
|
||||
|
||||
returns an object containing struct passwd entries
|
||||
*/
|
||||
static int ejs_getpwuid(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
/* validate arguments */
|
||||
if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "getpwuid invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
mpr_Return(eid, mpr_passwd(getpwuid(mprToInt(argv[0]))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
usage:
|
||||
var pw = nss.getgrnam("users");
|
||||
|
||||
returns an object containing struct group entries
|
||||
*/
|
||||
static int ejs_getgrnam(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
/* validate arguments */
|
||||
if (argc != 1 || argv[0]->type != MPR_TYPE_STRING) {
|
||||
ejsSetErrorMsg(eid, "getgrnam invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
mpr_Return(eid, mpr_group(getgrnam(mprToString(argv[0]))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
usage:
|
||||
var pw = nss.getgrgid(0);
|
||||
|
||||
returns an object containing struct group entries
|
||||
*/
|
||||
static int ejs_getgrgid(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
/* validate arguments */
|
||||
if (argc != 1 || argv[0]->type != MPR_TYPE_STRING) {
|
||||
ejsSetErrorMsg(eid, "getgrgid invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
mpr_Return(eid, mpr_group(getgrgid(mprToInt(argv[0]))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
initialise nss ejs subsystem
|
||||
*/
|
||||
static int ejs_nss_init(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct MprVar *nss = mprInitObject(eid, "nss", argc, argv);
|
||||
|
||||
mprSetCFunction(nss, "getpwnam", ejs_getpwnam);
|
||||
mprSetCFunction(nss, "getpwuid", ejs_getpwuid);
|
||||
mprSetCFunction(nss, "getgrnam", ejs_getgrnam);
|
||||
mprSetCFunction(nss, "getgrgid", ejs_getgrgid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
NTSTATUS smb_setup_ejs_nss(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "nss_init", ejs_nss_init, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
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 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/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);
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide hooks into smbd C calls from ejs scripts
|
||||
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "param/param.h"
|
||||
|
||||
/*
|
||||
get parameter
|
||||
|
||||
value = param.get("name");
|
||||
value = param.get("section", "name");
|
||||
*/
|
||||
static int ejs_param_get(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct param_context *ctx;
|
||||
const char *ret;
|
||||
if (argc != 1 && argc != 2) {
|
||||
ejsSetErrorMsg(eid, "param.get invalid argument count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = mprGetThisPtr(eid, "param");
|
||||
mprAssert(ctx);
|
||||
|
||||
if (argc == 2) {
|
||||
ret = param_get_string(ctx, argv[0], argv[1]);
|
||||
} else {
|
||||
ret = param_get_string(ctx, NULL, argv[0]);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
mpr_Return(eid, mprString(ret));
|
||||
} else {
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
get list parameter
|
||||
|
||||
ok = param.get_list("name");
|
||||
ok = param.get_list("section", "name");
|
||||
*/
|
||||
static int ejs_param_get_list(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct param_context *ctx;
|
||||
const char **ret;
|
||||
|
||||
if (argc != 1 && argc != 2) {
|
||||
ejsSetErrorMsg(eid, "param.get_list invalid argument count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = mprGetThisPtr(eid, "param");
|
||||
mprAssert(ctx);
|
||||
|
||||
if (argc == 2) {
|
||||
ret = param_get_string_list(ctx, argv[0], argv[1], NULL);
|
||||
} else {
|
||||
ret = param_get_string_list(ctx, NULL, argv[0], NULL);
|
||||
}
|
||||
|
||||
if (ret != NULL) {
|
||||
mpr_Return(eid, mprList("array", ret));
|
||||
} else {
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
set parameter
|
||||
|
||||
ok = param.set("name", "value");
|
||||
ok = param.set("section", "name", "value");
|
||||
*/
|
||||
static int ejs_param_set(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct param_context *ctx;
|
||||
const char **list;
|
||||
const char *section, *paramname;
|
||||
struct MprVar *value;
|
||||
bool ret;
|
||||
if (argc != 2 && argc != 3) {
|
||||
ejsSetErrorMsg(eid, "param.set invalid argument count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = mprGetThisPtr(eid, "param");
|
||||
mprAssert(ctx);
|
||||
|
||||
|
||||
if (argc == 3) {
|
||||
section = mprToString(argv[0]);
|
||||
paramname = mprToString(argv[1]);
|
||||
value = argv[2];
|
||||
} else {
|
||||
section = NULL;
|
||||
paramname = mprToString(argv[0]);
|
||||
value = argv[1];
|
||||
}
|
||||
|
||||
list = mprToList(mprMemCtx(), value);
|
||||
if (list) {
|
||||
ret = param_set_string_list(ctx, section, paramname, list);
|
||||
} else {
|
||||
ret = param_set_string(ctx, section, paramname, mprToString(value));
|
||||
}
|
||||
|
||||
mpr_Return(eid, mprCreateBoolVar(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
param data as a two-level array
|
||||
|
||||
data = param.data;
|
||||
*/
|
||||
static int ejs_param_data(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct param_context *ctx;
|
||||
struct MprVar ret;
|
||||
struct param_section *sec;
|
||||
|
||||
if (argc != 0) {
|
||||
ejsSetErrorMsg(eid, "param.data does not take arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = mprGetThisPtr(eid, "param");
|
||||
mprAssert(ctx);
|
||||
|
||||
ret = mprObject("array");
|
||||
|
||||
for (sec = ctx->sections; sec; sec = sec->next) {
|
||||
struct MprVar ps = mprObject("array");
|
||||
struct param *p;
|
||||
|
||||
for (p = sec->parameters; p; p = p->next) {
|
||||
mprSetVar(&ps, p->name, mprString(p->value));
|
||||
}
|
||||
|
||||
mprSetVar(&ret, sec->name, ps);
|
||||
}
|
||||
|
||||
mpr_Return(eid, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
load file
|
||||
|
||||
ok = param.load(file);
|
||||
*/
|
||||
static int ejs_param_load(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct param_context *ctx;
|
||||
bool ret;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "param.load invalid argument count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = mprGetThisPtr(eid, "param");
|
||||
mprAssert(ctx);
|
||||
|
||||
ret = param_read(ctx, argv[0]);
|
||||
|
||||
mpr_Return(eid, mprCreateBoolVar(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
save file
|
||||
|
||||
ok = param.save(file);
|
||||
*/
|
||||
static int ejs_param_save(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
struct param_context *ctx;
|
||||
bool ret;
|
||||
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "param.save invalid argument count");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = mprGetThisPtr(eid, "param");
|
||||
mprAssert(ctx);
|
||||
|
||||
ret = param_write(ctx, argv[0]);
|
||||
|
||||
mpr_Return(eid, mprCreateBoolVar(ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void param_add_members(struct MprVar *obj)
|
||||
{
|
||||
mprSetStringCFunction(obj, "get", ejs_param_get);
|
||||
mprSetStringCFunction(obj, "get_list", ejs_param_get_list);
|
||||
mprSetCFunction(obj, "set", ejs_param_set);
|
||||
mprSetStringCFunction(obj, "load", ejs_param_load);
|
||||
mprSetStringCFunction(obj, "save", ejs_param_save);
|
||||
mprSetStringCFunction(obj, "data", ejs_param_data);
|
||||
}
|
||||
|
||||
/*
|
||||
initialise param ejs subsystem
|
||||
*/
|
||||
static int ejs_param_init(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct MprVar *obj = mprInitObject(eid, "param", argc, argv);
|
||||
|
||||
mprSetPtrChild(obj, "param", param_init(mprMemCtx()));
|
||||
|
||||
param_add_members(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct MprVar mprParam(struct param_context *ctx)
|
||||
{
|
||||
struct MprVar mpv = mprObject("param");
|
||||
mprSetPtrChild(&mpv, "param", ctx);
|
||||
param_add_members(&mpv);
|
||||
return mpv;
|
||||
}
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
void smb_setup_ejs_param(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "param_init", ejs_param_init, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide access to randomisation 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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "system/passwd.h"
|
||||
#include "librpc/gen_ndr/ndr_misc.h"
|
||||
|
||||
/*
|
||||
usage:
|
||||
var i = random();
|
||||
*/
|
||||
static int ejs_random(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
mpr_Return(eid, mprCreateIntegerVar(generate_random()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
usage:
|
||||
var s = randpass(len);
|
||||
*/
|
||||
static int ejs_randpass(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
char *s;
|
||||
if (argc != 1 || !mprVarIsNumber(argv[0]->type)) {
|
||||
ejsSetErrorMsg(eid, "randpass invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
s = generate_random_str(mprMemCtx(), mprToInt(argv[0]));
|
||||
mpr_Return(eid, mprString(s));
|
||||
talloc_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
usage:
|
||||
var guid = randguid();
|
||||
*/
|
||||
static int ejs_randguid(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct GUID guid = GUID_random();
|
||||
char *s = GUID_string(mprMemCtx(), &guid);
|
||||
mpr_Return(eid, mprString(s));
|
||||
talloc_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
usage:
|
||||
var sid = randsid();
|
||||
*/
|
||||
static int ejs_randsid(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
char *s = talloc_asprintf(mprMemCtx(), "S-1-5-21-%8u-%8u-%8u",
|
||||
(unsigned)generate_random(),
|
||||
(unsigned)generate_random(),
|
||||
(unsigned)generate_random());
|
||||
mpr_Return(eid, mprString(s));
|
||||
talloc_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
initialise random ejs subsystem
|
||||
*/
|
||||
static int ejs_random_init(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct MprVar *obj = mprInitObject(eid, "random", argc, argv);
|
||||
|
||||
mprSetCFunction(obj, "random", ejs_random);
|
||||
mprSetCFunction(obj, "randpass", ejs_randpass);
|
||||
mprSetCFunction(obj, "randguid", ejs_randguid);
|
||||
mprSetCFunction(obj, "randsid", ejs_randsid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
NTSTATUS smb_setup_ejs_random(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "random_init", ejs_random_init, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide interfaces to rpc 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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "librpc/gen_ndr/echo.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "lib/messaging/irpc.h"
|
||||
#include "scripting/ejs/ejsrpc.h"
|
||||
#include "lib/util/dlinklist.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "librpc/rpc/dcerpc_table.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
|
||||
/*
|
||||
state of a irpc 'connection'
|
||||
*/
|
||||
struct ejs_irpc_connection {
|
||||
const char *server_name;
|
||||
uint32_t *dest_ids;
|
||||
struct messaging_context *msg_ctx;
|
||||
};
|
||||
|
||||
/*
|
||||
messaging clients need server IDs as well ...
|
||||
*/
|
||||
#define EJS_ID_BASE 0x30000000
|
||||
|
||||
/*
|
||||
setup a context for talking to a irpc server
|
||||
example:
|
||||
status = irpc.connect("smb_server");
|
||||
*/
|
||||
static int ejs_irpc_connect(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
struct event_context *ev;
|
||||
struct ejs_irpc_connection *p;
|
||||
struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
|
||||
|
||||
/* validate arguments */
|
||||
if (argc != 1) {
|
||||
ejsSetErrorMsg(eid, "rpc_connect invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = talloc(this, struct ejs_irpc_connection);
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->server_name = argv[0];
|
||||
|
||||
ev = event_context_find(p);
|
||||
|
||||
/* create a messaging context, looping as we have no way to
|
||||
allocate temporary server ids automatically */
|
||||
for (i=0;i<10000;i++) {
|
||||
p->msg_ctx = messaging_init(p, EJS_ID_BASE + i, ev);
|
||||
if (p->msg_ctx) break;
|
||||
}
|
||||
if (p->msg_ctx == NULL) {
|
||||
ejsSetErrorMsg(eid, "irpc_connect unable to create a messaging context");
|
||||
talloc_free(p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p->dest_ids = irpc_servers_byname(p->msg_ctx, p->server_name);
|
||||
if (p->dest_ids == NULL || p->dest_ids[0] == 0) {
|
||||
talloc_free(p);
|
||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
} else {
|
||||
mprSetPtrChild(this, "irpc", p);
|
||||
status = NT_STATUS_OK;
|
||||
}
|
||||
|
||||
mpr_Return(eid, mprNTSTATUS(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
connect to an rpc server
|
||||
examples:
|
||||
status = rpc.connect("ncacn_ip_tcp:localhost");
|
||||
status = rpc.connect("ncacn_ip_tcp:localhost", "pipe_name");
|
||||
*/
|
||||
static int ejs_rpc_connect(MprVarHandle eid, int argc, char **argv)
|
||||
{
|
||||
const char *binding, *pipe_name;
|
||||
const struct dcerpc_interface_table *iface;
|
||||
NTSTATUS status;
|
||||
struct dcerpc_pipe *p;
|
||||
struct cli_credentials *creds;
|
||||
struct event_context *ev;
|
||||
struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
|
||||
struct MprVar *credentials;
|
||||
|
||||
/* validate arguments */
|
||||
if (argc < 1) {
|
||||
ejsSetErrorMsg(eid, "rpc_connect invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
binding = argv[0];
|
||||
if (strchr(binding, ':') == NULL) {
|
||||
/* its an irpc connect */
|
||||
return ejs_irpc_connect(eid, argc, argv);
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
pipe_name = argv[1];
|
||||
} else {
|
||||
pipe_name = mprToString(mprGetProperty(this, "pipe_name", NULL));
|
||||
}
|
||||
|
||||
iface = idl_iface_by_name(pipe_name);
|
||||
if (iface == NULL) {
|
||||
status = NT_STATUS_OBJECT_NAME_INVALID;
|
||||
goto done;
|
||||
}
|
||||
|
||||
credentials = mprGetProperty(this, "credentials", NULL);
|
||||
if (credentials) {
|
||||
creds = mprGetPtr(credentials, "creds");
|
||||
} else {
|
||||
creds = cmdline_credentials;
|
||||
}
|
||||
if (creds == NULL) {
|
||||
creds = cli_credentials_init(mprMemCtx());
|
||||
cli_credentials_guess(creds);
|
||||
cli_credentials_set_anonymous(creds);
|
||||
}
|
||||
|
||||
ev = event_context_find(mprMemCtx());
|
||||
|
||||
status = dcerpc_pipe_connect(this, &p, binding, iface, creds, ev);
|
||||
if (!NT_STATUS_IS_OK(status)) goto done;
|
||||
|
||||
/* callers don't allocate ref vars in the ejs interface */
|
||||
p->conn->flags |= DCERPC_NDR_REF_ALLOC;
|
||||
|
||||
/* by making the pipe a child of the connection variable, it will
|
||||
auto close when it goes out of scope in the script */
|
||||
mprSetPtrChild(this, "pipe", p);
|
||||
|
||||
done:
|
||||
mpr_Return(eid, mprNTSTATUS(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
make an irpc call - called via the same interface as rpc
|
||||
*/
|
||||
static int ejs_irpc_call(int eid, struct MprVar *io,
|
||||
const struct dcerpc_interface_table *iface, int callnum,
|
||||
ejs_pull_function_t ejs_pull, ejs_push_function_t ejs_push)
|
||||
{
|
||||
NTSTATUS status;
|
||||
void *ptr;
|
||||
struct ejs_rpc *ejs;
|
||||
const struct dcerpc_interface_call *call;
|
||||
struct ejs_irpc_connection *p;
|
||||
struct irpc_request **reqs;
|
||||
int i, count;
|
||||
struct MprVar *results;
|
||||
|
||||
p = mprGetThisPtr(eid, "irpc");
|
||||
|
||||
ejs = talloc(mprMemCtx(), struct ejs_rpc);
|
||||
if (ejs == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
call = &iface->calls[callnum];
|
||||
|
||||
ejs->eid = eid;
|
||||
ejs->callname = call->name;
|
||||
|
||||
/* allocate the C structure */
|
||||
ptr = talloc_zero_size(ejs, call->struct_size);
|
||||
if (ptr == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* convert the mpr object into a C structure */
|
||||
status = ejs_pull(ejs, io, ptr);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (count=0;p->dest_ids[count];count++) /* noop */ ;
|
||||
|
||||
/* we need to make a call per server */
|
||||
reqs = talloc_array(ejs, struct irpc_request *, count);
|
||||
if (reqs == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* make the actual calls */
|
||||
for (i=0;i<count;i++) {
|
||||
reqs[i] = irpc_call_send(p->msg_ctx, p->dest_ids[i],
|
||||
iface, callnum, ptr, ptr);
|
||||
if (reqs[i] == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
talloc_steal(reqs, reqs[i]);
|
||||
}
|
||||
|
||||
mprSetVar(io, "results", mprObject("results"));
|
||||
results = mprGetProperty(io, "results", NULL);
|
||||
|
||||
/* and receive the results, placing them in io.results[i] */
|
||||
for (i=0;i<count;i++) {
|
||||
struct MprVar *output;
|
||||
|
||||
status = irpc_call_recv(reqs[i]);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
status = ejs_push(ejs, io, ptr);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* add to the results array */
|
||||
output = mprGetProperty(io, "output", NULL);
|
||||
if (output) {
|
||||
char idx[16];
|
||||
mprItoa(i, idx, sizeof(idx));
|
||||
mprSetProperty(results, idx, output);
|
||||
mprDeleteProperty(io, "output");
|
||||
}
|
||||
}
|
||||
mprSetVar(results, "length", mprCreateIntegerVar(i));
|
||||
|
||||
done:
|
||||
talloc_free(ejs);
|
||||
mpr_Return(eid, mprNTSTATUS(status));
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
backend code for making an rpc call - this is called from the pidl generated ejs
|
||||
code
|
||||
*/
|
||||
int ejs_rpc_call(int eid, int argc, struct MprVar **argv,
|
||||
const struct dcerpc_interface_table *iface, int callnum,
|
||||
ejs_pull_function_t ejs_pull, ejs_push_function_t ejs_push)
|
||||
{
|
||||
struct MprVar *io;
|
||||
struct dcerpc_pipe *p;
|
||||
NTSTATUS status;
|
||||
void *ptr;
|
||||
struct rpc_request *req;
|
||||
struct ejs_rpc *ejs;
|
||||
const struct dcerpc_interface_call *call;
|
||||
|
||||
if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) {
|
||||
ejsSetErrorMsg(eid, "rpc_call invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
io = argv[0];
|
||||
|
||||
if (mprGetThisPtr(eid, "irpc")) {
|
||||
/* its an irpc call */
|
||||
return ejs_irpc_call(eid, io, iface, callnum, ejs_pull, ejs_push);
|
||||
}
|
||||
|
||||
/* get the pipe info */
|
||||
p = mprGetThisPtr(eid, "pipe");
|
||||
if (p == NULL) {
|
||||
ejsSetErrorMsg(eid, "rpc_call invalid pipe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ejs = talloc(mprMemCtx(), struct ejs_rpc);
|
||||
if (ejs == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
call = &iface->calls[callnum];
|
||||
|
||||
ejs->eid = eid;
|
||||
ejs->callname = call->name;
|
||||
|
||||
/* allocate the C structure */
|
||||
ptr = talloc_zero_size(ejs, call->struct_size);
|
||||
if (ptr == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* convert the mpr object into a C structure */
|
||||
status = ejs_pull(ejs, io, ptr);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* make the actual call */
|
||||
req = dcerpc_ndr_request_send(p, NULL, iface, callnum, ptr, ptr);
|
||||
|
||||
/* if requested, print the structure */
|
||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
|
||||
ndr_print_function_debug(call->ndr_print, call->name, NDR_IN, ptr);
|
||||
}
|
||||
|
||||
if (req == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = dcerpc_ndr_request_recv(req);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* print the 'out' structure, if needed */
|
||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_OUT) {
|
||||
ndr_print_function_debug(call->ndr_print, call->name, NDR_OUT, ptr);
|
||||
}
|
||||
|
||||
status = ejs_push(ejs, io, ptr);
|
||||
|
||||
done:
|
||||
talloc_free(ejs);
|
||||
mpr_Return(eid, mprNTSTATUS(status));
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
hook called by generated RPC interfaces at the end of their init routines
|
||||
used to add generic operations on the pipe
|
||||
*/
|
||||
int ejs_rpc_init(struct MprVar *obj, const char *name)
|
||||
{
|
||||
dcerpc_table_init();
|
||||
|
||||
mprSetStringCFunction(obj, "connect", ejs_rpc_connect);
|
||||
if (mprGetProperty(obj, "pipe_name", NULL) == NULL) {
|
||||
mprSetVar(obj, "pipe_name", mprString(name));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
provide hooks into smbd C calls from ejs scripts
|
||||
|
||||
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 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 "scripting/ejs/smbcalls.h"
|
||||
#include "lib/appweb/ejs/ejs.h"
|
||||
#include "lib/samba3/samba3.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "librpc/gen_ndr/ndr_misc.h"
|
||||
|
||||
|
||||
static struct MprVar mprRegistry(struct samba3_regdb *reg)
|
||||
{
|
||||
struct MprVar mpv = mprObject("registry"), ks, vs, k, v;
|
||||
int i, j;
|
||||
|
||||
ks = mprArray("array");
|
||||
|
||||
for (i = 0; i < reg->key_count; i++) {
|
||||
k = mprObject("regkey");
|
||||
|
||||
mprSetVar(&k, "name", mprString(reg->keys[i].name));
|
||||
|
||||
vs = mprArray("array");
|
||||
|
||||
for (j = 0; j < reg->keys[i].value_count; j++) {
|
||||
v = mprObject("regval");
|
||||
|
||||
mprSetVar(&v, "name", mprString(reg->keys[i].values[j].name));
|
||||
mprSetVar(&v, "type", mprCreateIntegerVar(reg->keys[i].values[j].type));
|
||||
mprSetVar(&v, "data", mprDataBlob(reg->keys[i].values[j].data));
|
||||
|
||||
mprAddArray(&vs, j, v);
|
||||
}
|
||||
|
||||
mprSetVar(&k, "values", vs);
|
||||
|
||||
mprAddArray(&ks, i, k);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&ks, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
mprSetVar(&mpv, "keys", ks);
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprPolicy(struct samba3_policy *pol)
|
||||
{
|
||||
struct MprVar mpv = mprObject("policy");
|
||||
|
||||
mprSetVar(&mpv, "min_password_length", mprCreateIntegerVar(pol->min_password_length));
|
||||
mprSetVar(&mpv, "password_history", mprCreateIntegerVar(pol->password_history));
|
||||
mprSetVar(&mpv, "user_must_logon_to_change_password", mprCreateIntegerVar(pol->user_must_logon_to_change_password));
|
||||
mprSetVar(&mpv, "maximum_password_age", mprCreateIntegerVar(pol->maximum_password_age));
|
||||
mprSetVar(&mpv, "minimum_password_age", mprCreateIntegerVar(pol->minimum_password_age));
|
||||
mprSetVar(&mpv, "lockout_duration", mprCreateIntegerVar(pol->lockout_duration));
|
||||
mprSetVar(&mpv, "reset_count_minutes", mprCreateIntegerVar(pol->reset_count_minutes));
|
||||
mprSetVar(&mpv, "bad_lockout_minutes", mprCreateIntegerVar(pol->bad_lockout_minutes));
|
||||
mprSetVar(&mpv, "disconnect_time", mprCreateIntegerVar(pol->disconnect_time));
|
||||
mprSetVar(&mpv, "refuse_machine_password_change", mprCreateIntegerVar(pol->refuse_machine_password_change));
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprIdmapDb(struct samba3_idmapdb *db)
|
||||
{
|
||||
struct MprVar mpv = mprObject("idmapdb"), mps, mp;
|
||||
int i;
|
||||
|
||||
mprSetVar(&mpv, "user_hwm", mprCreateIntegerVar(db->user_hwm));
|
||||
mprSetVar(&mpv, "group_hwm", mprCreateIntegerVar(db->group_hwm));
|
||||
|
||||
mps = mprArray("array");
|
||||
|
||||
for (i = 0; i < db->mapping_count; i++) {
|
||||
char *tmp;
|
||||
mp = mprObject("idmap");
|
||||
|
||||
mprSetVar(&mp, "IDMAP_GROUP", mprCreateIntegerVar(IDMAP_GROUP));
|
||||
mprSetVar(&mp, "IDMAP_USER", mprCreateIntegerVar(IDMAP_USER));
|
||||
mprSetVar(&mp, "type", mprCreateIntegerVar(db->mappings[i].type));
|
||||
mprSetVar(&mp, "unix_id", mprCreateIntegerVar(db->mappings[i].unix_id));
|
||||
|
||||
tmp = dom_sid_string(NULL, db->mappings[i].sid);
|
||||
mprSetVar(&mp, "sid", mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
|
||||
mprAddArray(&mps, i, mp);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&mpv, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
|
||||
mprSetVar(&mpv, "mappings", mps);
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprGroupMappings(struct samba3_groupdb *db)
|
||||
{
|
||||
struct MprVar mpv = mprArray("array"), g;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < db->groupmap_count; i++) {
|
||||
char *tmp;
|
||||
g = mprObject("group");
|
||||
|
||||
mprSetVar(&g, "gid", mprCreateIntegerVar(db->groupmappings[i].gid));
|
||||
|
||||
tmp = dom_sid_string(NULL, db->groupmappings[i].sid);
|
||||
mprSetVar(&g, "sid", mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
|
||||
mprSetVar(&g, "sid_name_use", mprCreateIntegerVar(db->groupmappings[i].sid_name_use));
|
||||
mprSetVar(&g, "nt_name", mprString(db->groupmappings[i].nt_name));
|
||||
mprSetVar(&g, "comment", mprString(db->groupmappings[i].comment));
|
||||
|
||||
mprAddArray(&mpv, i, g);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&mpv, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprAliases(struct samba3_groupdb *db)
|
||||
{
|
||||
struct MprVar mpv = mprObject("array"), a, am;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < db->alias_count; i++) {
|
||||
char *tmp;
|
||||
a = mprObject("alias");
|
||||
|
||||
tmp = dom_sid_string(NULL, db->aliases[i].sid);
|
||||
mprSetVar(&a, "sid", mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
|
||||
am = mprArray("array");
|
||||
|
||||
for (j = 0; j < db->aliases[i].member_count; j++) {
|
||||
tmp = dom_sid_string(NULL, db->aliases[i].members[j]);
|
||||
mprAddArray(&am, j, mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
}
|
||||
|
||||
mprSetVar(&a, "members", am);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&mpv, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprDomainSecrets(struct samba3_domainsecrets *ds)
|
||||
{
|
||||
struct MprVar v, e = mprObject("domainsecrets");
|
||||
char *tmp;
|
||||
DATA_BLOB blob;
|
||||
|
||||
mprSetVar(&e, "name", mprString(ds->name));
|
||||
|
||||
tmp = dom_sid_string(NULL, &ds->sid);
|
||||
mprSetVar(&e, "sid", mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
|
||||
tmp = GUID_string(NULL, &ds->guid);
|
||||
mprSetVar(&e, "guid", mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
|
||||
mprSetVar(&e, "plaintext_pw", mprString(ds->plaintext_pw));
|
||||
|
||||
mprSetVar(&e, "last_change_time", mprCreateIntegerVar(ds->last_change_time));
|
||||
mprSetVar(&e, "sec_channel_type", mprCreateIntegerVar(ds->sec_channel_type));
|
||||
|
||||
v = mprObject("hash_pw");
|
||||
|
||||
blob.data = ds->hash_pw.hash;
|
||||
blob.length = 16;
|
||||
mprSetVar(&v, "hash", mprDataBlob(blob));
|
||||
|
||||
mprSetVar(&v, "mod_time", mprCreateIntegerVar(ds->hash_pw.mod_time));
|
||||
|
||||
mprSetVar(&e, "hash_pw", v);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct MprVar mprSecrets(struct samba3_secrets *sec)
|
||||
{
|
||||
struct MprVar mpv = mprObject("samba3_secrets"), es, e;
|
||||
int i;
|
||||
|
||||
es = mprArray("array");
|
||||
|
||||
for (i = 0; i < sec->ldappw_count; i++) {
|
||||
e = mprObject("ldappw");
|
||||
|
||||
mprSetVar(&e, "dn", mprString(sec->ldappws[i].dn));
|
||||
mprSetVar(&e, "password", mprString(sec->ldappws[i].password));
|
||||
|
||||
mprAddArray(&es, i, e);
|
||||
}
|
||||
|
||||
mprSetVar(&mpv, "ldappws", es);
|
||||
|
||||
es = mprArray("array");
|
||||
|
||||
for (i = 0; i < sec->domain_count; i++) {
|
||||
mprAddArray(&es, i, mprDomainSecrets(&sec->domains[i]));
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&es, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
mprSetVar(&mpv, "domains", es);
|
||||
|
||||
es = mprArray("trusted_domains");
|
||||
|
||||
for (i = 0; i < sec->trusted_domain_count; i++) {
|
||||
struct MprVar ns;
|
||||
char *tmp;
|
||||
int j;
|
||||
e = mprObject("trusted_domain");
|
||||
|
||||
ns = mprArray("array");
|
||||
|
||||
for (j = 0; j < sec->trusted_domains[i].uni_name_len; j++) {
|
||||
mprAddArray(&ns, j, mprString(sec->trusted_domains[i].uni_name[j]));
|
||||
}
|
||||
|
||||
mprSetVar(&e, "uni_name", ns);
|
||||
|
||||
mprSetVar(&e, "pass", mprString(sec->trusted_domains[i].pass));
|
||||
mprSetVar(&e, "mod_time", mprCreateIntegerVar(sec->trusted_domains[i].mod_time));
|
||||
|
||||
tmp = dom_sid_string(NULL, &sec->trusted_domains[i].domain_sid);
|
||||
mprSetVar(&e, "domains_sid", mprString(tmp));
|
||||
talloc_free(tmp);
|
||||
|
||||
mprAddArray(&es, i, e);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&es, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
mprSetVar(&mpv, "trusted_domains", es);
|
||||
|
||||
es = mprArray("array");
|
||||
|
||||
for (i = 0; i < sec->afs_keyfile_count; i++) {
|
||||
struct MprVar ks;
|
||||
int j;
|
||||
e = mprObject("afs_keyfile");
|
||||
|
||||
mprSetVar(&e, "cell", mprString(sec->afs_keyfiles[i].cell));
|
||||
|
||||
ks = mprArray("array");
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
struct MprVar k = mprObject("entry");
|
||||
DATA_BLOB blob;
|
||||
|
||||
mprSetVar(&k, "kvno", mprCreateIntegerVar(sec->afs_keyfiles[i].entry[j].kvno));
|
||||
blob.data = (uint8_t*)sec->afs_keyfiles[i].entry[j].key;
|
||||
blob.length = 8;
|
||||
mprSetVar(&k, "key", mprDataBlob(blob));
|
||||
|
||||
mprAddArray(&ks, j, k);
|
||||
}
|
||||
|
||||
mprSetVar(&e, "entry", ks);
|
||||
|
||||
mprSetVar(&e, "nkeys", mprCreateIntegerVar(sec->afs_keyfiles[i].nkeys));
|
||||
|
||||
mprAddArray(&es, i, e);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&es, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
mprSetVar(&mpv, "afs_keyfiles", es);
|
||||
|
||||
mprSetVar(&mpv, "ipc_cred", mprCredentials(sec->ipc_cred));
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprShares(struct samba3 *samba3)
|
||||
{
|
||||
struct MprVar mpv = mprArray("array"), s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samba3->share_count; i++) {
|
||||
s = mprObject("share");
|
||||
|
||||
mprSetVar(&s, "name", mprString(samba3->shares[i].name));
|
||||
|
||||
/* FIXME: secdesc */
|
||||
|
||||
mprAddArray(&mpv, i, s);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&mpv, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprSamAccounts(struct samba3 *samba3)
|
||||
{
|
||||
struct MprVar mpv = mprArray("array"), m;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < samba3->samaccount_count; i++) {
|
||||
struct samba3_samaccount *a = &samba3->samaccounts[i];
|
||||
DATA_BLOB blob;
|
||||
|
||||
m = mprObject("samba3_samaccount");
|
||||
|
||||
mprSetVar(&m, "logon_time", mprCreateIntegerVar(a->logon_time));
|
||||
mprSetVar(&m, "logoff_time", mprCreateIntegerVar(a->logoff_time));
|
||||
mprSetVar(&m, "kickoff_time", mprCreateIntegerVar(a->kickoff_time));
|
||||
mprSetVar(&m, "bad_password_time", mprCreateIntegerVar(a->bad_password_time));
|
||||
mprSetVar(&m, "pass_last_set_time", mprCreateIntegerVar(a->pass_last_set_time));
|
||||
mprSetVar(&m, "pass_can_change_time", mprCreateIntegerVar(a->pass_can_change_time));
|
||||
mprSetVar(&m, "pass_must_change_time", mprCreateIntegerVar(a->pass_must_change_time));
|
||||
mprSetVar(&m, "user_rid", mprCreateIntegerVar(a->user_rid));
|
||||
mprSetVar(&m, "group_rid", mprCreateIntegerVar(a->group_rid));
|
||||
mprSetVar(&m, "acct_ctrl", mprCreateIntegerVar(a->acct_ctrl));
|
||||
mprSetVar(&m, "logon_divs", mprCreateIntegerVar(a->logon_divs));
|
||||
mprSetVar(&m, "bad_password_count", mprCreateIntegerVar(a->bad_password_count));
|
||||
mprSetVar(&m, "logon_count", mprCreateIntegerVar(a->logon_count));
|
||||
mprSetVar(&m, "username", mprString(a->username));
|
||||
mprSetVar(&m, "domain", mprString(a->domain));
|
||||
mprSetVar(&m, "nt_username", mprString(a->nt_username));
|
||||
mprSetVar(&m, "dir_drive", mprString(a->dir_drive));
|
||||
mprSetVar(&m, "munged_dial", mprString(a->munged_dial));
|
||||
mprSetVar(&m, "fullname", mprString(a->fullname));
|
||||
mprSetVar(&m, "homedir", mprString(a->homedir));
|
||||
mprSetVar(&m, "logon_script", mprString(a->logon_script));
|
||||
mprSetVar(&m, "profile_path", mprString(a->profile_path));
|
||||
mprSetVar(&m, "acct_desc", mprString(a->acct_desc));
|
||||
mprSetVar(&m, "workstations", mprString(a->workstations));
|
||||
blob.length = 16;
|
||||
blob.data = a->lm_pw.hash;
|
||||
mprSetVar(&m, "lm_pw", mprDataBlob(blob));
|
||||
blob.data = a->nt_pw.hash;
|
||||
mprSetVar(&m, "nt_pw", mprDataBlob(blob));
|
||||
|
||||
mprAddArray(&mpv, i, m);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&mpv, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static struct MprVar mprWinsEntries(struct samba3 *samba3)
|
||||
{
|
||||
struct MprVar mpv = mprArray("array");
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < samba3->winsdb_count; i++) {
|
||||
struct MprVar w = mprObject("wins_entry"), ips;
|
||||
|
||||
mprSetVar(&w, "name", mprString(samba3->winsdb_entries[i].name));
|
||||
mprSetVar(&w, "nb_flags", mprCreateIntegerVar(samba3->winsdb_entries[i].nb_flags));
|
||||
mprSetVar(&w, "type", mprCreateIntegerVar(samba3->winsdb_entries[i].type));
|
||||
mprSetVar(&w, "ttl", mprCreateIntegerVar(samba3->winsdb_entries[i].ttl));
|
||||
|
||||
ips = mprObject("array");
|
||||
|
||||
for (j = 0; j < samba3->winsdb_entries[i].ip_count; j++) {
|
||||
const char *addr;
|
||||
addr = sys_inet_ntoa(samba3->winsdb_entries[i].ips[j]);
|
||||
mprAddArray(&ips, j, mprString(addr));
|
||||
}
|
||||
|
||||
mprSetVar(&w, "ips", ips);
|
||||
|
||||
mprAddArray(&mpv, i, w);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
mprSetVar(&mpv, "length", mprCreateIntegerVar(i));
|
||||
}
|
||||
|
||||
return mpv;
|
||||
}
|
||||
|
||||
static int ejs_find_domainsecrets(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct samba3 *samba3 = NULL;
|
||||
struct samba3_domainsecrets *sec;
|
||||
|
||||
if (argc < 1) {
|
||||
ejsSetErrorMsg(eid, "find_domainsecrets invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
samba3 = mprGetThisPtr(eid, "samba3");
|
||||
mprAssert(samba3);
|
||||
sec = samba3_find_domainsecrets(samba3, mprToString(argv[0]));
|
||||
|
||||
if (sec == NULL) {
|
||||
mpr_Return(eid, mprCreateUndefinedVar());
|
||||
} else {
|
||||
mpr_Return(eid, mprDomainSecrets(sec));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
initialise samba3 ejs subsystem
|
||||
|
||||
samba3 = samba3_read(libdir,smbconf)
|
||||
*/
|
||||
static int ejs_samba3_read(MprVarHandle eid, int argc, struct MprVar **argv)
|
||||
{
|
||||
struct MprVar mpv = mprObject("samba3");
|
||||
struct samba3 *samba3;
|
||||
NTSTATUS status;
|
||||
|
||||
if (argc < 2) {
|
||||
ejsSetErrorMsg(eid, "samba3_read invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = samba3_read(mprToString(argv[0]), mprToString(argv[1]), mprMemCtx(), &samba3);
|
||||
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
ejsSetErrorMsg(eid, "samba3_read: error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mprAssert(samba3);
|
||||
|
||||
mprSetPtrChild(&mpv, "samba3", samba3);
|
||||
mprSetVar(&mpv, "winsentries", mprWinsEntries(samba3));
|
||||
mprSetVar(&mpv, "samaccounts", mprSamAccounts(samba3));
|
||||
mprSetVar(&mpv, "shares", mprShares(samba3));
|
||||
mprSetVar(&mpv, "secrets", mprSecrets(&samba3->secrets));
|
||||
mprSetVar(&mpv, "groupmappings", mprGroupMappings(&samba3->group));
|
||||
mprSetVar(&mpv, "aliases", mprAliases(&samba3->group));
|
||||
mprSetVar(&mpv, "idmapdb", mprIdmapDb(&samba3->idmap));
|
||||
mprSetVar(&mpv, "policy", mprPolicy(&samba3->policy));
|
||||
mprSetVar(&mpv, "registry", mprRegistry(&samba3->registry));
|
||||
mprSetVar(&mpv, "configuration", mprParam(samba3->configuration));
|
||||
mprSetCFunction(&mpv, "find_domainsecrets", ejs_find_domainsecrets);
|
||||
|
||||
mpr_Return(eid, mpv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup C functions that be called from ejs
|
||||
*/
|
||||
NTSTATUS smb_setup_ejs_samba3(void)
|
||||
{
|
||||
ejsDefineCFunction(-1, "samba3_read", ejs_samba3_read, NULL, MPR_VAR_SCRIPT_HANDLE);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
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 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 "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");
|
||||
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");
|
||||
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(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;
|
||||
|
||||
/*
|
||||
hackity hack ...
|
||||
*/
|
||||
while ((p = strchr(format, '%'))) {
|
||||
char *fmt2;
|
||||
int len, len_count=0;
|
||||
char *tstr;
|
||||
ret = talloc_asprintf_append(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(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(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_size(mprMemCtx(), 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_size(mprMemCtx(), 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;
|
||||
}
|
||||
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
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 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 "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 = iface_count();
|
||||
struct MprVar ret = mprArray("interfaces");
|
||||
for (i=0;i<count;i++) {
|
||||
mprAddArray(&ret, i, mprString(iface_n_ip(i)));
|
||||
}
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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, "ntgmtime", ejs_sys_ntgmtime);
|
||||
mprSetCFunction(obj, "ldaptime", ejs_sys_ldaptime);
|
||||
mprSetCFunction(obj, "httptime", ejs_sys_httptime);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
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 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 "lib/appweb/ejs/ejsInternal.h"
|
||||
#include "scripting/ejs/smbcalls.h"
|
||||
#include "auth/gensec/gensec.h"
|
||||
#include "ldb/include/ldb.h"
|
||||
|
||||
static EjsId eid;
|
||||
|
||||
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;
|
||||
|
||||
fault_setup(argv[0]);
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
gensec_init();
|
||||
mprSetCtx(mem_ctx);
|
||||
|
||||
lp_load();
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
auth js library functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
get a list of domains for SWAT authentication
|
||||
*/
|
||||
function getDomainList()
|
||||
{
|
||||
var ret = new Array(2);
|
||||
var lp = loadparm_init();
|
||||
ret[0] = "System User";
|
||||
ret[1] = lp.get("workgroup");
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
base js library functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
if (global["HAVE_BASE_JS"] != undefined) {
|
||||
return;
|
||||
}
|
||||
HAVE_BASE_JS=1
|
||||
|
||||
/* bring the string functions into the global frame */
|
||||
string_init(global);
|
||||
|
||||
/*
|
||||
an essential function!
|
||||
*/
|
||||
function printf()
|
||||
{
|
||||
print(vsprintf(arguments));
|
||||
}
|
||||
|
||||
/*
|
||||
helper function to setup a rpc io object, ready for input
|
||||
*/
|
||||
function irpcObj()
|
||||
{
|
||||
var o = new Object();
|
||||
o.input = new Object();
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
check that a status result is OK
|
||||
*/
|
||||
function check_status_ok(status)
|
||||
{
|
||||
if (status.is_ok != true) {
|
||||
printVars(status);
|
||||
}
|
||||
assert(status.is_ok == true);
|
||||
}
|
||||
|
||||
/*
|
||||
check that two arrays are equal
|
||||
*/
|
||||
function check_array_equal(a1, a2)
|
||||
{
|
||||
assert(a1.length == a2.length);
|
||||
for (i=0; i<a1.length; i++) {
|
||||
assert(a1[i] == a2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
check that an array is all zeros
|
||||
*/
|
||||
function check_array_zero(a)
|
||||
{
|
||||
for (i=0; i<a.length; i++) {
|
||||
assert(a[i] == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
substitute strings of the form ${NAME} in str, replacing
|
||||
with substitutions from subobj
|
||||
*/
|
||||
function substitute_var(str, subobj)
|
||||
{
|
||||
var list = split("${", str);
|
||||
var i;
|
||||
for (i=1;i<list.length;i++) {
|
||||
var list2 = split("}", list[i], 1);
|
||||
if ((list2.length < 2) && (list2[0] + "}" != list[i])) {
|
||||
return undefined;
|
||||
}
|
||||
var key = list2[0];
|
||||
var val;
|
||||
if (typeof(subobj[key]) == "undefined") {
|
||||
val = "${" + key + "}";
|
||||
} else if (typeof(subobj[key]) == "string") {
|
||||
val = subobj[key];
|
||||
} else {
|
||||
var fn = subobj[key];
|
||||
val = fn(key);
|
||||
}
|
||||
list2[0] = "" + val;
|
||||
list[i] = join("", list2);
|
||||
}
|
||||
return join("", list);
|
||||
}
|
||||
|
||||
/*
|
||||
return "s" if a number should be shown as plural
|
||||
*/
|
||||
function plural(n)
|
||||
{
|
||||
if (n == 1) {
|
||||
return "";
|
||||
}
|
||||
return "s";
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
server side js functions for encoding/decoding objects into linear strings
|
||||
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL Version 2 or later
|
||||
*/
|
||||
/*
|
||||
usage:
|
||||
|
||||
enc = encodeObject(obj);
|
||||
obj = decodeObject(enc);
|
||||
|
||||
The encoded format of the object is a string that is safe to
|
||||
use in URLs
|
||||
|
||||
Note that only data elements are encoded, not functions
|
||||
*/
|
||||
|
||||
function __count_members(o) {
|
||||
var i, count = 0;
|
||||
for (i in o) {
|
||||
count++;
|
||||
}
|
||||
if (o.length != undefined) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function __replace(str, old, rep) {
|
||||
var s = string_init();
|
||||
var a = s.split(old, str);
|
||||
var j = s.join(rep, a);
|
||||
return s.join(rep, a);
|
||||
}
|
||||
|
||||
function encodeElement(e, name) {
|
||||
var t = typeof(e);
|
||||
var r;
|
||||
var s = string_init();
|
||||
if (t == 'object' && e == null) {
|
||||
t = 'null';
|
||||
}
|
||||
if (t == 'object') {
|
||||
r = s.sprintf("%s:%s:%s", name, t, encodeObject(e));
|
||||
} else if (t == "string") {
|
||||
var enc = s.encodeURIComponent(e);
|
||||
var rep = __replace(enc, '%', '#');
|
||||
r = s.sprintf("%s:%s:%s:",
|
||||
name, t, __replace(s.encodeURIComponent(e),'%','#'));
|
||||
} else if (t == "boolean" || t == "number") {
|
||||
r = s.sprintf("%s:%s:%s:", name, t, "" + e);
|
||||
} else if (t == "undefined" || t == "null") {
|
||||
r = s.sprintf("%s:%s:", name, t);
|
||||
} else if (t == "pointer") {
|
||||
r = s.sprintf("%s:string:(POINTER):", name);
|
||||
} else {
|
||||
println("Unable to linearise type " + t);
|
||||
r = "";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function encodeObject(o) {
|
||||
var s = string_init();
|
||||
var i, r = s.sprintf("%u:", __count_members(o));
|
||||
for (i in o) {
|
||||
r = r + encodeElement(o[i], i);
|
||||
}
|
||||
if (o.length != undefined) {
|
||||
r = r + encodeElement(o.length, 'length');
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function decodeObjectArray(a) {
|
||||
var s = string_init();
|
||||
var o = new Object();
|
||||
var i, count = a[a.i]; a.i++;
|
||||
for (i=0;i<count;i++) {
|
||||
var name = a[a.i]; a.i++;
|
||||
var type = a[a.i]; a.i++;
|
||||
var value;
|
||||
if (type == 'object') {
|
||||
o[name] = decodeObjectArray(a);
|
||||
} else if (type == "string") {
|
||||
value = s.decodeURIComponent(__replace(a[a.i],'#','%')); a.i++;
|
||||
o[name] = value;
|
||||
} else if (type == "boolean") {
|
||||
value = a[a.i]; a.i++;
|
||||
if (value == 'true') {
|
||||
o[name] = true;
|
||||
} else {
|
||||
o[name] = false;
|
||||
}
|
||||
} else if (type == "undefined") {
|
||||
o[name] = undefined;
|
||||
} else if (type == "null") {
|
||||
o[name] = null;
|
||||
} else if (type == "number") {
|
||||
value = a[a.i]; a.i++;
|
||||
o[name] = value + 0;
|
||||
} else {
|
||||
println("Unable to delinearise type " + t);
|
||||
assert(t == "supported type");
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function decodeObject(str) {
|
||||
var s = string_init();
|
||||
var a = s.split(':', str);
|
||||
a.i = 0;
|
||||
return decodeObjectArray(a);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
backend code for Samba4 management
|
||||
Copyright Andrew Tridgell 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
return a list of current sessions
|
||||
*/
|
||||
function smbsrv_sessions()
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
status = irpc.connect("smb_server");
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.level = irpc.SMBSRV_INFO_SESSIONS;
|
||||
status = irpc.smbsrv_information(io);
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* gather the results into a single array */
|
||||
var i, count=0, ret = new Array(0);
|
||||
for (i=0;i<io.results.length;i++) {
|
||||
var sessions = io.results[i].info.sessions.sessions;
|
||||
var j;
|
||||
for (j=0;j<sessions.length;j++) {
|
||||
ret[count] = sessions[j];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of current tree connects
|
||||
*/
|
||||
function smbsrv_tcons()
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
status = irpc.connect("smb_server");
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.level = irpc.SMBSRV_INFO_TCONS;
|
||||
status = irpc.smbsrv_information(io);
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* gather the results into a single array */
|
||||
var i, count=0, ret = new Object();
|
||||
for (i=0;i<io.results.length;i++) {
|
||||
var tcons = io.results[i].info.tcons.tcons;
|
||||
var j;
|
||||
for (j=0;j<tcons.length;j++) {
|
||||
ret[count] = tcons[j];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
ret.length = count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
return nbtd statistics
|
||||
*/
|
||||
function nbtd_statistics()
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
status = irpc.connect("nbt_server");
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.level = irpc.NBTD_INFO_STATISTICS;
|
||||
status = irpc.nbtd_information(io);
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
return io.results[0].info.stats;
|
||||
}
|
||||
|
||||
/*
|
||||
see if a service is enabled
|
||||
*/
|
||||
function service_enabled(name)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var services = lp.get("server services");
|
||||
var i;
|
||||
for (i=0;i<services.length;i++) {
|
||||
if (services[i] == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
show status of a server
|
||||
*/
|
||||
function server_status(name)
|
||||
{
|
||||
var i;
|
||||
var io;
|
||||
var irpc = irpc_init();
|
||||
|
||||
if (!service_enabled(name)) {
|
||||
return "DISABLED";
|
||||
}
|
||||
|
||||
status = irpc.connect(name + "_server");
|
||||
if (status.is_ok != true) {
|
||||
return "DOWN";
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
status = irpc.irpc_uptime(io);
|
||||
if (status.is_ok != true) {
|
||||
return "NOT RESPONDING";
|
||||
}
|
||||
|
||||
return "RUNNING";
|
||||
}
|
||||
|
||||
/*
|
||||
show status of a stream server
|
||||
*/
|
||||
function stream_server_status(name)
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
|
||||
if (!service_enabled(name)) {
|
||||
return "DISABLED";
|
||||
}
|
||||
status = irpc.connect(name + "_server");
|
||||
if (status.is_ok != true) {
|
||||
return "0 connections";
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
status = irpc.irpc_uptime(io);
|
||||
if (status.is_ok != true) {
|
||||
return "NOT RESPONDING";
|
||||
}
|
||||
|
||||
var n = io.results.length;
|
||||
return sprintf("%u connection%s", n, plural(n));
|
||||
}
|
||||
@@ -0,0 +1,870 @@
|
||||
/*
|
||||
backend code for provisioning a Samba4 server
|
||||
Copyright Andrew Tridgell 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
sys = sys_init();
|
||||
|
||||
/*
|
||||
return true if the current install seems to be OK
|
||||
*/
|
||||
function install_ok(session_info, credentials)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var ldb = ldb_init();
|
||||
ldb.session_info = session_info;
|
||||
ldb.credentials = credentials;
|
||||
if (lp.get("realm") == "") {
|
||||
return false;
|
||||
}
|
||||
var ok = ldb.connect(lp.get("sam database"));
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
var res = ldb.search("(cn=Administrator)");
|
||||
if (res.length != 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
find a user or group from a list of possibilities
|
||||
*/
|
||||
function findnss()
|
||||
{
|
||||
var i;
|
||||
assert(arguments.length >= 2);
|
||||
var nssfn = arguments[0];
|
||||
for (i=1;i<arguments.length;i++) {
|
||||
if (nssfn(arguments[i]) != undefined) {
|
||||
return arguments[i];
|
||||
}
|
||||
}
|
||||
printf("Unable to find user/group for %s\n", arguments[1]);
|
||||
assert(i<arguments.length);
|
||||
}
|
||||
|
||||
/*
|
||||
add a foreign security principle
|
||||
*/
|
||||
function add_foreign(ldb, subobj, sid, desc)
|
||||
{
|
||||
var add = sprintf("
|
||||
dn: CN=%s,CN=ForeignSecurityPrincipals,%s
|
||||
objectClass: top
|
||||
objectClass: foreignSecurityPrincipal
|
||||
description: %s
|
||||
",
|
||||
sid, subobj.BASEDN, desc);
|
||||
/* deliberately ignore errors from this, as the records may
|
||||
already exist */
|
||||
ldb.add(add);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup a mapping between a sam name and a unix name
|
||||
*/
|
||||
function setup_name_mapping(info, ldb, sid, unixname)
|
||||
{
|
||||
var attrs = new Array("dn");
|
||||
var res = ldb.search(sprintf("objectSid=%s", sid),
|
||||
info.subobj.BASEDN, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (res.length != 1) {
|
||||
info.message("Failed to find record for objectSid %s\n", sid);
|
||||
return false;
|
||||
}
|
||||
var mod = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: unixName
|
||||
unixName: %s
|
||||
",
|
||||
res[0].dn, unixname);
|
||||
var ok = ldb.modify(mod);
|
||||
if (!ok) {
|
||||
info.message("name mapping for %s failed - %s\n",
|
||||
sid, ldb.errstring());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
return current time as a nt time string
|
||||
*/
|
||||
function nttime()
|
||||
{
|
||||
return "" + sys.nttime();
|
||||
}
|
||||
|
||||
/*
|
||||
return current time as a ldap time string
|
||||
*/
|
||||
function ldaptime()
|
||||
{
|
||||
return sys.ldaptime(sys.nttime());
|
||||
}
|
||||
|
||||
/*
|
||||
return a date string suitable for a dns zone serial number
|
||||
*/
|
||||
function datestring()
|
||||
{
|
||||
var t = sys.ntgmtime(sys.nttime());
|
||||
return sprintf("%04u%02u%02u%02u",
|
||||
t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour);
|
||||
}
|
||||
|
||||
/*
|
||||
return first host IP
|
||||
*/
|
||||
function hostip()
|
||||
{
|
||||
var list = sys.interfaces();
|
||||
return list[0];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return first part of hostname
|
||||
*/
|
||||
function hostname()
|
||||
{
|
||||
var s = split(".", sys.hostname());
|
||||
return s[0];
|
||||
}
|
||||
|
||||
/* the ldb is in bad shape, possibly due to being built from an
|
||||
incompatible previous version of the code, so delete it
|
||||
completely */
|
||||
function ldb_delete(ldb)
|
||||
{
|
||||
println("Deleting " + ldb.filename);
|
||||
var lp = loadparm_init();
|
||||
sys.unlink(sprintf("%s/%s", lp.get("private dir"), ldb.filename));
|
||||
ldb.transaction_cancel();
|
||||
ldb.close();
|
||||
var ok = ldb.connect(ldb.filename);
|
||||
ldb.transaction_start();
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
/*
|
||||
erase an ldb, removing all records
|
||||
*/
|
||||
function ldb_erase(ldb)
|
||||
{
|
||||
var res;
|
||||
|
||||
/* delete the specials */
|
||||
ldb.del("@INDEXLIST");
|
||||
ldb.del("@ATTRIBUTES");
|
||||
ldb.del("@SUBCLASSES");
|
||||
ldb.del("@MODULES");
|
||||
ldb.del("@PARTITION");
|
||||
ldb.del("@KLUDGEACL");
|
||||
|
||||
/* and the rest */
|
||||
attrs = new Array("dn");
|
||||
var basedn = "";
|
||||
var res = ldb.search("(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
var i;
|
||||
if (typeof(res) == "undefined") {
|
||||
ldb_delete(ldb);
|
||||
return;
|
||||
}
|
||||
for (i=0;i<res.length;i++) {
|
||||
ldb.del(res[i].dn);
|
||||
}
|
||||
|
||||
|
||||
var res = ldb.search("(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (res.length != 0) {
|
||||
ldb_delete(ldb);
|
||||
return;
|
||||
}
|
||||
assert(res.length == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
erase an ldb, removing all records
|
||||
*/
|
||||
function ldb_erase_partitions(info, ldb)
|
||||
{
|
||||
var rootDSE_attrs = new Array("namingContexts");
|
||||
var lp = loadparm_init();
|
||||
var j;
|
||||
|
||||
var res = ldb.search("(objectClass=*)", "", ldb.SCOPE_BASE, rootDSE_attrs);
|
||||
assert(typeof(res) != "undefined");
|
||||
assert(res.length == 1);
|
||||
if (typeof(res[0].namingContexts) == "undefined") {
|
||||
return;
|
||||
}
|
||||
for (j=0; j<res[0].namingContexts.length; j++) {
|
||||
var attrs = new Array("dn");
|
||||
var basedn = res[0].namingContexts[j];
|
||||
var k;
|
||||
var previous_remaining = 1;
|
||||
var current_remaining = 0;
|
||||
|
||||
for (k=0; k < 10 && (previous_remaining != current_remaining); k++) {
|
||||
/* and the rest */
|
||||
var res2 = ldb.search("(|(objectclass=*)(dn=*))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
var i;
|
||||
if (typeof(res2) == "undefined") {
|
||||
info.message("ldb search failed: " + ldb.errstring() + "\n");
|
||||
continue;
|
||||
}
|
||||
previous_remaining = current_remaining;
|
||||
current_remaining = res2.length;
|
||||
for (i=0;i<res2.length;i++) {
|
||||
ldb.del(res2[i].dn);
|
||||
}
|
||||
|
||||
var res3 = ldb.search("(|(objectclass=*)(dn=*))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (typeof(res3) == "undefined") {
|
||||
info.message("ldb search failed: " + ldb.errstring() + "\n");
|
||||
continue;
|
||||
}
|
||||
if (res3.length != 0) {
|
||||
info.message("Failed to delete all records under " + basedn + ", " + res3.length + " records remaining\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function open_ldb(info, dbname, erase)
|
||||
{
|
||||
var ldb = ldb_init();
|
||||
ldb.session_info = info.session_info;
|
||||
ldb.credentials = info.credentials;
|
||||
ldb.filename = dbname;
|
||||
|
||||
var connect_ok = ldb.connect(dbname);
|
||||
if (!connect_ok) {
|
||||
var lp = loadparm_init();
|
||||
sys.unlink(sprintf("%s/%s", lp.get("private dir"), dbname));
|
||||
connect_ok = ldb.connect(dbname);
|
||||
assert(connect_ok);
|
||||
}
|
||||
|
||||
ldb.transaction_start();
|
||||
|
||||
if (erase) {
|
||||
ldb_erase(ldb);
|
||||
}
|
||||
return ldb;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup a ldb in the private dir
|
||||
*/
|
||||
function setup_add_ldif(ldif, info, ldb, failok)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var src = lp.get("setup directory") + "/" + ldif;
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, info.subobj);
|
||||
|
||||
var add_ok = ldb.add(data);
|
||||
if (!add_ok) {
|
||||
info.message("ldb load failed: " + ldb.errstring() + "\n");
|
||||
if (!failok) {
|
||||
assert(add_ok);
|
||||
}
|
||||
}
|
||||
return add_ok;
|
||||
}
|
||||
|
||||
function setup_modify_ldif(ldif, info, ldb, failok)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var src = lp.get("setup directory") + "/" + ldif;
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, info.subobj);
|
||||
|
||||
var mod_ok = ldb.modify(data);
|
||||
if (!mod_ok) {
|
||||
info.message("ldb load failed: " + ldb.errstring() + "\n");
|
||||
if (!failok) {
|
||||
assert(mod_ok);
|
||||
}
|
||||
}
|
||||
return mod_ok;
|
||||
}
|
||||
|
||||
|
||||
function setup_ldb(ldif, info, dbname)
|
||||
{
|
||||
var erase = true;
|
||||
var failok = false;
|
||||
|
||||
if (arguments.length >= 4) {
|
||||
erase = arguments[3];
|
||||
}
|
||||
if (arguments.length == 5) {
|
||||
failok = arguments[4];
|
||||
}
|
||||
var ldb = open_ldb(info, dbname, erase);
|
||||
if (setup_add_ldif(ldif, info, ldb, failok)) {
|
||||
var commit_ok = ldb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("ldb commit failed: " + ldb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
setup a ldb in the private dir
|
||||
*/
|
||||
function setup_ldb_modify(ldif, info, ldb)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
|
||||
var src = lp.get("setup directory") + "/" + ldif;
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, info.subobj);
|
||||
|
||||
var mod_ok = ldb.modify(data);
|
||||
if (!mod_ok) {
|
||||
info.message("ldb load failed: " + ldb.errstring() + "\n");
|
||||
return mod_ok;
|
||||
}
|
||||
return mod_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
setup a file in the private dir
|
||||
*/
|
||||
function setup_file(template, message, fname, subobj)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var f = fname;
|
||||
var src = lp.get("setup directory") + "/" + template;
|
||||
|
||||
sys.unlink(f);
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, subobj);
|
||||
|
||||
ok = sys.file_save(f, data);
|
||||
if (!ok) {
|
||||
message("failed to create file: " + f + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
}
|
||||
|
||||
function provision_default_paths(subobj)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var paths = new Object();
|
||||
paths.smbconf = lp.get("config file");
|
||||
paths.shareconf = lp.get("private dir") + "/" + "share.ldb";
|
||||
paths.hklm = "hklm.ldb";
|
||||
paths.hkcu = "hkcu.ldb";
|
||||
paths.hkcr = "hkcr.ldb";
|
||||
paths.hku = "hku.ldb";
|
||||
paths.hkpd = "hkpd.ldb";
|
||||
paths.hkpt = "hkpt.ldb";
|
||||
paths.samdb = lp.get("sam database");
|
||||
paths.secrets = "secrets.ldb";
|
||||
paths.dns = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".zone";
|
||||
paths.winsdb = "wins.ldb";
|
||||
paths.ldap_basedn_ldif = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".ldif";
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup reasonable name mappings for sam names to unix names
|
||||
*/
|
||||
function setup_name_mappings(info, ldb)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var attrs = new Array("objectSid");
|
||||
var subobj = info.subobj;
|
||||
|
||||
res = ldb.search("objectSid=*", subobj.BASEDN, ldb.SCOPE_BASE, attrs);
|
||||
assert(res.length == 1 && res[0].objectSid != undefined);
|
||||
var sid = res[0].objectSid;
|
||||
|
||||
/* add some foreign sids if they are not present already */
|
||||
add_foreign(ldb, subobj, "S-1-5-7", "Anonymous");
|
||||
add_foreign(ldb, subobj, "S-1-1-0", "World");
|
||||
add_foreign(ldb, subobj, "S-1-5-2", "Network");
|
||||
add_foreign(ldb, subobj, "S-1-5-18", "System");
|
||||
add_foreign(ldb, subobj, "S-1-5-11", "Authenticated Users");
|
||||
|
||||
/* some well known sids */
|
||||
setup_name_mapping(info, ldb, "S-1-5-7", subobj.NOBODY);
|
||||
setup_name_mapping(info, ldb, "S-1-1-0", subobj.NOGROUP);
|
||||
setup_name_mapping(info, ldb, "S-1-5-2", subobj.NOGROUP);
|
||||
setup_name_mapping(info, ldb, "S-1-5-18", subobj.ROOT);
|
||||
setup_name_mapping(info, ldb, "S-1-5-11", subobj.USERS);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-544", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-545", subobj.USERS);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-546", subobj.NOGROUP);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-551", subobj.BACKUP);
|
||||
|
||||
/* and some well known domain rids */
|
||||
setup_name_mapping(info, ldb, sid + "-500", subobj.ROOT);
|
||||
setup_name_mapping(info, ldb, sid + "-518", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, sid + "-519", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, sid + "-512", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, sid + "-513", subobj.USERS);
|
||||
setup_name_mapping(info, ldb, sid + "-520", subobj.WHEEL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
provision samba4 - caution, this wipes all existing data!
|
||||
*/
|
||||
function provision(subobj, message, blank, paths, session_info, credentials)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var sys = sys_init();
|
||||
var info = new Object();
|
||||
|
||||
/*
|
||||
some options need to be upper/lower case
|
||||
*/
|
||||
subobj.REALM = strupper(subobj.REALM);
|
||||
subobj.HOSTNAME = strlower(subobj.HOSTNAME);
|
||||
subobj.DOMAIN = strupper(subobj.DOMAIN);
|
||||
assert(valid_netbios_name(subobj.DOMAIN));
|
||||
subobj.NETBIOSNAME = strupper(subobj.HOSTNAME);
|
||||
assert(valid_netbios_name(subobj.NETBIOSNAME));
|
||||
var rdns = split(",", subobj.BASEDN);
|
||||
subobj.RDN_DC = substr(rdns[0], strlen("DC="));
|
||||
|
||||
if (subobj.DOMAINGUID != undefined) {
|
||||
subobj.DOMAINGUID_MOD = sprintf("replace: objectGUID\nobjectGUID: %s\n-", subobj.DOMAINGUID);
|
||||
} else {
|
||||
subobj.DOMAINGUID_MOD = "";
|
||||
}
|
||||
|
||||
if (subobj.HOSTGUID != undefined) {
|
||||
subobj.HOSTGUID_ADD = sprintf("objectGUID: %s", subobj.HOSTGUID);
|
||||
} else {
|
||||
subobj.HOSTGUID_ADD = "";
|
||||
}
|
||||
|
||||
info.subobj = subobj;
|
||||
info.message = message;
|
||||
info.credentials = credentials;
|
||||
info.session_info = session_info;
|
||||
|
||||
/* only install a new smb.conf if there isn't one there already */
|
||||
var st = sys.stat(paths.smbconf);
|
||||
if (st == undefined) {
|
||||
message("Setting up smb.conf\n");
|
||||
setup_file("provision.smb.conf", info.message, paths.smbconf, subobj);
|
||||
lp.reload();
|
||||
}
|
||||
/* only install a new shares config db if there is none */
|
||||
st = sys.stat(paths.shareconf);
|
||||
if (st == undefined) {
|
||||
message("Setting up share.ldb\n");
|
||||
setup_ldb("share.ldif", info, paths.shareconf);
|
||||
}
|
||||
message("Setting up secrets.ldb\n");
|
||||
setup_ldb("secrets.ldif", info, paths.secrets);
|
||||
message("Setting up keytabs\n");
|
||||
var keytab_ok = credentials_update_all_keytabs();
|
||||
assert(keytab_ok);
|
||||
message("Setting up hklm.ldb\n");
|
||||
setup_ldb("hklm.ldif", info, paths.hklm);
|
||||
|
||||
message("Setting up sam.ldb partitions\n");
|
||||
/* Also wipes the database */
|
||||
setup_ldb("provision_partitions.ldif", info, paths.samdb);
|
||||
|
||||
var samdb = open_ldb(info, paths.samdb, false);
|
||||
|
||||
message("Setting up sam.ldb attributes\n");
|
||||
setup_add_ldif("provision_init.ldif", info, samdb, false);
|
||||
message("Erasing data from partitions\n");
|
||||
ldb_erase_partitions(info, samdb);
|
||||
|
||||
message("Adding baseDN: " + subobj.BASEDN + " (permitted to fail)\n");
|
||||
var add_ok = setup_add_ldif("provision_basedn.ldif", info, samdb, true);
|
||||
message("Modifying baseDN: " + subobj.BASEDN + "\n");
|
||||
var modify_ok = setup_ldb_modify("provision_basedn_modify.ldif", info, samdb);
|
||||
if (!modify_ok) {
|
||||
if (!add_ok) {
|
||||
message("Failed to both add and modify " + subobj.BASEDN + " in target " + subobj.LDAPBACKEND + "\n");
|
||||
message("Perhaps you need to run the provision script with the --ldap-base-dn option, and add this record to the backend manually\n");
|
||||
};
|
||||
assert(modify_ok);
|
||||
};
|
||||
|
||||
message("Setting up sam.ldb Samba4 schema\n");
|
||||
setup_add_ldif("schema_samba4.ldif", info, samdb, false);
|
||||
message("Setting up sam.ldb AD schema\n");
|
||||
setup_add_ldif("schema.ldif", info, samdb, false);
|
||||
|
||||
// (hack) Reload, now we have the schema loaded.
|
||||
var commit_ok = samdb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("samdb commit failed: " + samdb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
samdb.close();
|
||||
|
||||
samdb = open_ldb(info, paths.samdb, false);
|
||||
|
||||
message("Setting up display specifiers\n");
|
||||
setup_add_ldif("display_specifiers.ldif", info, samdb, false);
|
||||
message("Setting up sam.ldb templates\n");
|
||||
setup_add_ldif("provision_templates.ldif", info, samdb, false);
|
||||
message("Setting up sam.ldb data\n");
|
||||
setup_add_ldif("provision.ldif", info, samdb, false);
|
||||
|
||||
if (blank != false) {
|
||||
message("Setting up sam.ldb index\n");
|
||||
setup_add_ldif("provision_index.ldif", info, samdb, false);
|
||||
|
||||
var commit_ok = samdb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("ldb commit failed: " + samdb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// message("Activate schema module");
|
||||
// setup_modify_ldif("schema_activation.ldif", info, samdb, false);
|
||||
//
|
||||
// // (hack) Reload, now we have the schema loaded.
|
||||
// var commit_ok = samdb.transaction_commit();
|
||||
// if (!commit_ok) {
|
||||
// info.message("samdb commit failed: " + samdb.errstring() + "\n");
|
||||
// assert(commit_ok);
|
||||
// }
|
||||
// samdb.close();
|
||||
//
|
||||
// samdb = open_ldb(info, paths.samdb, false);
|
||||
//
|
||||
message("Setting up sam.ldb users and groups\n");
|
||||
setup_add_ldif("provision_users.ldif", info, samdb, false);
|
||||
|
||||
if (setup_name_mappings(info, samdb) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
message("Setting up sam.ldb index\n");
|
||||
setup_add_ldif("provision_index.ldif", info, samdb, false);
|
||||
|
||||
var commit_ok = samdb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("samdb commit failed: " + samdb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Write out a DNS zone file, from the info in the current database */
|
||||
function provision_dns(subobj, message, paths, session_info, credentials)
|
||||
{
|
||||
message("Setting up DNS zone: " + subobj.DNSDOMAIN + " \n");
|
||||
var ldb = ldb_init();
|
||||
ldb.session_info = session_info;
|
||||
ldb.credentials = credentials;
|
||||
|
||||
/* connect to the sam */
|
||||
var ok = ldb.connect(paths.samdb);
|
||||
assert(ok);
|
||||
|
||||
/* These values may have changed, due to an incoming SamSync,
|
||||
or may not have been specified, so fetch them from the database */
|
||||
|
||||
var attrs = new Array("objectGUID");
|
||||
res = ldb.search("objectGUID=*", subobj.BASEDN, ldb.SCOPE_BASE, attrs);
|
||||
assert(res.length == 1);
|
||||
assert(res[0].objectGUID != undefined);
|
||||
subobj.DOMAINGUID = res[0].objectGUID;
|
||||
|
||||
subobj.HOSTGUID = searchone(ldb, subobj.BASEDN, "(&(objectClass=computer)(cn=" + subobj.NETBIOSNAME + "))", "objectGUID");
|
||||
assert(subobj.HOSTGUID != undefined);
|
||||
|
||||
setup_file("provision.zone",
|
||||
message, paths.dns,
|
||||
subobj);
|
||||
|
||||
message("Please install the zone located in " + paths.dns + " into your DNS server\n");
|
||||
}
|
||||
|
||||
/* Write out a DNS zone file, from the info in the current database */
|
||||
function provision_ldapbase(subobj, message, paths)
|
||||
{
|
||||
message("Setting up LDAP base entry: " + subobj.BASEDN + " \n");
|
||||
var rdns = split(",", subobj.BASEDN);
|
||||
subobj.EXTENSIBLEOBJECT = "objectClass: extensibleObject";
|
||||
|
||||
subobj.RDN_DC = substr(rdns[0], strlen("DC="));
|
||||
|
||||
setup_file("provision_basedn.ldif",
|
||||
message, paths.ldap_basedn_ldif,
|
||||
subobj);
|
||||
|
||||
message("Please install the LDIF located in " + paths.ldap_basedn_ldif + " into your LDAP server, and re-run with --ldap-backend=ldap://my.ldap.server\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
guess reasonably default options for provisioning
|
||||
*/
|
||||
function provision_guess()
|
||||
{
|
||||
var subobj = new Object();
|
||||
var nss = nss_init();
|
||||
var lp = loadparm_init();
|
||||
var rdn_list;
|
||||
random_init(local);
|
||||
|
||||
subobj.REALM = strupper(lp.get("realm"));
|
||||
subobj.DOMAIN = lp.get("workgroup");
|
||||
subobj.HOSTNAME = hostname();
|
||||
|
||||
assert(subobj.REALM);
|
||||
assert(subobj.DOMAIN);
|
||||
assert(subobj.HOSTNAME);
|
||||
|
||||
subobj.VERSION = version();
|
||||
subobj.HOSTIP = hostip();
|
||||
subobj.DOMAINSID = randsid();
|
||||
subobj.INVOCATIONID = randguid();
|
||||
subobj.KRBTGTPASS = randpass(12);
|
||||
subobj.MACHINEPASS = randpass(12);
|
||||
subobj.ADMINPASS = randpass(12);
|
||||
subobj.DEFAULTSITE = "Default-First-Site-Name";
|
||||
subobj.NEWGUID = randguid;
|
||||
subobj.NTTIME = nttime;
|
||||
subobj.LDAPTIME = ldaptime;
|
||||
subobj.DATESTRING = datestring;
|
||||
subobj.ROOT = findnss(nss.getpwnam, "root");
|
||||
subobj.NOBODY = findnss(nss.getpwnam, "nobody");
|
||||
subobj.NOGROUP = findnss(nss.getgrnam, "nogroup", "nobody");
|
||||
subobj.WHEEL = findnss(nss.getgrnam, "wheel", "root", "staff", "adm");
|
||||
subobj.BACKUP = findnss(nss.getgrnam, "backup", "wheel", "root", "staff");
|
||||
subobj.USERS = findnss(nss.getgrnam, "users", "guest", "other", "unknown", "usr");
|
||||
subobj.DNSDOMAIN = strlower(subobj.REALM);
|
||||
subobj.DNSNAME = sprintf("%s.%s",
|
||||
strlower(subobj.HOSTNAME),
|
||||
subobj.DNSDOMAIN);
|
||||
rdn_list = split(".", subobj.DNSDOMAIN);
|
||||
subobj.BASEDN = "DC=" + join(",DC=", rdn_list);
|
||||
subobj.LDAPBACKEND = "users.ldb";
|
||||
subobj.LDAPMODULES = "objectguid";
|
||||
subobj.EXTENSIBLEOBJECT = "# no objectClass: extensibleObject for local ldb";
|
||||
return subobj;
|
||||
}
|
||||
|
||||
/*
|
||||
search for one attribute as a string
|
||||
*/
|
||||
function searchone(ldb, basedn, expression, attribute)
|
||||
{
|
||||
var attrs = new Array(attribute);
|
||||
res = ldb.search(expression, basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (res.length != 1 ||
|
||||
res[0][attribute] == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return res[0][attribute];
|
||||
}
|
||||
|
||||
/*
|
||||
modify an account to remove the
|
||||
*/
|
||||
function enable_account(ldb, user_dn)
|
||||
{
|
||||
var attrs = new Array("userAccountControl");
|
||||
var res = ldb.search(NULL, user_dn, ldb.SCOPE_ONELEVEL, attrs);
|
||||
assert(res.length == 1);
|
||||
var userAccountControl = res[0].userAccountControl;
|
||||
userAccountControl = userAccountControl - 2; /* remove disabled bit */
|
||||
var mod = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: userAccountControl
|
||||
userAccountControl: %u
|
||||
",
|
||||
user_dn, userAccountControl);
|
||||
var ok = ldb.modify(mod);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
add a new user record
|
||||
*/
|
||||
function newuser(username, unixname, password, message, session_info, credentials)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var samdb = lp.get("sam database");
|
||||
var ldb = ldb_init();
|
||||
random_init(local);
|
||||
ldb.session_info = session_info;
|
||||
ldb.credentials = credentials;
|
||||
|
||||
/* connect to the sam */
|
||||
var ok = ldb.connect(samdb);
|
||||
assert(ok);
|
||||
|
||||
ldb.transaction_start();
|
||||
|
||||
/* find the DNs for the domain and the domain users group */
|
||||
var attrs = new Array("defaultNamingContext");
|
||||
res = ldb.search("defaultNamingContext=*", "", ldb.SCOPE_BASE, attrs);
|
||||
assert(res.length == 1 && res[0].defaultNamingContext != undefined);
|
||||
var domain_dn = res[0].defaultNamingContext;
|
||||
assert(domain_dn != undefined);
|
||||
var dom_users = searchone(ldb, domain_dn, "name=Domain Users", "dn");
|
||||
assert(dom_users != undefined);
|
||||
|
||||
var user_dn = sprintf("CN=%s,CN=Users,%s", username, domain_dn);
|
||||
|
||||
|
||||
/*
|
||||
the new user record. note the reliance on the samdb module to fill
|
||||
in a sid, guid etc
|
||||
*/
|
||||
var ldif = sprintf("
|
||||
dn: %s
|
||||
sAMAccountName: %s
|
||||
memberOf: %s
|
||||
unixName: %s
|
||||
sambaPassword: %s
|
||||
objectClass: user
|
||||
",
|
||||
user_dn, username, dom_users,
|
||||
unixname, password);
|
||||
/*
|
||||
add the user to the users group as well
|
||||
*/
|
||||
var modgroup = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
add: member
|
||||
member: %s
|
||||
",
|
||||
dom_users, user_dn);
|
||||
|
||||
|
||||
/*
|
||||
now the real work
|
||||
*/
|
||||
message("Adding user %s\n", user_dn);
|
||||
ok = ldb.add(ldif);
|
||||
if (ok != true) {
|
||||
message("Failed to add %s - %s\n", user_dn, ldb.errstring());
|
||||
return false;
|
||||
}
|
||||
|
||||
message("Modifying group %s\n", dom_users);
|
||||
ok = ldb.modify(modgroup);
|
||||
if (ok != true) {
|
||||
message("Failed to modify %s - %s\n", dom_users, ldb.errstring());
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
modify the userAccountControl to remove the disabled bit
|
||||
*/
|
||||
ok = enable_account(ldb, user_dn);
|
||||
if (ok) {
|
||||
ldb.transaction_commit();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Check whether a name is valid as a NetBIOS name.
|
||||
// FIXME: There are probably more constraints here.
|
||||
// crh has a paragraph on this in his book (1.4.1.1)
|
||||
function valid_netbios_name(name)
|
||||
{
|
||||
if (strlen(name) > 13) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function provision_validate(subobj, message)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
|
||||
if (!valid_netbios_name(subobj.DOMAIN)) {
|
||||
message("Invalid NetBIOS name for domain\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!valid_netbios_name(subobj.NETBIOSNAME)) {
|
||||
message("Invalid NetBIOS name for host\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (strupper(lp.get("workgroup")) != strupper(subobj.DOMAIN)) {
|
||||
message("workgroup '%s' in smb.conf must match chosen domain '%s'\n",
|
||||
lp.get("workgroup"), subobj.DOMAIN);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strupper(lp.get("realm")) != strupper(subobj.REALM)) {
|
||||
message("realm '%s' in smb.conf must match chosen realm '%s'\n",
|
||||
lp.get("realm"), subobj.REALM);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function join_domain(domain, netbios_name, join_type, creds, message)
|
||||
{
|
||||
var ctx = NetContext(creds);
|
||||
var joindom = new Object();
|
||||
joindom.domain = domain;
|
||||
joindom.join_type = join_type;
|
||||
joindom.netbios_name = netbios_name;
|
||||
if (!ctx.JoinDomain(joindom)) {
|
||||
message("Domain Join failed: " + joindom.error_string);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Vampire a remote domain. Session info and credentials are required for for
|
||||
* access to our local database (might be remote ldap)
|
||||
*/
|
||||
|
||||
function vampire(domain, session_info, credentials, message) {
|
||||
var ctx = NetContext(credentials);
|
||||
var vampire_ctx = new Object();
|
||||
var machine_creds = credentials_init();
|
||||
machine_creds.set_domain(form.DOMAIN);
|
||||
if (!machine_creds.set_machine_account()) {
|
||||
message("Failed to access domain join information!");
|
||||
return false;
|
||||
}
|
||||
vampire_ctx.machine_creds = machine_creds;
|
||||
vampire_ctx.session_info = session_info;
|
||||
if (!ctx.SamSyncLdb(vampire_ctx)) {
|
||||
message("Migration of remote domain to Samba failed: " + vampire_ctx.error_string);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
samr rpc utility functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
if (global["HAVE_SAMR_JS"] != undefined) {
|
||||
return;
|
||||
}
|
||||
HAVE_SAMR_JS=1
|
||||
|
||||
/*
|
||||
return a list of names and indexes from a samArray
|
||||
*/
|
||||
function samArray(output)
|
||||
{
|
||||
var list = new Array(output.num_entries);
|
||||
if (output.sam == NULL) {
|
||||
return list;
|
||||
}
|
||||
var i, entries = output.sam.entries;
|
||||
for (i=0;i<output.num_entries;i++) {
|
||||
list[i] = new Object();
|
||||
list[i].name = entries[i].name;
|
||||
list[i].idx = entries[i].idx;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
connect to the sam database
|
||||
*/
|
||||
function samrConnect(conn)
|
||||
{
|
||||
security_init(conn);
|
||||
var io = irpcObj();
|
||||
io.input.system_name = NULL;
|
||||
io.input.access_mask = conn.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
var status = conn.samr_Connect2(io);
|
||||
check_status_ok(status);
|
||||
return io.output.connect_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
close a handle
|
||||
*/
|
||||
function samrClose(conn, handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
var status = conn.samr_Close(io);
|
||||
check_status_ok(status);
|
||||
}
|
||||
|
||||
/*
|
||||
get the sid for a domain
|
||||
*/
|
||||
function samrLookupDomain(conn, handle, domain)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.connect_handle = handle;
|
||||
io.input.domain_name = domain;
|
||||
var status = conn.samr_LookupDomain(io);
|
||||
check_status_ok(status);
|
||||
return io.output.sid;
|
||||
}
|
||||
|
||||
/*
|
||||
open a domain by sid
|
||||
*/
|
||||
function samrOpenDomain(conn, handle, sid)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.connect_handle = handle;
|
||||
io.input.access_mask = conn.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.input.sid = sid;
|
||||
var status = conn.samr_OpenDomain(io);
|
||||
check_status_ok(status);
|
||||
return io.output.domain_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
open a user by rid
|
||||
*/
|
||||
function samrOpenUser(conn, handle, rid)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.domain_handle = handle;
|
||||
io.input.access_mask = conn.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.input.rid = rid;
|
||||
var status = conn.samr_OpenUser(io);
|
||||
check_status_ok(status);
|
||||
return io.output.user_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of all users
|
||||
*/
|
||||
function samrEnumDomainUsers(conn, dom_handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.domain_handle = dom_handle;
|
||||
io.input.resume_handle = 0;
|
||||
io.input.acct_flags = 0;
|
||||
io.input.max_size = -1;
|
||||
var status = conn.samr_EnumDomainUsers(io);
|
||||
check_status_ok(status);
|
||||
return samArray(io.output);
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of all groups
|
||||
*/
|
||||
function samrEnumDomainGroups(conn, dom_handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.domain_handle = dom_handle;
|
||||
io.input.resume_handle = 0;
|
||||
io.input.acct_flags = 0;
|
||||
io.input.max_size = -1;
|
||||
var status = conn.samr_EnumDomainGroups(io);
|
||||
check_status_ok(status);
|
||||
return samArray(io.output);
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of domains
|
||||
*/
|
||||
function samrEnumDomains(conn, handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.connect_handle = handle;
|
||||
io.input.resume_handle = 0;
|
||||
io.input.buf_size = -1;
|
||||
var status = conn.samr_EnumDomains(io);
|
||||
check_status_ok(status);
|
||||
return samArray(io.output);
|
||||
}
|
||||
|
||||
/*
|
||||
return information about a user
|
||||
*/
|
||||
function samrQueryUserInfo(conn, user_handle, level)
|
||||
{
|
||||
var r, io = irpcObj();
|
||||
io.input.user_handle = user_handle;
|
||||
io.input.level = level;
|
||||
var status = conn.samr_QueryUserInfo(io);
|
||||
check_status_ok(status);
|
||||
return io.output.info.info3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
fill a user array with user information from samrQueryUserInfo
|
||||
*/
|
||||
function samrFillUserInfo(conn, dom_handle, users, level)
|
||||
{
|
||||
var i;
|
||||
for (i=0;i<users.length;i++) {
|
||||
var r, user_handle, info;
|
||||
user_handle = samrOpenUser(conn, dom_handle, users[i].idx);
|
||||
info = samrQueryUserInfo(conn, user_handle, level);
|
||||
info.name = users[i].name;
|
||||
info.idx = users[i].idx;
|
||||
users[i] = info;
|
||||
samrClose(conn, user_handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
server side js functions for handling async calls from js clients
|
||||
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL Version 2 or later
|
||||
*/
|
||||
|
||||
libinclude("encoder.js");
|
||||
|
||||
/*
|
||||
register a new call
|
||||
*/
|
||||
function __register_call(name, func)
|
||||
{
|
||||
var c = this;
|
||||
c.calls[name] = func;
|
||||
}
|
||||
|
||||
/*
|
||||
run a call sent from the client, and output the returned object (if any)
|
||||
*/
|
||||
function __run_call() {
|
||||
var c = this;
|
||||
var name = form['ajaj_func'];
|
||||
if (name == undefined) {
|
||||
/* no function to run */
|
||||
return;
|
||||
}
|
||||
var args = form['ajaj_args'];
|
||||
if (args == undefined) {
|
||||
println("no function arguments given in run_call");
|
||||
exit(0);
|
||||
}
|
||||
args = decodeObject(args);
|
||||
if (c.calls[name] == undefined) {
|
||||
println("undefined remote call " + name);
|
||||
exit(0);
|
||||
}
|
||||
var f = c.calls[name];
|
||||
var res;
|
||||
/* oh what a hack - should write a varargs ejs helper */
|
||||
if (args.length == 0) {
|
||||
res = f();
|
||||
} else if (args.length == 1) {
|
||||
res = f(args[0]);
|
||||
} else if (args.length == 2) {
|
||||
res = f(args[0], args[1]);
|
||||
} else if (args.length == 3) {
|
||||
res = f(args[0], args[1], args[2]);
|
||||
} else if (args.length == 4) {
|
||||
res = f(args[0], args[1], args[2], args[3]);
|
||||
} else if (args.length == 5) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4]);
|
||||
} else if (args.length == 6) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
} else if (args.length == 7) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
||||
} else if (args.length == 8) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||
} else {
|
||||
println("too many arguments for remote call: " + name);
|
||||
exit(0);
|
||||
}
|
||||
var repobj = new Object();
|
||||
repobj.res = res;
|
||||
write(encodeObject(repobj));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
initialise a server call object
|
||||
*/
|
||||
function servCallObj()
|
||||
{
|
||||
var c = new Object();
|
||||
c.add = __register_call;
|
||||
c.run = __run_call;
|
||||
c.calls = new Object();
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,674 @@
|
||||
/*
|
||||
backend code for upgrading from Samba3
|
||||
Copyright Jelmer Vernooij 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
libinclude("base.js");
|
||||
|
||||
function regkey_to_dn(name)
|
||||
{
|
||||
var dn = "hive=NONE";
|
||||
var i = 0;
|
||||
|
||||
var as = split("/", name);
|
||||
|
||||
for (i in as) {
|
||||
if (i > 0) {
|
||||
dn = sprintf("key=%s,", as[i]) + dn;
|
||||
}
|
||||
}
|
||||
|
||||
return dn;
|
||||
}
|
||||
|
||||
/* Where prefix is any of:
|
||||
* - HKLM
|
||||
* HKU
|
||||
* HKCR
|
||||
* HKPD
|
||||
* HKPT
|
||||
*/
|
||||
|
||||
function upgrade_registry(regdb,prefix,ldb)
|
||||
{
|
||||
assert(regdb != undefined);
|
||||
var prefix_up = strupper(prefix);
|
||||
var ldif = new Array();
|
||||
|
||||
for (var i in regdb.keys) {
|
||||
var rk = regdb.keys[i];
|
||||
var pts = split("/", rk.name);
|
||||
|
||||
/* Only handle selected hive */
|
||||
if (strupper(pts[0]) != prefix_up) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var keydn = regkey_to_dn(rk.name);
|
||||
|
||||
var pts = split("/", rk.name);
|
||||
|
||||
/* Convert key name to dn */
|
||||
ldif[rk.name] = sprintf("
|
||||
dn: %s
|
||||
name: %s
|
||||
|
||||
", keydn, pts[0]);
|
||||
|
||||
for (var j in rk.values) {
|
||||
var rv = rk.values[j];
|
||||
|
||||
ldif[rk.name + " (" + rv.name + ")"] = sprintf("
|
||||
dn: %s,value=%s
|
||||
value: %s
|
||||
type: %d
|
||||
data:: %s", keydn, rv.name, rv.name, rv.type, ldb.encode(rv.data));
|
||||
}
|
||||
}
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_sam_policy(samba3,dn)
|
||||
{
|
||||
var ldif = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: minPwdLength
|
||||
minPwdLength: %d
|
||||
pwdHistoryLength: %d
|
||||
minPwdAge: %d
|
||||
maxPwdAge: %d
|
||||
lockoutDuration: %d
|
||||
samba3ResetCountMinutes: %d
|
||||
samba3UserMustLogonToChangePassword: %d
|
||||
samba3BadLockoutMinutes: %d
|
||||
samba3DisconnectTime: %d
|
||||
|
||||
", dn, samba3.policy.min_password_length,
|
||||
samba3.policy.password_history, samba3.policy.minimum_password_age,
|
||||
samba3.policy.maximum_password_age, samba3.policy.lockout_duration,
|
||||
samba3.policy.reset_count_minutes, samba3.policy.user_must_logon_to_change_password,
|
||||
samba3.policy.bad_lockout_minutes, samba3.policy.disconnect_time
|
||||
);
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_sam_account(ldb,acc,domaindn,domainsid)
|
||||
{
|
||||
if (acc.nt_username == undefined) {
|
||||
acc.nt_username = acc.username;
|
||||
}
|
||||
|
||||
if (acc.nt_username == "") {
|
||||
acc.nt_username = acc.username;
|
||||
}
|
||||
|
||||
if (acc.fullname == undefined) {
|
||||
var pw = nss.getpwnam(acc.fullname);
|
||||
acc.fullname = pw.pw_gecos;
|
||||
}
|
||||
|
||||
var pts = split(',', acc.fullname);
|
||||
acc.fullname = pts[0];
|
||||
|
||||
if (acc.fullname == undefined) {
|
||||
acc.fullname = acc.username;
|
||||
}
|
||||
|
||||
assert(acc.fullname != undefined);
|
||||
assert(acc.nt_username != undefined);
|
||||
|
||||
var ldif = sprintf(
|
||||
"dn: cn=%s,%s
|
||||
objectClass: top
|
||||
objectClass: user
|
||||
lastLogon: %d
|
||||
lastLogoff: %d
|
||||
unixName: %s
|
||||
sAMAccountName: %s
|
||||
cn: %s
|
||||
description: %s
|
||||
primaryGroupID: %d
|
||||
badPwdcount: %d
|
||||
logonCount: %d
|
||||
samba3Domain: %s
|
||||
samba3DirDrive: %s
|
||||
samba3MungedDial: %s
|
||||
samba3Homedir: %s
|
||||
samba3LogonScript: %s
|
||||
samba3ProfilePath: %s
|
||||
samba3Workstations: %s
|
||||
samba3KickOffTime: %d
|
||||
samba3BadPwdTime: %d
|
||||
samba3PassLastSetTime: %d
|
||||
samba3PassCanChangeTime: %d
|
||||
samba3PassMustChangeTime: %d
|
||||
objectSid: %s-%d
|
||||
lmPwdHash:: %s
|
||||
ntPwdHash:: %s
|
||||
|
||||
", ldb.dn_escape(acc.fullname), domaindn, acc.logon_time, acc.logoff_time, acc.username, acc.nt_username, acc.nt_username,
|
||||
|
||||
acc.acct_desc, acc.group_rid, acc.bad_password_count, acc.logon_count,
|
||||
acc.domain, acc.dir_drive, acc.munged_dial, acc.homedir, acc.logon_script,
|
||||
acc.profile_path, acc.workstations, acc.kickoff_time, acc.bad_password_time,
|
||||
acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, domainsid, acc.user_rid,
|
||||
ldb.encode(acc.lm_pw), ldb.encode(acc.nt_pw));
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_sam_group(grp,domaindn)
|
||||
{
|
||||
var nss = nss_init();
|
||||
|
||||
var gr;
|
||||
if (grp.sid_name_use == 5) { // Well-known group
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (grp.nt_name == "Domain Guests" ||
|
||||
grp.nt_name == "Domain Users" ||
|
||||
grp.nt_name == "Domain Admins") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (grp.gid == -1) {
|
||||
gr = nss.getgrnam(grp.nt_name);
|
||||
} else {
|
||||
gr = nss.getgrgid(grp.gid);
|
||||
}
|
||||
|
||||
if (gr == undefined) {
|
||||
grp.unixname = "UNKNOWN";
|
||||
} else {
|
||||
grp.unixname = gr.gr_name;
|
||||
}
|
||||
|
||||
assert(grp.unixname != undefined);
|
||||
|
||||
var ldif = sprintf(
|
||||
"dn: cn=%s,%s
|
||||
objectClass: top
|
||||
objectClass: group
|
||||
description: %s
|
||||
cn: %s
|
||||
objectSid: %s
|
||||
unixName: %s
|
||||
samba3SidNameUse: %d
|
||||
", grp.nt_name, domaindn,
|
||||
grp.comment, grp.nt_name, grp.sid, grp.unixname, grp.sid_name_use);
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_winbind(samba3,domaindn)
|
||||
{
|
||||
var ldif = sprintf("
|
||||
|
||||
dn: dc=none
|
||||
userHwm: %d
|
||||
groupHwm: %d
|
||||
|
||||
", samba3.idmap.user_hwm, samba3.idmap.group_hwm);
|
||||
|
||||
for (var i in samba3.idmap.mappings) {
|
||||
var m = samba3.idmap.mappings[i];
|
||||
ldif = ldif + sprintf("
|
||||
dn: SID=%s,%s
|
||||
SID: %s
|
||||
type: %d
|
||||
unixID: %d", m.sid, domaindn, m.sid, m.type, m.unix_id);
|
||||
}
|
||||
|
||||
return ldif;
|
||||
}
|
||||
*/
|
||||
|
||||
function upgrade_wins(samba3)
|
||||
{
|
||||
var ldif = "";
|
||||
var version_id = 0;
|
||||
|
||||
for (i in samba3.winsentries) {
|
||||
var rType;
|
||||
var rState;
|
||||
var nType;
|
||||
var numIPs = 0;
|
||||
var e = samba3.winsentries[i];
|
||||
var now = sys.nttime();
|
||||
var ttl = sys.unix2nttime(e.ttl);
|
||||
|
||||
version_id++;
|
||||
|
||||
for (var i in e.ips) {
|
||||
numIPs++;
|
||||
}
|
||||
|
||||
if (e.type == 0x1C) {
|
||||
rType = 0x2;
|
||||
} else if (sys.bitAND(e.type, 0x80)) {
|
||||
if (numIPs > 1) {
|
||||
rType = 0x2;
|
||||
} else {
|
||||
rType = 0x1;
|
||||
}
|
||||
} else {
|
||||
if (numIPs > 1) {
|
||||
rType = 0x3;
|
||||
} else {
|
||||
rType = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ttl > now) {
|
||||
rState = 0x0;/* active */
|
||||
} else {
|
||||
rState = 0x1;/* released */
|
||||
}
|
||||
|
||||
nType = (sys.bitAND(e.nb_flags,0x60)>>5);
|
||||
|
||||
ldif = ldif + sprintf("
|
||||
dn: name=%s,type=0x%02X
|
||||
type: 0x%02X
|
||||
name: %s
|
||||
objectClass: winsRecord
|
||||
recordType: %u
|
||||
recordState: %u
|
||||
nodeType: %u
|
||||
isStatic: 0
|
||||
expireTime: %s
|
||||
versionID: %llu
|
||||
", e.name, e.type, e.type, e.name,
|
||||
rType, rState, nType,
|
||||
sys.ldaptime(ttl), version_id);
|
||||
|
||||
for (var i in e.ips) {
|
||||
ldif = ldif + sprintf("address: %s\n", e.ips[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ldif = ldif + sprintf("
|
||||
dn: CN=VERSION
|
||||
objectClass: winsMaxVersion
|
||||
maxVersion: %llu
|
||||
", version_id);
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_provision(samba3)
|
||||
{
|
||||
var subobj = new Object();
|
||||
var nss = nss_init();
|
||||
var lp = loadparm_init();
|
||||
var rdn_list;
|
||||
|
||||
var domainname = samba3.configuration.get("workgroup");
|
||||
|
||||
if (domainname == undefined) {
|
||||
domainname = samba3.secrets.domains[0].name;
|
||||
println("No domain specified in smb.conf file, assuming '" + domainname + "'");
|
||||
}
|
||||
|
||||
var domsec = samba3.find_domainsecrets(domainname);
|
||||
var hostsec = samba3.find_domainsecrets(hostname());
|
||||
var realm = samba3.configuration.get("realm");
|
||||
|
||||
if (realm == undefined) {
|
||||
realm = domainname;
|
||||
println("No realm specified in smb.conf file, assuming '" + realm + "'");
|
||||
}
|
||||
random_init(local);
|
||||
|
||||
subobj.REALM = realm;
|
||||
subobj.DOMAIN = domainname;
|
||||
subobj.HOSTNAME = hostname();
|
||||
|
||||
assert(subobj.REALM);
|
||||
assert(subobj.DOMAIN);
|
||||
assert(subobj.HOSTNAME);
|
||||
|
||||
subobj.HOSTIP = hostip();
|
||||
if (domsec != undefined) {
|
||||
subobj.DOMAINGUID = domsec.guid;
|
||||
subobj.DOMAINSID = domsec.sid;
|
||||
} else {
|
||||
println("Can't find domain secrets for '" + domainname + "'; using random SID and GUID");
|
||||
subobj.DOMAINGUID = randguid();
|
||||
subobj.DOMAINSID = randsid();
|
||||
}
|
||||
|
||||
if (hostsec) {
|
||||
subobj.HOSTGUID = hostsec.guid;
|
||||
} else {
|
||||
subobj.HOSTGUID = randguid();
|
||||
}
|
||||
subobj.INVOCATIONID = randguid();
|
||||
subobj.KRBTGTPASS = randpass(12);
|
||||
subobj.MACHINEPASS = randpass(12);
|
||||
subobj.ADMINPASS = randpass(12);
|
||||
subobj.DEFAULTSITE = "Default-First-Site-Name";
|
||||
subobj.NEWGUID = randguid;
|
||||
subobj.NTTIME = nttime;
|
||||
subobj.LDAPTIME = ldaptime;
|
||||
subobj.DATESTRING = datestring;
|
||||
subobj.USN = nextusn;
|
||||
subobj.ROOT = findnss(nss.getpwnam, "root");
|
||||
subobj.NOBODY = findnss(nss.getpwnam, "nobody");
|
||||
subobj.NOGROUP = findnss(nss.getgrnam, "nogroup", "nobody");
|
||||
subobj.WHEEL = findnss(nss.getgrnam, "wheel", "root");
|
||||
subobj.USERS = findnss(nss.getgrnam, "users", "guest", "other");
|
||||
subobj.DNSDOMAIN = strlower(subobj.REALM);
|
||||
subobj.DNSNAME = sprintf("%s.%s",
|
||||
strlower(subobj.HOSTNAME),
|
||||
subobj.DNSDOMAIN);
|
||||
subobj.BASEDN = "DC=" + join(",DC=", split(".", subobj.REALM));
|
||||
rdn_list = split(".", subobj.REALM);
|
||||
return subobj;
|
||||
}
|
||||
|
||||
smbconf_keep = new Array(
|
||||
"dos charset",
|
||||
"unix charset",
|
||||
"display charset",
|
||||
"comment",
|
||||
"path",
|
||||
"directory",
|
||||
"workgroup",
|
||||
"realm",
|
||||
"netbios name",
|
||||
"netbios aliases",
|
||||
"netbios scope",
|
||||
"server string",
|
||||
"interfaces",
|
||||
"bind interfaces only",
|
||||
"security",
|
||||
"auth methods",
|
||||
"encrypt passwords",
|
||||
"null passwords",
|
||||
"obey pam restrictions",
|
||||
"password server",
|
||||
"smb passwd file",
|
||||
"private dir",
|
||||
"passwd chat",
|
||||
"password level",
|
||||
"lanman auth",
|
||||
"ntlm auth",
|
||||
"client NTLMv2 auth",
|
||||
"client lanman auth",
|
||||
"client plaintext auth",
|
||||
"read only",
|
||||
"hosts allow",
|
||||
"hosts deny",
|
||||
"log level",
|
||||
"debuglevel",
|
||||
"log file",
|
||||
"smb ports",
|
||||
"large readwrite",
|
||||
"max protocol",
|
||||
"min protocol",
|
||||
"unicode",
|
||||
"read raw",
|
||||
"write raw",
|
||||
"disable netbios",
|
||||
"nt status support",
|
||||
"announce version",
|
||||
"announce as",
|
||||
"max mux",
|
||||
"max xmit",
|
||||
"name resolve order",
|
||||
"max wins ttl",
|
||||
"min wins ttl",
|
||||
"time server",
|
||||
"unix extensions",
|
||||
"use spnego",
|
||||
"server signing",
|
||||
"client signing",
|
||||
"max connections",
|
||||
"paranoid server security",
|
||||
"socket options",
|
||||
"strict sync",
|
||||
"max print jobs",
|
||||
"printable",
|
||||
"print ok",
|
||||
"printer name",
|
||||
"printer",
|
||||
"map system",
|
||||
"map hidden",
|
||||
"map archive",
|
||||
"preferred master",
|
||||
"prefered master",
|
||||
"local master",
|
||||
"browseable",
|
||||
"browsable",
|
||||
"wins server",
|
||||
"wins support",
|
||||
"csc policy",
|
||||
"strict locking",
|
||||
"config file",
|
||||
"preload",
|
||||
"auto services",
|
||||
"lock dir",
|
||||
"lock directory",
|
||||
"pid directory",
|
||||
"socket address",
|
||||
"copy",
|
||||
"include",
|
||||
"available",
|
||||
"volume",
|
||||
"fstype",
|
||||
"panic action",
|
||||
"msdfs root",
|
||||
"host msdfs",
|
||||
"winbind separator");
|
||||
|
||||
/*
|
||||
Remove configuration variables not present in Samba4
|
||||
oldconf: Old configuration structure
|
||||
mark: Whether removed configuration variables should be
|
||||
kept in the new configuration as "samba3:<name>"
|
||||
*/
|
||||
function upgrade_smbconf(oldconf,mark)
|
||||
{
|
||||
var data = oldconf.data();
|
||||
var newconf = param_init();
|
||||
|
||||
for (var s in data) {
|
||||
for (var p in data[s]) {
|
||||
var keep = false;
|
||||
for (var k in smbconf_keep) {
|
||||
if (smbconf_keep[k] == p) {
|
||||
keep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keep) {
|
||||
newconf.set(s, p, oldconf.get(s, p));
|
||||
} else if (mark) {
|
||||
newconf.set(s, "samba3:"+p, oldconf.get(s,p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oldconf.get("domain logons") == "True") {
|
||||
if (oldconf.get("domain master") == "True") {
|
||||
newconf.set("server role", "pdc");
|
||||
} else {
|
||||
newconf.set("server role", "bdc");
|
||||
}
|
||||
} else {
|
||||
if (oldconf.get("domain master") == "True") {
|
||||
newconf.set("server role", "standalone");
|
||||
} else {
|
||||
newconf.set("server role", "member server");
|
||||
}
|
||||
}
|
||||
|
||||
return newconf;
|
||||
}
|
||||
|
||||
function upgrade(subobj, samba3, message, paths, session_info, credentials)
|
||||
{
|
||||
var ret = 0;
|
||||
var lp = loadparm_init();
|
||||
var samdb = ldb_init();
|
||||
samdb.session_info = session_info;
|
||||
samdb.credentials = credentials;
|
||||
var ok = samdb.connect(paths.samdb);
|
||||
if (!ok) {
|
||||
info.message("samdb connect failed: " + samdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
message("Writing configuration\n");
|
||||
var newconf = upgrade_smbconf(samba3.configuration,true);
|
||||
newconf.save(paths.smbconf);
|
||||
|
||||
message("Importing account policies\n");
|
||||
var ldif = upgrade_sam_policy(samba3,subobj.BASEDN);
|
||||
ok = samdb.modify(ldif);
|
||||
if (!ok) {
|
||||
message("samdb load failed: " + samdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
var regdb = ldb_init();
|
||||
ok = regdb.connect(paths.hklm);
|
||||
if (!ok) {
|
||||
message("registry connect: " + regdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
ok = regdb.modify(sprintf("
|
||||
dn: value=RefusePasswordChange,key=Parameters,key=Netlogon,key=Services,key=CurrentControlSet,key=System,HIVE=NONE
|
||||
replace: type
|
||||
type: 4
|
||||
replace: data
|
||||
data: %d
|
||||
", samba3.policy.refuse_machine_password_change));
|
||||
if (!ok) {
|
||||
message("registry load failed: " + regdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
message("Importing users\n");
|
||||
for (var i in samba3.samaccounts) {
|
||||
var msg = "... " + samba3.samaccounts[i].username;
|
||||
var ldif = upgrade_sam_account(samdb,samba3.samaccounts[i],subobj.BASEDN,subobj.DOMAINSID);
|
||||
ok = samdb.add(ldif);
|
||||
if (!ok && samdb.errstring() != "Record exists") {
|
||||
msg = msg + "... error: " + samdb.errstring();
|
||||
ret = ret + 1;
|
||||
}
|
||||
message(msg + "\n");
|
||||
}
|
||||
|
||||
message("Importing groups\n");
|
||||
for (var i in samba3.groupmappings) {
|
||||
var msg = "... " + samba3.groupmappings[i].nt_name;
|
||||
var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
|
||||
if (ldif != undefined) {
|
||||
ok = samdb.add(ldif);
|
||||
if (!ok && samdb.errstring() != "Record exists") {
|
||||
msg = msg + "... error: " + samdb.errstring();
|
||||
ret = ret + 1;
|
||||
}
|
||||
}
|
||||
message(msg + "\n");
|
||||
}
|
||||
|
||||
message("Importing registry data\n");
|
||||
var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt");
|
||||
for (var i in hives) {
|
||||
var hn = hives[i];
|
||||
message("... " + hn + "\n");
|
||||
regdb = ldb_init();
|
||||
ok = regdb.connect(paths[hn]);
|
||||
assert(ok);
|
||||
var ldif = upgrade_registry(samba3.registry, hn, regdb);
|
||||
for (var j in ldif) {
|
||||
var msg = "... ... " + j;
|
||||
ok = regdb.add(ldif[j]);
|
||||
if (!ok && regdb.errstring() != "Record exists") {
|
||||
msg = msg + "... error: " + regdb.errstring();
|
||||
ret = ret + 1;
|
||||
}
|
||||
message(msg + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message("Importing WINS data\n");
|
||||
var winsdb = ldb_init();
|
||||
ok = winsdb.connect(paths.winsdb);
|
||||
assert(ok);
|
||||
ldb_erase(winsdb);
|
||||
|
||||
var ldif = upgrade_wins(samba3);
|
||||
ok = winsdb.add(ldif);
|
||||
assert(ok);
|
||||
|
||||
// figure out ldapurl, if applicable
|
||||
var ldapurl = undefined;
|
||||
var pdb = samba3.configuration.get_list("passdb backend");
|
||||
if (pdb != undefined) {
|
||||
for (var b in pdb) {
|
||||
if (strlen(pdb[b]) >= 7) {
|
||||
if (substr(pdb[b], 0, 7) == "ldapsam") {
|
||||
ldapurl = substr(pdb[b], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// URL was not specified in passdb backend but ldap /is/ used
|
||||
if (ldapurl == "") {
|
||||
ldapurl = "ldap://" + samba3.configuration.get("ldap server");
|
||||
}
|
||||
|
||||
// Enable samba3sam module if original passdb backend was ldap
|
||||
if (ldapurl != undefined) {
|
||||
message("Enabling Samba3 LDAP mappings for SAM database\n");
|
||||
|
||||
ok = samdb.modify("
|
||||
dn: @MODULES
|
||||
changetype: modify
|
||||
replace: @LIST
|
||||
@LIST: samldb,operational,objectguid,rdn_name,samba3sam
|
||||
");
|
||||
if (!ok) {
|
||||
message("Error enabling samba3sam module: " + samdb.errstring() + "\n");
|
||||
ret = ret + 1;
|
||||
}
|
||||
|
||||
ok = samdb.add(sprintf("
|
||||
dn: @MAP=samba3sam
|
||||
@MAP_URL: %s", ldapurl));
|
||||
assert(ok);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function upgrade_verify(subobj, samba3,paths,message)
|
||||
{
|
||||
message("Verifying account policies\n");
|
||||
var samldb = ldb_init();
|
||||
var ne = 0;
|
||||
|
||||
var ok = samldb.connect(paths.samdb);
|
||||
assert(ok);
|
||||
|
||||
for (var i in samba3.samaccounts) {
|
||||
var msg = samldb.search("(&(sAMAccountName=" + samba3.samaccounts[i].nt_username + ")(objectclass=user))");
|
||||
assert(msg.length >= 1);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
winreg rpc utility functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
libinclude("base.js");
|
||||
|
||||
/*
|
||||
close a handle
|
||||
*/
|
||||
function __winreg_close(handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
this.winreg_CloseKey(io);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
open a hive
|
||||
*/
|
||||
function __winreg_open_hive(hive)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.system_name = NULL;
|
||||
io.input.access_mask = this.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
var status;
|
||||
if (hive == "HKLM") {
|
||||
status = this.winreg_OpenHKLM(io);
|
||||
} else if (hive == "HKCR") {
|
||||
status = this.winreg_OpenHKCR(io);
|
||||
} else if (hive == "HKPD") {
|
||||
status = this.winreg_OpenHKPD(io);
|
||||
} else if (hive == "HKU") {
|
||||
status = this.winreg_OpenHKU(io);
|
||||
} else {
|
||||
this._last_error = "Unknown hive " + hive;
|
||||
return undefined;
|
||||
}
|
||||
if (!status.is_ok) {
|
||||
return undefined;
|
||||
}
|
||||
return io.output.handle;
|
||||
}
|
||||
|
||||
/*
|
||||
open a handle to a path
|
||||
*/
|
||||
function __winreg_open_path(path)
|
||||
{
|
||||
var s = string_init();
|
||||
var i, components = s.split('\\', path);
|
||||
|
||||
/* cope with a leading slash */
|
||||
if (components[0] == '') {
|
||||
for (i=0;i<(components.length-1);i++) {
|
||||
components[i] = components[i+1];
|
||||
}
|
||||
delete(components[i]);
|
||||
}
|
||||
|
||||
if (components.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var handle = this.open_hive(components[0]);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (components.length == 1) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
var hpath = components[1];
|
||||
|
||||
for (i=2;i<components.length;i++) {
|
||||
hpath = hpath + "\\" + components[i];
|
||||
}
|
||||
|
||||
io = irpcObj();
|
||||
io.input.parent_handle = handle;
|
||||
io.input.keyname = hpath;
|
||||
io.input.unknown = 0;
|
||||
io.input.access_mask = this.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
var status = this.winreg_OpenKey(io);
|
||||
|
||||
this.close(handle);
|
||||
|
||||
if (!status.is_ok) {
|
||||
return undefined;
|
||||
}
|
||||
if (io.output.result != "WERR_OK") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return io.output.handle;
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of keys for a winreg server given a path
|
||||
usage:
|
||||
list = reg.enum_path(path);
|
||||
*/
|
||||
function __winreg_enum_path(path)
|
||||
{
|
||||
var list = new Array(0);
|
||||
|
||||
if (path == null || path == "\\" || path == "") {
|
||||
return new Array("HKLM", "HKU");
|
||||
}
|
||||
|
||||
var handle = this.open_path(path);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
io.input.name = new Object();
|
||||
io.input.name.length = 0;
|
||||
io.input.name.size = 32;
|
||||
io.input.name.name = NULL;
|
||||
io.input.keyclass = new Object();
|
||||
io.input.keyclass.length = 0;
|
||||
io.input.keyclass.size = 1024;
|
||||
io.input.keyclass.name = NULL;
|
||||
io.input.last_changed_time = 0;
|
||||
|
||||
var idx = 0;
|
||||
for (idx=0;idx >= 0;idx++) {
|
||||
io.input.enum_index = idx;
|
||||
var status = this.winreg_EnumKey(io);
|
||||
if (!status.is_ok) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
var out = io.output;
|
||||
if (out.result == "WERR_MORE_DATA") {
|
||||
io.input.name.size = io.input.name.size * 2;
|
||||
idx--;
|
||||
if (io.input.name.size > 32000) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (out.result != "WERR_OK") {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
list[list.length] = out.name.name;
|
||||
}
|
||||
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return a list of values for a winreg server given a path
|
||||
usage:
|
||||
list = reg.enum_values(path);
|
||||
|
||||
each returned list element is an object containing a name, a
|
||||
type and a value
|
||||
*/
|
||||
function __winreg_enum_values(path)
|
||||
{
|
||||
var data = datablob_init();
|
||||
var list = new Array(0);
|
||||
|
||||
var handle = this.open_path(path);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
io.input.name = new Object();
|
||||
io.input.name.length = 0;
|
||||
io.input.name.size = 128;
|
||||
io.input.name.name = "";
|
||||
io.input.type = 0;
|
||||
io.input.value = new Array(0);
|
||||
io.input.size = 1024;
|
||||
io.input.length = 0;
|
||||
|
||||
var idx;
|
||||
for (idx=0;idx >= 0;idx++) {
|
||||
io.input.enum_index = idx;
|
||||
var status = this.winreg_EnumValue(io);
|
||||
if (!status.is_ok) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
var out = io.output;
|
||||
if (out.result == "WERR_MORE_DATA") {
|
||||
io.input.size = io.input.size * 2;
|
||||
io.input.name.size = io.input.name.size * 2;
|
||||
idx--;
|
||||
/* limit blobs to 1M */
|
||||
if (io.input.size > 1000000) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (out.result != "WERR_OK") {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
var el = new Object();
|
||||
el.name = out.name.name;
|
||||
el.type = out.type;
|
||||
el.rawvalue = out.value;
|
||||
el.value = data.regToVar(el.rawvalue, el.type);
|
||||
el.size = out.size;
|
||||
list[list.length] = el;
|
||||
}
|
||||
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
create a new key
|
||||
ok = reg.create_key(path, key);
|
||||
*/
|
||||
function __winreg_create_key(path, key)
|
||||
{
|
||||
var handle = this.open_path(path);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
io.input.name = key;
|
||||
io.input.keyclass = NULL;
|
||||
io.input.options = 0;
|
||||
io.input.access_mask = this.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.input.secdesc = NULL;
|
||||
io.input.action_taken = 0;
|
||||
|
||||
var status = this.winreg_CreateKey(io);
|
||||
this.close(handle);
|
||||
if (!status.is_ok) {
|
||||
return false;
|
||||
}
|
||||
if (io.output.result != "WERR_OK") {
|
||||
return false;
|
||||
}
|
||||
this.close(io.output.new_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return a string for a winreg type
|
||||
*/
|
||||
function __winreg_typestring(type)
|
||||
{
|
||||
return this.typenames[type];
|
||||
}
|
||||
|
||||
/*
|
||||
initialise the winreg lib, returning an object
|
||||
*/
|
||||
function winregObj()
|
||||
{
|
||||
var reg = winreg_init();
|
||||
security_init(reg);
|
||||
|
||||
reg.typenames = new Array("REG_NONE", "REG_SZ", "REG_EXPAND_SZ", "REG_BINARY",
|
||||
"REG_DWORD", "REG_DWORD_BIG_ENDIAN", "REG_LINK", "REG_MULTI_SZ",
|
||||
"REG_RESOURCE_LIST", "REG_FULL_RESOURCE_DESCRIPTOR",
|
||||
"REG_RESOURCE_REQUIREMENTS_LIST", "REG_QWORD");
|
||||
|
||||
reg.close = __winreg_close;
|
||||
reg.open_hive = __winreg_open_hive;
|
||||
reg.open_path = __winreg_open_path;
|
||||
reg.enum_path = __winreg_enum_path;
|
||||
reg.enum_values = __winreg_enum_values;
|
||||
reg.create_key = __winreg_create_key;
|
||||
reg.typestring = __winreg_typestring;
|
||||
|
||||
return reg;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
README for Samba SWIG Python extensions
|
||||
---------------------------------------
|
||||
|
||||
Instructions for building:
|
||||
|
||||
1. Run configure with the --with-python option to enable python
|
||||
extensions.
|
||||
|
||||
2. Edit the script/build_idl.sh script to pass the --swig option to
|
||||
pidl. Here's a patch:
|
||||
|
||||
Index: script/build_idl.sh
|
||||
===================================================================
|
||||
--- script/build_idl.sh (revision 2413)
|
||||
+++ script/build_idl.sh (working copy)
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
[ -d librpc/gen_ndr ] || mkdir -p librpc/gen_ndr || exit 1
|
||||
|
||||
-PIDL="$PERL ./build/pidl/pidl.pl --output librpc/gen_ndr/ndr_ --parse --header --parser --server"
|
||||
+PIDL="$PERL ./build/pidl/pidl.pl --output librpc/gen_ndr/ndr_ --parse --header --parser --server --swig"
|
||||
TABLES="$PERL ./build/pidl/tables.pl --output librpc/gen_ndr/tables"
|
||||
|
||||
if [ x$FULLBUILD = xFULL ]; then
|
||||
|
||||
3. Run 'make idl_full swig' to build extensions.
|
||||
|
||||
4. At some stage there will be a proper system for installing the
|
||||
extensions, but right now it's easier to run them in place. Set
|
||||
your PYTHONPATH to include the modules. From the Samba source
|
||||
directory, run:
|
||||
|
||||
export PYTHONPATH=`pwd`/scripting/swig
|
||||
|
||||
Now you can go nuts and use the extensions. Check the
|
||||
scripting/swig/torture directory for a testsuite. There will
|
||||
hopefully be a bunch of usage examples somewhere.
|
||||
@@ -0,0 +1,29 @@
|
||||
dnl # Scripting subsystem
|
||||
|
||||
# Check for python support
|
||||
|
||||
PYTHON=
|
||||
|
||||
AC_ARG_WITH(python,
|
||||
[ --with-python=PYTHONNAME build Python libraries],
|
||||
[ case "${withval-python}" in
|
||||
yes)
|
||||
PYTHON=python
|
||||
;;
|
||||
no)
|
||||
PYTHON=
|
||||
;;
|
||||
*)
|
||||
PYTHON=${withval-python}
|
||||
;;
|
||||
esac ])
|
||||
|
||||
if test x"$PYTHON" != "x"; then
|
||||
incdir=`python -c 'import sys; print "%s/include/python%d.%d" % (sys.prefix, sys.version_info[[0]], sys.version_info[[1]])'`
|
||||
CPPFLAGS="$CPPFLAGS -I $incdir"
|
||||
else
|
||||
SMB_ENABLE(swig_dcerpc, NO)
|
||||
fi
|
||||
|
||||
AC_SUBST(PYTHON)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#######################
|
||||
# Start LIBRARY swig_dcerpc
|
||||
[LIBRARY::swig_dcerpc]
|
||||
LIBRARY_REALNAME = _dcerpc.$(SHLIBEXT)
|
||||
PUBLIC_DEPENDENCIES = LIBCLI_SMB NDR_MISC LIBSAMBA-UTIL LIBSAMBA-CONFIG RPC_NDR_SAMR RPC_NDR_LSA DYNCONFIG
|
||||
OBJ_FILES = dcerpc_wrap.o
|
||||
# End LIBRARY swig_dcerpc
|
||||
#######################
|
||||
|
||||
# Swig extensions
|
||||
swig: lib/tdb/swig/_tdb.$(SHLIBEXT) lib/ldb/swig/_ldb.$(SHLIBEXT) \
|
||||
libcli/swig/_libcli_nbt.$(SHLIBEXT)
|
||||
|
||||
.SUFFIXES: _wrap.c .i
|
||||
|
||||
.i_wrap.c:
|
||||
swig -I$(srcdir)/scripting/swig -python $<
|
||||
|
||||
SWIG_INCLUDES = librpc/gen_ndr/samr.i librpc/gen_ndr/lsa.i librpc/gen_ndr/spoolss.i
|
||||
|
||||
scripting/swig/dcerpc_wrap.c: scripting/swig/dcerpc.i scripting/swig/samba.i scripting/swig/status_codes.i $(SWIG_INCLUDES)
|
||||
|
||||
clean::
|
||||
@echo "Removing SWIG output files"
|
||||
@-rm -f scripting/swig/tdb.pyc scripting/swig/tdb.py
|
||||
|
||||
# Swig testing
|
||||
|
||||
swigtest: swig
|
||||
./script/tests/test_swig.sh
|
||||
@@ -0,0 +1,239 @@
|
||||
/* Tastes like -*- C -*- */
|
||||
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Swig interface to librpc functions.
|
||||
|
||||
Copyright (C) Tim Potter 2004
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
%module dcerpc
|
||||
|
||||
%{
|
||||
|
||||
/* This symbol is used in both includes.h and Python.h which causes an
|
||||
annoying compiler warning. */
|
||||
|
||||
#ifdef HAVE_FSTAT
|
||||
#undef HAVE_FSTAT
|
||||
#endif
|
||||
|
||||
#include "includes.h"
|
||||
#include "dynconfig.h"
|
||||
|
||||
#undef strcpy
|
||||
|
||||
PyObject *ntstatus_exception, *werror_exception;
|
||||
|
||||
/* Set up return of a dcerpc.NTSTATUS exception */
|
||||
|
||||
void set_ntstatus_exception(int status)
|
||||
{
|
||||
PyObject *obj = Py_BuildValue("(i,s)", status,
|
||||
nt_errstr(NT_STATUS(status)));
|
||||
|
||||
PyErr_SetObject(ntstatus_exception, obj);
|
||||
}
|
||||
|
||||
void set_werror_exception(int status)
|
||||
{
|
||||
PyObject *obj = Py_BuildValue("(i,s)", status,
|
||||
win_errstr(W_ERROR(status)));
|
||||
|
||||
PyErr_SetObject(werror_exception, obj);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%include "samba.i"
|
||||
|
||||
%pythoncode %{
|
||||
NTSTATUS = _dcerpc.NTSTATUS
|
||||
WERROR = _dcerpc.WERROR
|
||||
%}
|
||||
|
||||
%init %{
|
||||
setup_logging("python", DEBUG_STDERR);
|
||||
lp_load();
|
||||
ntstatus_exception = PyErr_NewException("_dcerpc.NTSTATUS", NULL, NULL);
|
||||
werror_exception = PyErr_NewException("_dcerpc.WERROR", NULL, NULL);
|
||||
PyDict_SetItemString(d, "NTSTATUS", ntstatus_exception);
|
||||
PyDict_SetItemString(d, "WERROR", werror_exception);
|
||||
|
||||
/* BINARY swig_dcerpc INIT */
|
||||
|
||||
extern NTSTATUS dcerpc_misc_init(void);
|
||||
extern NTSTATUS dcerpc_krb5pac_init(void);
|
||||
extern NTSTATUS dcerpc_samr_init(void);
|
||||
extern NTSTATUS dcerpc_dcerpc_init(void);
|
||||
extern NTSTATUS auth_sam_init(void);
|
||||
extern NTSTATUS dcerpc_lsa_init(void);
|
||||
extern NTSTATUS dcerpc_netlogon_init(void);
|
||||
extern NTSTATUS gensec_init(void);
|
||||
extern NTSTATUS auth_developer_init(void);
|
||||
extern NTSTATUS gensec_spnego_init(void);
|
||||
extern NTSTATUS auth_winbind_init(void);
|
||||
extern NTSTATUS gensec_gssapi_init(void);
|
||||
extern NTSTATUS gensec_ntlmssp_init(void);
|
||||
extern NTSTATUS dcerpc_nbt_init(void);
|
||||
extern NTSTATUS auth_anonymous_init(void);
|
||||
extern NTSTATUS gensec_krb5_init(void);
|
||||
extern NTSTATUS dcerpc_schannel_init(void);
|
||||
extern NTSTATUS dcerpc_epmapper_init(void);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_misc_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_krb5pac_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_samr_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_dcerpc_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(auth_sam_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_lsa_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_netlogon_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(gensec_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(auth_developer_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(gensec_spnego_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(auth_winbind_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(gensec_gssapi_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(gensec_ntlmssp_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_nbt_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(auth_anonymous_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(gensec_krb5_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_schannel_init())) exit(1);
|
||||
if (NT_STATUS_IS_ERR(dcerpc_epmapper_init())) exit(1);
|
||||
|
||||
%}
|
||||
|
||||
%typemap(in, numinputs=0) struct dcerpc_pipe **OUT (struct dcerpc_pipe *temp_dcerpc_pipe) {
|
||||
$1 = &temp_dcerpc_pipe;
|
||||
}
|
||||
|
||||
%typemap(in, numinputs=0) TALLOC_CTX * {
|
||||
$1 = talloc_init("$symname");
|
||||
}
|
||||
|
||||
%typemap(freearg) TALLOC_CTX * {
|
||||
// talloc_free($1);
|
||||
}
|
||||
|
||||
%typemap(argout) struct dcerpc_pipe ** {
|
||||
long status = PyLong_AsLong(resultobj);
|
||||
|
||||
/* Throw exception if result was not OK */
|
||||
|
||||
if (status != 0) {
|
||||
set_ntstatus_exception(status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set REF_ALLOC flag so we don't have to do too much extra
|
||||
mucking around with ref variables in ndr unmarshalling. */
|
||||
|
||||
(*$1)->conn->flags |= DCERPC_NDR_REF_ALLOC;
|
||||
|
||||
/* Return swig handle on dcerpc_pipe */
|
||||
|
||||
resultobj = SWIG_NewPointerObj(*$1, SWIGTYPE_p_dcerpc_pipe, 0);
|
||||
}
|
||||
|
||||
%types(struct dcerpc_pipe *);
|
||||
|
||||
%rename(pipe_connect) dcerpc_pipe_connect;
|
||||
|
||||
NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
|
||||
struct dcerpc_pipe **OUT,
|
||||
const char *binding,
|
||||
const char *pipe_uuid,
|
||||
uint32_t pipe_version,
|
||||
struct cli_credentials *credentials);
|
||||
|
||||
%typemap(in) DATA_BLOB * (DATA_BLOB temp_data_blob) {
|
||||
temp_data_blob.data = PyString_AsString($input);
|
||||
temp_data_blob.length = PyString_Size($input);
|
||||
$1 = &temp_data_blob;
|
||||
}
|
||||
|
||||
const char *dcerpc_server_name(struct dcerpc_pipe *p);
|
||||
|
||||
char *nt_errstr(NTSTATUS nt_code);
|
||||
|
||||
/* Some typemaps for easier access to resume handles. Really this can
|
||||
also be done using the uint32 carray functions, but it's a bit of a
|
||||
hassle. TODO: Fix memory leak here. */
|
||||
|
||||
%typemap(in) uint32_t *resume_handle {
|
||||
$1 = malloc(sizeof(*$1));
|
||||
*$1 = PyLong_AsLong($input);
|
||||
}
|
||||
|
||||
%typemap(out) uint32_t *resume_handle {
|
||||
$result = PyLong_FromLong(*$1);
|
||||
}
|
||||
|
||||
%typemap(in) struct policy_handle * {
|
||||
|
||||
if ((SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor,
|
||||
SWIG_POINTER_EXCEPTION)) == -1)
|
||||
return NULL;
|
||||
|
||||
if ($1 == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "None is not a valid policy handle");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* When returning a policy handle to Python we need to make a copy of
|
||||
as the talloc context it is created under is destroyed after the
|
||||
wrapper function returns. TODO: Fix memory leak created here. */
|
||||
|
||||
%typemap(out) struct policy_handle * {
|
||||
if ($1) {
|
||||
struct policy_handle *temp = (struct policy_handle *)malloc(sizeof(struct policy_handle));
|
||||
memcpy(temp, $1, sizeof(struct policy_handle));
|
||||
$result = SWIG_NewPointerObj(temp, SWIGTYPE_p_policy_handle, 0);
|
||||
} else {
|
||||
Py_INCREF(Py_None);
|
||||
$result = Py_None;
|
||||
}
|
||||
}
|
||||
|
||||
%{
|
||||
#include "librpc/gen_ndr/ndr_misc.h"
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
#include "librpc/gen_ndr/ndr_samr.h"
|
||||
%}
|
||||
|
||||
%include "carrays.i"
|
||||
|
||||
/* Some functions for accessing arrays of fixed-width integers. */
|
||||
|
||||
%array_functions(uint8_t, uint8_array);
|
||||
%array_functions(uint16_t, uint16_array);
|
||||
%array_functions(uint32_t, uint32_array);
|
||||
|
||||
/* Functions for handling arrays of structures. It would be nice for
|
||||
pidl to automatically generating these instead of having to find
|
||||
them all by hand. */
|
||||
|
||||
%array_functions(struct samr_SamEntry, samr_SamEntry_array);
|
||||
%array_functions(union samr_ConnectInfo, samr_ConnectInfo_array);
|
||||
%array_functions(struct samr_RidWithAttribute, samr_RidWithAttribute_array);
|
||||
|
||||
%array_functions(struct lsa_SidPtr, lsa_SidPtr_array);
|
||||
|
||||
%include "librpc/gen_ndr/misc.i"
|
||||
%include "librpc/gen_ndr/security.i"
|
||||
%include "librpc/gen_ndr/samr.i"
|
||||
%include "librpc/gen_ndr/lsa.i"
|
||||
Executable
+301
@@ -0,0 +1,301 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys, os, string
|
||||
from cmd import Cmd
|
||||
from optparse import OptionParser
|
||||
from pprint import pprint
|
||||
|
||||
import dcerpc, samr
|
||||
|
||||
def swig2dict(obj):
|
||||
"""Convert a swig object to a dictionary."""
|
||||
|
||||
result = {}
|
||||
|
||||
for attr in filter(lambda x: type(x) == str, dir(obj)):
|
||||
|
||||
if attr[:2] == '__' and attr[-2:] == '__':
|
||||
continue
|
||||
|
||||
if attr == 'this' or attr == 'thisown':
|
||||
continue
|
||||
|
||||
result[attr] = getattr(obj, attr)
|
||||
|
||||
return result
|
||||
|
||||
class rpcclient(Cmd):
|
||||
|
||||
prompt = 'rpcclient$ '
|
||||
|
||||
def __init__(self, server, cred):
|
||||
Cmd.__init__(self)
|
||||
self.server = server
|
||||
self.cred = cred
|
||||
|
||||
def emptyline(self):
|
||||
|
||||
# Default for empty line is to repeat last command - yuck
|
||||
|
||||
pass
|
||||
|
||||
def onecmd(self, line):
|
||||
|
||||
# Override the onecmd() method so we can trap error returns
|
||||
|
||||
try:
|
||||
Cmd.onecmd(self, line)
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
print 'The command returned an error: %s' % arg[1]
|
||||
|
||||
# Command handlers
|
||||
|
||||
def do_help(self, line):
|
||||
"""Displays on-line help for rpcclient commands."""
|
||||
Cmd.do_help(self, line)
|
||||
|
||||
def do_shell(self, line):
|
||||
|
||||
status = os.system(line)
|
||||
|
||||
if os.WIFEXITED(status):
|
||||
if os.WEXITSTATUS(status) != 0:
|
||||
print 'Command exited with code %d' % os.WEXITSTATUS(status)
|
||||
else:
|
||||
print 'Command exited with signal %d' % os.WTERMSIG(status)
|
||||
|
||||
def do_EOF(self, line):
|
||||
"""Exits rpcclient."""
|
||||
print
|
||||
sys.exit(0)
|
||||
|
||||
# SAMR pipe commands
|
||||
|
||||
def do_SamrEnumDomains(self, line):
|
||||
"""Enumerate domain names."""
|
||||
|
||||
usage = 'usage: SamrEnumDomains'
|
||||
|
||||
if line != '':
|
||||
print usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
|
||||
for i in connect_handle.EnumDomains():
|
||||
print i
|
||||
|
||||
def do_SamrLookupDomain(self, line):
|
||||
"""Return the SID for a domain."""
|
||||
|
||||
usage = 'SamrLookupDomain DOMAIN'
|
||||
|
||||
parser = OptionParser(usage)
|
||||
options, args = parser.parse_args(string.split(line))
|
||||
|
||||
if len(args) != 1:
|
||||
print 'usage:', usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
|
||||
print connect_handle.LookupDomain(args[0])
|
||||
|
||||
def do_SamrQueryDomInfo(self, line):
|
||||
"""Return information about a domain designated by its SID."""
|
||||
|
||||
usage = 'SamrQueryDomInfo DOMAIN_SID [info_level]'
|
||||
|
||||
parser = OptionParser(usage)
|
||||
options, args = parser.parse_args(string.split(line))
|
||||
|
||||
if (len(args) == 0) or (len(args) > 2):
|
||||
print 'usage:', usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
domain_handle = connect_handle.OpenDomain(args[0])
|
||||
|
||||
if (len(args) == 2):
|
||||
result = domain_handle.QueryDomainInfo(int(args[1]))
|
||||
else:
|
||||
result = domain_handle.QueryDomainInfo()
|
||||
|
||||
pprint(swig2dict(result))
|
||||
|
||||
def do_SamrQueryDomInfo2(self, line):
|
||||
"""Return information about a domain designated by its SID.
|
||||
(Windows 2000 and >)"""
|
||||
|
||||
usage = 'SamrQueryDomInfo2 DOMAIN_SID [info_level] (Windows 2000 and >)'
|
||||
parser = OptionParser(usage)
|
||||
options, args = parser.parse_args(string.split(line))
|
||||
|
||||
if len(args) == 0 or len(args) > 2:
|
||||
print 'usage:', usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
domain_handle = connect_handle.OpenDomain(args[0])
|
||||
|
||||
if (len(args) == 2):
|
||||
result = domain_handle.QueryDomainInfo2(int(args[1]))
|
||||
else:
|
||||
result = domain_handle.QueryDomainInfo2()
|
||||
|
||||
pprint(swig2dict(result))
|
||||
|
||||
def do_SamrEnumDomainGroups(self, line):
|
||||
"""Return the list of groups of a domain designated by its SID."""
|
||||
|
||||
usage = 'SamrEnumDomainGroups DOMAIN_SID'
|
||||
|
||||
parser = OptionParser(usage)
|
||||
options, args = parser.parse_args(string.split(line))
|
||||
|
||||
if len(args) != 1:
|
||||
print 'usage:', usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
domain_handle = connect_handle.OpenDomain(args[0])
|
||||
|
||||
result = domain_handle.EnumDomainGroups()
|
||||
|
||||
pprint(result)
|
||||
|
||||
def do_SamrEnumDomainAliases(self, line):
|
||||
"""Return the list of aliases (local groups) of a domain designated
|
||||
by its SID."""
|
||||
|
||||
usage = 'SamrEnumDomainAliases DOMAIN_SID'
|
||||
|
||||
parser = OptionParser(usage)
|
||||
options, args = parser.parse_args(string.split(line))
|
||||
|
||||
if len(args) != 1:
|
||||
print 'usage:', usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
domain_handle = connect_handle.OpenDomain(args[0])
|
||||
|
||||
result = domain_handle.EnumDomainAliases()
|
||||
|
||||
pprint(result)
|
||||
|
||||
def do_SamrEnumDomainUsers(self, line):
|
||||
"""Return the list of users of a domain designated by its SID."""
|
||||
|
||||
usage = 'SamrEnumDomainUsers DOMAIN_SID [user_account_flags]'
|
||||
|
||||
parser = OptionParser(usage)
|
||||
options, args = parser.parse_args(string.split(line))
|
||||
|
||||
if (len(args) == 0) or (len(args) > 2):
|
||||
print 'usage:', usage
|
||||
return
|
||||
|
||||
pipe = dcerpc.pipe_connect(
|
||||
'ncacn_np:%s' % self.server,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION),
|
||||
self.cred)
|
||||
|
||||
connect_handle = samr.Connect(pipe)
|
||||
domain_handle = connect_handle.OpenDomain(args[0])
|
||||
|
||||
if (len(args) == 2):
|
||||
result = domain_handle.EnumDomainUsers(int(args[1]))
|
||||
else:
|
||||
result = domain_handle.EnumDomainUsers()
|
||||
|
||||
pprint(result)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Parse command line
|
||||
|
||||
usage = 'rpcclient SERVER [options]'
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
print usage
|
||||
sys.exit(1)
|
||||
|
||||
server = sys.argv[1]
|
||||
del(sys.argv[1])
|
||||
|
||||
parser = OptionParser(usage)
|
||||
|
||||
parser.add_option('-U', '--username', action='store', type='string',
|
||||
help='Use given credentials when connecting',
|
||||
metavar='DOMAIN\\username%password',
|
||||
dest='username')
|
||||
|
||||
parser.add_option('-c', '--command', action='store', type='string',
|
||||
help='Execute COMMAND', dest='command')
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
# Break --username up into domain, username and password
|
||||
|
||||
cred = None
|
||||
|
||||
if not options.username:
|
||||
options.username = '%'
|
||||
|
||||
domain = ''
|
||||
if string.find(options.username, '\\') != -1:
|
||||
domain, options.username = string.split(options.username, '\\')
|
||||
|
||||
password = ''
|
||||
if string.find(options.username, '%') != -1:
|
||||
options.username, password = string.split(options.username, '%')
|
||||
|
||||
username = options.username
|
||||
|
||||
if username != '':
|
||||
cred = (domain, username, password)
|
||||
|
||||
# Run command loop
|
||||
|
||||
c = rpcclient(server, cred)
|
||||
|
||||
if options.command:
|
||||
c.onecmd(options.command)
|
||||
sys.exit(0)
|
||||
|
||||
while 1:
|
||||
try:
|
||||
c.cmdloop()
|
||||
except KeyboardInterrupt:
|
||||
print 'KeyboardInterrupt'
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Common swig definitions
|
||||
|
||||
Copyright (C) 2004 Tim Potter <tpot@samba.org>
|
||||
|
||||
** NOTE! The following LGPL license applies to the swig
|
||||
** definitions. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
%apply int { uint8_t };
|
||||
%apply int { int8_t };
|
||||
%apply unsigned int { uint16_t };
|
||||
%apply int { int16_t };
|
||||
%apply unsigned long long { uint64_t };
|
||||
%apply long long { int64_t };
|
||||
|
||||
%typemap(in) uint32_t {
|
||||
if (PyLong_Check($input))
|
||||
$1 = PyLong_AsUnsignedLong($input);
|
||||
else if (PyInt_Check($input))
|
||||
$1 = PyInt_AsLong($input);
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,"Expected a long or an int");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) uint32_t {
|
||||
$result = PyLong_FromUnsignedLong($1);
|
||||
}
|
||||
|
||||
%typemap(in) NTSTATUS {
|
||||
if (PyLong_Check($input))
|
||||
$1 = NT_STATUS(PyLong_AsUnsignedLong($input));
|
||||
else if (PyInt_Check($input))
|
||||
$1 = NT_STATUS(PyInt_AsLong($input));
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "Expected a long or an int");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) NTSTATUS {
|
||||
$result = PyLong_FromUnsignedLong(NT_STATUS_V($1));
|
||||
}
|
||||
|
||||
%typemap(in) struct cli_credentials * {
|
||||
$1 = cli_credentials_init(NULL);
|
||||
cli_credentials_set_conf($1);
|
||||
if ($input == Py_None) {
|
||||
cli_credentials_set_anonymous($1);
|
||||
} else {
|
||||
if (!PyTuple_Check($input) ||
|
||||
PyTuple_Size($input) != 3) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expecting three element tuple");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyString_Check(PyTuple_GetItem($input, 0)) ||
|
||||
!PyString_Check(PyTuple_GetItem($input, 1)) ||
|
||||
!PyString_Check(PyTuple_GetItem($input, 2))) {
|
||||
PyErr_SetString(PyExc_TypeError, "Expecting string elements");
|
||||
return NULL;
|
||||
}
|
||||
cli_credentials_set_domain($1, PyString_AsString(PyTuple_GetItem($input, 0)), CRED_SPECIFIED);
|
||||
cli_credentials_set_username($1, PyString_AsString(PyTuple_GetItem($input, 1)), CRED_SPECIFIED);
|
||||
cli_credentials_set_password($1, PyString_AsString(PyTuple_GetItem($input, 2)), CRED_SPECIFIED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,753 @@
|
||||
import dcerpc
|
||||
|
||||
def sid_to_string(sid):
|
||||
"""Convert a Python dictionary SID to a string SID."""
|
||||
|
||||
result = 'S-%d' % sid.sid_rev_num
|
||||
|
||||
result = result + '-%u' % \
|
||||
(dcerpc.uint8_array_getitem(sid.id_auth, 5) +
|
||||
(dcerpc.uint8_array_getitem(sid.id_auth, 4) << 8) +
|
||||
(dcerpc.uint8_array_getitem(sid.id_auth, 3) << 16) +
|
||||
(dcerpc.uint8_array_getitem(sid.id_auth, 2) << 24))
|
||||
|
||||
for i in range(0, sid.num_auths):
|
||||
result = result + '-%u' % \
|
||||
dcerpc.uint32_array_getitem(sid.sub_auths, i)
|
||||
|
||||
return result
|
||||
|
||||
def string_to_sid(string):
|
||||
"""Convert a string SID to a Python dictionary SID. Throws a
|
||||
ValueError if the SID string was badly formed."""
|
||||
|
||||
if string[0] != 'S':
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
string = string[1:]
|
||||
|
||||
import re
|
||||
|
||||
match = re.match('-\d+', string)
|
||||
|
||||
if not match:
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
try:
|
||||
sid_rev_num = int(string[match.start()+1:match.end()])
|
||||
except ValueError:
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
string = string[match.end():]
|
||||
|
||||
match = re.match('-\d+', string)
|
||||
|
||||
if not match:
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
try:
|
||||
ia = int(string[match.start()+1:match.end()])
|
||||
except ValueError:
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
string = string[match.end():]
|
||||
|
||||
id_auth = [0, 0, (ia >> 24) & 0xff, (ia >> 16) & 0xff,
|
||||
(ia >> 8) & 0xff, ia & 0xff]
|
||||
|
||||
num_auths = 0
|
||||
sub_auths = []
|
||||
|
||||
while len(string):
|
||||
|
||||
match = re.match('-\d+', string)
|
||||
|
||||
if not match:
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
try:
|
||||
sa = int(string[match.start() + 1 : match.end()])
|
||||
except ValueError:
|
||||
raise ValueError('Bad SID format')
|
||||
|
||||
num_auths = num_auths + 1
|
||||
sub_auths.append(int(sa))
|
||||
|
||||
string = string[match.end():]
|
||||
|
||||
sid = dcerpc.dom_sid()
|
||||
sid.sid_rev_num = sid_rev_num
|
||||
sid.id_auth = dcerpc.new_uint8_array(6)
|
||||
for i in range(6):
|
||||
dcerpc.uint8_array_setitem(sid.id_auth, i, id_auth[i])
|
||||
sid.num_auths = num_auths
|
||||
sid.sub_auths = dcerpc.new_uint32_array(num_auths)
|
||||
for i in range(num_auths):
|
||||
dcerpc.uint32_array_setitem(sid.sub_auths, i, sub_auths[i])
|
||||
|
||||
return sid
|
||||
|
||||
def call_fn(fn, pipe, args):
|
||||
"""Wrap up a RPC call and throw an exception is an error was returned."""
|
||||
|
||||
result = fn(pipe, args);
|
||||
|
||||
if result & 0xc0000000L:
|
||||
raise dcerpc.NTSTATUS(result, dcerpc.nt_errstr(result));
|
||||
|
||||
return result;
|
||||
|
||||
class SamrHandle:
|
||||
|
||||
def __init__(self, pipe, handle):
|
||||
|
||||
self.pipe = pipe
|
||||
self.handle = handle
|
||||
|
||||
def __del__(self):
|
||||
|
||||
if self.handle is not None:
|
||||
self.Close()
|
||||
|
||||
def Close(self):
|
||||
|
||||
r = dcerpc.samr_Close()
|
||||
r.data_in.handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Close, self.pipe, r)
|
||||
|
||||
self.handle = None
|
||||
|
||||
def QuerySecurity(self, sec_info = 7):
|
||||
|
||||
r = dcerpc.samr_QuerySecurity()
|
||||
r.data_in.handle = self.handle
|
||||
r.data_in.sec_info = sec_info
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QuerySecurity, self.pipe, r)
|
||||
|
||||
return r.data_out.sdbuf
|
||||
|
||||
def SetSecurity(self, sdbuf, sec_info = 7):
|
||||
|
||||
r = dcerpc.samr_SetSecurity()
|
||||
r.data_in.handle = self.handle
|
||||
r.data_in.sec_info = sec_info
|
||||
r.data_in.sdbuf = sdbuf
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_SetSecurity, self.pipe, r)
|
||||
|
||||
class ConnectHandle(SamrHandle):
|
||||
|
||||
def EnumDomains(self):
|
||||
|
||||
r = dcerpc.samr_EnumDomains()
|
||||
r.data_in.connect_handle = self.handle
|
||||
r.data_in.resume_handle = 0
|
||||
r.data_in.buf_size = -1
|
||||
|
||||
domains = []
|
||||
|
||||
while 1:
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_EnumDomains, self.pipe, r)
|
||||
|
||||
for i in range(r.data_out.sam.count):
|
||||
domains.append(dcerpc.samr_SamEntry_array_getitem(
|
||||
r.data_out.sam.entries, i).name.string)
|
||||
|
||||
# TODO: Handle more entries here
|
||||
|
||||
break
|
||||
|
||||
return domains
|
||||
|
||||
def LookupDomain(self, domain_name):
|
||||
|
||||
r = dcerpc.samr_LookupDomain()
|
||||
r.data_in.connect_handle = self.handle
|
||||
r.data_in.domain_name = dcerpc.samr_String()
|
||||
r.data_in.domain_name.string = domain_name
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_LookupDomain, self.pipe, r)
|
||||
|
||||
return sid_to_string(r.data_out.sid);
|
||||
|
||||
def OpenDomain(self, domain_sid, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_OpenDomain()
|
||||
r.data_in.connect_handle = self.handle
|
||||
r.data_in.access_mask = access_mask
|
||||
r.data_in.sid = string_to_sid(domain_sid)
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_OpenDomain, self.pipe, r)
|
||||
|
||||
return DomainHandle(self.pipe, r.data_out.domain_handle)
|
||||
|
||||
def Shutdown(self):
|
||||
|
||||
r = dcerpc.samr_Shutdown()
|
||||
r.data_in.connect_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Shutdown, self.pipe, r)
|
||||
|
||||
def GetDomPwInfo(self, domain_name):
|
||||
|
||||
r = dcerpc.samr_GetDomPwInfo()
|
||||
r.data_in.domain_name = dcerpc.samr_String()
|
||||
r.data_in.domain_name.string = domain_name
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetDomPwInfo, self.pipe, r)
|
||||
|
||||
return r.data_out.info
|
||||
|
||||
|
||||
def SetBootKeyInformation(self, unknown1, unknown2, unknown3):
|
||||
|
||||
r = dcerpc.samr_GetBootKeyInformation()
|
||||
r.data_in.connect_handle = self.handle
|
||||
r.data_in.unknown1 = unknown1
|
||||
r.data_in.unknown2 = unknown2
|
||||
r.data_in.unknown3 = unknown3
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_SetBootKeyInformation, self.pipe, r)
|
||||
|
||||
class DomainHandle(SamrHandle):
|
||||
|
||||
def QueryDomainInfo(self, level = 2):
|
||||
|
||||
r = dcerpc.samr_QueryDomainInfo()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.level = level
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryDomainInfo, self.pipe, r)
|
||||
|
||||
return getattr(r.data_out.info, 'info%d' % level)
|
||||
|
||||
def QueryDomainInfo2(self, level = 2):
|
||||
|
||||
r = dcerpc.samr_QueryDomainInfo2()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.level = level
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryDomainInfo2, self.pipe, r)
|
||||
|
||||
return getattr(r.data_out.info, 'info%d' % level)
|
||||
|
||||
def SetDomainInfo(self, level, info):
|
||||
|
||||
r = dcerpc.samr_SetDomainInfo()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.level = level
|
||||
r.data_in.info = dcerpc.samr_DomainInfo()
|
||||
setattr(r.data_in.info, 'info%d' % level, info)
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_SetDomainInfo, self.pipe, r)
|
||||
|
||||
def EnumDomainGroups(self):
|
||||
|
||||
r = dcerpc.samr_EnumDomainGroups()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.resume_handle = 0
|
||||
r.data_in.max_size = 1000
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_EnumDomainGroups, self.pipe, r)
|
||||
|
||||
groups = []
|
||||
|
||||
if r.data_out.sam.entries:
|
||||
for i in range(r.data_out.sam.count):
|
||||
groups.append(dcerpc.samr_SamEntry_array_getitem(
|
||||
r.data_out.sam.entries, i).name.string)
|
||||
|
||||
return groups
|
||||
|
||||
def EnumDomainAliases(self):
|
||||
|
||||
r = dcerpc.samr_EnumDomainAliases()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.resume_handle = 0
|
||||
# acct_flags in SamrEnumerateAliasesInDomain has probably
|
||||
# no meaning so use 0xffffffff like W2K
|
||||
r.data_in.acct_flags = 0xffffffffL
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_EnumDomainAliases, self.pipe, r)
|
||||
|
||||
aliases = []
|
||||
|
||||
if r.data_out.sam.entries:
|
||||
for i in range(r.data_out.sam.count):
|
||||
aliases.append(dcerpc.samr_SamEntry_array_getitem(
|
||||
r.data_out.sam.entries, i).name.string)
|
||||
|
||||
return aliases
|
||||
|
||||
def EnumDomainUsers(self, user_account_flags = 16):
|
||||
|
||||
r = dcerpc.samr_EnumDomainUsers()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.resume_handle = 0
|
||||
r.data_in.acct_flags = user_account_flags
|
||||
r.data_in.max_size = 1000
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_EnumDomainUsers, self.pipe, r)
|
||||
|
||||
users = []
|
||||
|
||||
if r.data_out.sam.entries:
|
||||
for i in range(r.data_out.sam.count):
|
||||
users.append(dcerpc.samr_SamEntry_array_getitem(
|
||||
r.data_out.sam.entries, i).name.string)
|
||||
|
||||
return users
|
||||
|
||||
def CreateUser(self, account_name, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_CreateUser()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.account_name = dcerpc.samr_String()
|
||||
r.data_in.account_name.string = account_name
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_CreateUser, self.pipe, r)
|
||||
|
||||
return (r.data_out.user_handle,
|
||||
dcerpc.uint32_array_getitem(r.data_out.rid, 0))
|
||||
|
||||
def CreateUser2(self, account_name, acct_flags = 0x00000010,
|
||||
access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_CreateUser2()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.account_name = dcerpc.samr_String()
|
||||
r.data_in.account_name.string = account_name
|
||||
r.data_in.acct_flags = acct_flags
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_CreateUser2, self.pipe, r)
|
||||
|
||||
return (r.data_out.user_handle,
|
||||
dcerpc.uint32_array_getitem(r.data_out.access_granted, 0),
|
||||
dcerpc.uint32_array_getitem(r.data_out.rid, 0))
|
||||
|
||||
def OpenUser(self, rid, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_OpenUser()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.access_mask = access_mask
|
||||
r.data_in.rid = rid
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_OpenUser, self.pipe, r)
|
||||
|
||||
return UserHandle(self.pipe, r.data_out.user_handle)
|
||||
|
||||
def OpenGroup(self, rid, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_OpenGroup()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.access_mask = access_mask
|
||||
r.data_in.rid = rid
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_OpenGroup, self.pipe, r)
|
||||
|
||||
return GroupHandle(self.pipe, r.data_out.group_handle)
|
||||
|
||||
def OpenAlias(self, rid, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_OpenAlias()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.access_mask = access_mask
|
||||
r.data_in.rid = rid
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_OpenAlias, self.pipe, r)
|
||||
|
||||
return AliasHandle(self.pipe, r.data_out.alias_handle)
|
||||
|
||||
def CreateDomAlias(self, alias_name, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_CreateDomAlias()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.alias_name = dcerpc.samr_String()
|
||||
r.data_in.alias_name.string = alias_name
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_CreateDomAlias, self.pipe, r)
|
||||
|
||||
return (AliasHandle(self.pipe, r.data_out.alias_handle),
|
||||
r.data_out.rid)
|
||||
|
||||
def RidToSid(self, rid):
|
||||
|
||||
r = dcerpc.samr_RidToSid()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.rid = rid
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_RidToSid, self.pipe, r)
|
||||
|
||||
return sid_to_string(r.data_out.sid)
|
||||
|
||||
def RemoveMemberFromForeignDomain(self, sid):
|
||||
|
||||
r = dcerpc.samr_RemoveMemberFromForeignDomain()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.sid = sid
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_RemoveMemberFromForeignDomain, self.pipe, r)
|
||||
|
||||
def LookupNames(self, names):
|
||||
|
||||
r = dcerpc.samr_LookupNames()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.num_names = len(names)
|
||||
r.data_in.names = dcerpc.new_samr_String_array(len(names))
|
||||
|
||||
for i in range(len(names)):
|
||||
s = dcerpc.samr_String()
|
||||
s.string = names[i]
|
||||
dcerpc.samr_String_array_setitem(r.data_in.names, i, s)
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_LookupNames, self.pipe, r)
|
||||
|
||||
return ([dcerpc.uint32_array_getitem(r.data_out.rids.ids, i)
|
||||
for i in range(r.data_out.rids.count)],
|
||||
[dcerpc.uint32_array_getitem(r.data_out.types.ids, i)
|
||||
for i in range(r.data_out.types.count)])
|
||||
|
||||
def CreateDomainGroup(self, domain_name, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_CreateDomainGroup()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.name = dcerpc.samr_String()
|
||||
r.data_in.name.string = domain_name
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_CreateDomainGroup, self.pipe, r)
|
||||
|
||||
def GetAliasMembership(self, sids):
|
||||
|
||||
r = dcerpc.samr_GetAliasMembership()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.sids = dcerpc.lsa_SidArray()
|
||||
r.data_in.sids.num_sids = len(sids)
|
||||
r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
|
||||
|
||||
for i in range(len(sids)):
|
||||
s = dcerpc.lsa_SidPtr()
|
||||
s.sid = string_to_sid(sids[i])
|
||||
dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetAliasMembership, self.pipe, r)
|
||||
|
||||
return [r.ids[x] for x in range(r.count)]
|
||||
|
||||
def QueryDisplayInfo(self, level):
|
||||
|
||||
# TODO: Handle more data returns
|
||||
|
||||
r = dcerpc.samr_QueryDisplayInfo()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.level = level
|
||||
r.data_in.start_idx = 0
|
||||
r.data_in.max_entries = 1000
|
||||
r.data_in.buf_size = -1
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo, self.pipe, r)
|
||||
|
||||
# TODO: Return a mapping of the various samr_DispInfo
|
||||
# structures here.
|
||||
|
||||
return getattr(r.data_out.info, 'info%d' % level)
|
||||
|
||||
def QueryDisplayInfo2(self, level):
|
||||
|
||||
# TODO: Handle more data returns
|
||||
|
||||
r = dcerpc.samr_QueryDisplayInfo2()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.level = level
|
||||
r.data_in.start_idx = 0
|
||||
r.data_in.max_entries = 1000
|
||||
r.data_in.buf_size = -1
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo2, self.pipe, r)
|
||||
|
||||
# TODO: Return a mapping of the various samr_DispInfo
|
||||
# structures here.
|
||||
|
||||
return getattr(r.data_out.info, 'info%d' % level)
|
||||
|
||||
def QueryDisplayInfo3(self, level):
|
||||
|
||||
# TODO: Handle more data returns
|
||||
|
||||
r = dcerpc.samr_QueryDisplayInfo3()
|
||||
r.data_in.domain_handle = self.handle
|
||||
r.data_in.level = level
|
||||
r.data_in.start_idx = 0
|
||||
r.data_in.max_entries = 1000
|
||||
r.data_in.buf_size = -1
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryDisplayInfo3, self.pipe, r)
|
||||
|
||||
# TODO: Return a mapping of the various samr_DispInfo
|
||||
# structures here.
|
||||
|
||||
return getattr(r.data_out.info, 'info%d' % level)
|
||||
|
||||
def GetBootKeyInformation(self):
|
||||
|
||||
r = dcerpc.samr_GetBootKeyInformation()
|
||||
r.data_in.domain_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
|
||||
|
||||
return r.data_out.unknown
|
||||
|
||||
def SetBootKeyInformation(self):
|
||||
|
||||
r = dcerpc.samr_GetBootKeyInformation()
|
||||
r.data_in.domain_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetBootKeyInformation, self.pipe, r)
|
||||
|
||||
def TestPrivateFunctionsDomain(self):
|
||||
|
||||
r = dcerpc.samr_TestPrivateFunctionsDomain()
|
||||
r.data_in.domain_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsDomain, self.pipe, r)
|
||||
|
||||
class UserHandle(SamrHandle):
|
||||
|
||||
def DeleteUser(self):
|
||||
|
||||
r = dcerpc.samr_DeleteUser()
|
||||
r.data_in.user_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_DeleteUser, self.pipe, r)
|
||||
|
||||
self.handle = None
|
||||
|
||||
def GetUserPwInfo(self):
|
||||
|
||||
r = dcerpc.samr_GetUserPwInfo()
|
||||
r.data_in.user_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetUserPwInfo, self.pipe, r)
|
||||
|
||||
return r.data_out.info
|
||||
|
||||
def QueryUserInfo(self, level):
|
||||
|
||||
r = dcerpc.samr_QueryUserInfo()
|
||||
r.data_in.user_handle = self.handle
|
||||
r.data_in.level = level
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryUserInfo, self.pipe, r)
|
||||
|
||||
return r.data_out.info
|
||||
|
||||
def QueryUserInfo2(self, level):
|
||||
|
||||
r = dcerpc.samr_QueryUserInfo2()
|
||||
r.data_in.user_handle = self.handle
|
||||
r.data_in.level = level
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryUserInfo2, self.pipe, r)
|
||||
|
||||
return r.data_out.info
|
||||
|
||||
def GetGroupsForUser(self):
|
||||
|
||||
r = dcerpc.samr_GetGroupsForUser()
|
||||
r.data_in.user_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetGroupsForUser, self.pipe, r)
|
||||
|
||||
rid_types = [dcerpc.samr_RidType_array_getitem(r.data_out.rids.rid, x)
|
||||
for x in range(r.data_out.rids.count)]
|
||||
|
||||
return [(x.rid, x.type) for x in rid_types]
|
||||
|
||||
def TestPrivateFunctionsUser(self):
|
||||
|
||||
r = dcerpc.samr_TestPrivateFunctionsUser()
|
||||
r.data_in.user_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_TestPrivateFunctionsUser, self.pipe, r)
|
||||
|
||||
class GroupHandle(SamrHandle):
|
||||
|
||||
def QueryGroupInfo(self, level):
|
||||
|
||||
r = dcerpc.samr_QueryGroupInfo()
|
||||
r.data_in.group_handle = self.handle
|
||||
r.data_in.level = level
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryGroupInfo, self.pipe, r)
|
||||
|
||||
return r.data_out.info
|
||||
|
||||
def SetGroupInfo(self, level, info):
|
||||
|
||||
r = dcerpc.samr_SetGroupInfo()
|
||||
r.data_in.group_handle = self.handle
|
||||
r.data_in.level = level
|
||||
r.data_in.info = info
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_SetGroupInfo, self.pipe, r)
|
||||
|
||||
def QueryGroupMember(self):
|
||||
|
||||
r = dcerpc.samr_QueryGroupMember()
|
||||
r.data_in.group_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryGroupMember, self.pipe, r)
|
||||
|
||||
return [(dcerpc.uint32_array_getitem(r.data_out.rids.rids, x),
|
||||
dcerpc.uint32_array_getitem(r.data_out.rids.unknown, x))
|
||||
for x in range(r.data_out.rids.count)]
|
||||
|
||||
class AliasHandle(SamrHandle):
|
||||
|
||||
def DeleteDomAlias(self):
|
||||
|
||||
r = dcerpc.samr_DeleteDomAlias()
|
||||
r.data_in.alias_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_DeleteDomAlias, self.pipe, r)
|
||||
|
||||
self.handle = None
|
||||
|
||||
def QueryAliasInfo(self, level = 1):
|
||||
|
||||
r = dcerpc.samr_QueryAliasInfo()
|
||||
r.data_in.alias_handle = self.handle
|
||||
r.data_in.level = level
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_QueryAliasInfo, self.pipe, r)
|
||||
|
||||
return r.data_out.info
|
||||
|
||||
def SetAliasInfo(self, level, info):
|
||||
|
||||
r = dcerpc.samr_SetAliasInfo()
|
||||
r.data_in.alias_handle = self.handle
|
||||
r.data_in.level = level
|
||||
r.data_in.info = info
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_SetAliasInfo, self.pipe, r)
|
||||
|
||||
def AddAliasMember(self, sid):
|
||||
|
||||
r = dcerpc.samr_AddAliasMember()
|
||||
r.data_in.alias_handle = self.handle
|
||||
r.data_in.sid = string_to_sid(sid)
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_AddAliasMember, self.pipe, r)
|
||||
|
||||
def AddMultipleMembersToAlias(self, sids):
|
||||
|
||||
r = dcerpc.samr_AddMultipleMembersToAlias()
|
||||
r.data_in.alias_handle = self.handle
|
||||
r.data_in.sids = dcerpc.lsa_SidArray()
|
||||
r.data_in.sids.num_sids = len(sids)
|
||||
r.data_in.sids.sids = dcerpc.new_lsa_SidPtr_array(len(sids))
|
||||
|
||||
for i in range(len(sids)):
|
||||
s = dcerpc.lsa_SidPtr()
|
||||
s.sid = string_to_sid(sids[i])
|
||||
dcerpc.lsa_SidPtr_array_setitem(r.data_in.sids.sids, i, s)
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_AddMultipleMembersToAlias, self.pipe, r)
|
||||
|
||||
def GetMembersInAlias(self):
|
||||
|
||||
r = dcerpc.samr_GetMembersInAlias()
|
||||
r.data_in.alias_handle = self.handle
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_GetMembersInAlias, self.pipe, r)
|
||||
|
||||
return [
|
||||
sid_to_string(
|
||||
dcerpc.lsa_SidPtr_array_getitem(r.data_out.sids.sids, x).sid)
|
||||
for x in range(r.data_out.sids.num_sids)]
|
||||
|
||||
def Connect(pipe, access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_Connect()
|
||||
r.data_in.system_name = dcerpc.new_uint16_array(1)
|
||||
dcerpc.uint16_array_setitem(r.data_in.system_name, 0, ord('\\'))
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Connect, pipe, r)
|
||||
|
||||
return ConnectHandle(pipe, r.data_out.connect_handle)
|
||||
|
||||
def Connect2(pipe, system_name = '', access_mask = 0x02000000):
|
||||
"""Connect to the SAMR pipe."""
|
||||
|
||||
r = dcerpc.samr_Connect2()
|
||||
r.data_in.system_name = system_name
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Connect2, pipe, r)
|
||||
|
||||
return ConnectHandle(pipe, r.data_out.connect_handle)
|
||||
|
||||
def Connect3(pipe, system_name = '', access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_Connect3()
|
||||
r.data_in.system_name = system_name
|
||||
r.data_in.unknown = 0
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Connect3, pipe, r)
|
||||
|
||||
return ConnectHandle(pipe, r.data_out.connect_handle)
|
||||
|
||||
|
||||
def Connect4(pipe, system_name = '', access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_Connect4()
|
||||
r.data_in.system_name = system_name
|
||||
r.data_in.unknown = 0
|
||||
r.data_in.access_mask = access_mask
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Connect4, pipe, r)
|
||||
|
||||
return ConnectHandle(pipe, r.data_out.connect_handle)
|
||||
|
||||
def Connect5(pipe, system_name = '', access_mask = 0x02000000):
|
||||
|
||||
r = dcerpc.samr_Connect5()
|
||||
r.data_in.system_name = system_name
|
||||
r.data_in.access_mask = access_mask
|
||||
r.data_in.level = 1
|
||||
r.data_in.info = dcerpc.new_samr_ConnectInfo_array(1)
|
||||
r.data_in.info.unknown1 = 0
|
||||
r.data_in.info.unknown2 = 0
|
||||
|
||||
call_fn(dcerpc.dcerpc_samr_Connect5, pipe, r)
|
||||
|
||||
return ConnectHandle(pipe, r.data_out.connect_handle)
|
||||
|
||||
# AddGroupMember
|
||||
# DeleteDomainGroup
|
||||
# DeleteGroupMember
|
||||
# SetMemberAttributesofGroup
|
||||
# AddAliasMember
|
||||
# DeleteAliasMember
|
||||
# GetMembersinAlias
|
||||
# SetUserInfo
|
||||
# ChangePasswordUser
|
||||
# GetDisplayEnumerationIndex
|
||||
# RemoveMemberFromForeignDomain
|
||||
# GetDisplayEnumerationIndex2
|
||||
# RemoveMultipleMembersFromAlias
|
||||
# OemChangePasswordUser2
|
||||
# ChangePasswordUser2
|
||||
# SetUserInfo2
|
||||
# ChangePasswordUser3
|
||||
# SetDsrmPassword
|
||||
# ValidatePassword
|
||||
@@ -0,0 +1,554 @@
|
||||
/* Win32 status codes */
|
||||
|
||||
#define STATUS_BUFFER_OVERFLOW 0x80000005
|
||||
#define STATUS_NO_MORE_FILES 0x80000006
|
||||
#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
|
||||
|
||||
#define STATUS_MORE_ENTRIES 0x0105
|
||||
#define STATUS_SOME_UNMAPPED 0x0107
|
||||
#define ERROR_INVALID_PARAMETER 0x0057
|
||||
#define ERROR_INSUFFICIENT_BUFFER 0x007a
|
||||
#define STATUS_NOTIFY_ENUM_DIR 0x010c
|
||||
#define ERROR_INVALID_DATATYPE 0x070c
|
||||
|
||||
/* NT status codes */
|
||||
|
||||
#define NT_STATUS_OK 0x00000000
|
||||
#define NT_STATUS_UNSUCCESSFUL 0xC0000001
|
||||
#define NT_STATUS_NOT_IMPLEMENTED 0xC0000002
|
||||
#define NT_STATUS_INVALID_INFO_CLASS 0xC0000003
|
||||
#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000004
|
||||
#define NT_STATUS_ACCESS_VIOLATION 0xC0000005
|
||||
#define NT_STATUS_IN_PAGE_ERROR 0xC0000006
|
||||
#define NT_STATUS_PAGEFILE_QUOTA 0xC0000007
|
||||
#define NT_STATUS_INVALID_HANDLE 0xC0000008
|
||||
#define NT_STATUS_BAD_INITIAL_STACK 0xC0000009
|
||||
#define NT_STATUS_BAD_INITIAL_PC 0xC000000a
|
||||
#define NT_STATUS_INVALID_CID 0xC000000b
|
||||
#define NT_STATUS_TIMER_NOT_CANCELED 0xC000000c
|
||||
#define NT_STATUS_INVALID_PARAMETER 0xC000000d
|
||||
#define NT_STATUS_NO_SUCH_DEVICE 0xC000000e
|
||||
#define NT_STATUS_NO_SUCH_FILE 0xC000000f
|
||||
#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000010
|
||||
#define NT_STATUS_END_OF_FILE 0xC0000011
|
||||
#define NT_STATUS_WRONG_VOLUME 0xC0000012
|
||||
#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000013
|
||||
#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000014
|
||||
#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000015
|
||||
#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000016
|
||||
#define NT_STATUS_NO_MEMORY 0xC0000017
|
||||
#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000018
|
||||
#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000019
|
||||
#define NT_STATUS_UNABLE_TO_FREE_VM 0xC000001a
|
||||
#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC000001b
|
||||
#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC000001c
|
||||
#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC000001d
|
||||
#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC000001e
|
||||
#define NT_STATUS_INVALID_VIEW_SIZE 0xC000001f
|
||||
#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000020
|
||||
#define NT_STATUS_ALREADY_COMMITTED 0xC0000021
|
||||
#define NT_STATUS_ACCESS_DENIED 0xC0000022
|
||||
#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000023
|
||||
#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000024
|
||||
#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025
|
||||
#define NT_STATUS_INVALID_DISPOSITION 0xC0000026
|
||||
#define NT_STATUS_UNWIND 0xC0000027
|
||||
#define NT_STATUS_BAD_STACK 0xC0000028
|
||||
#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000029
|
||||
#define NT_STATUS_NOT_LOCKED 0xC000002a
|
||||
#define NT_STATUS_PARITY_ERROR 0xC000002b
|
||||
#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC000002c
|
||||
#define NT_STATUS_NOT_COMMITTED 0xC000002d
|
||||
#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC000002e
|
||||
#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC000002f
|
||||
#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000030
|
||||
#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000031
|
||||
#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000032
|
||||
#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000033
|
||||
#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034
|
||||
#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000035
|
||||
#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000036
|
||||
#define NT_STATUS_PORT_DISCONNECTED 0xC0000037
|
||||
#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000038
|
||||
#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000039
|
||||
#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC000003a
|
||||
#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC000003b
|
||||
#define NT_STATUS_DATA_OVERRUN 0xC000003c
|
||||
#define NT_STATUS_DATA_LATE_ERROR 0xC000003d
|
||||
#define NT_STATUS_DATA_ERROR 0xC000003e
|
||||
#define NT_STATUS_CRC_ERROR 0xC000003f
|
||||
#define NT_STATUS_SECTION_TOO_BIG 0xC0000040
|
||||
#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000041
|
||||
#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000042
|
||||
#define NT_STATUS_SHARING_VIOLATION 0xC0000043
|
||||
#define NT_STATUS_QUOTA_EXCEEDED 0xC0000044
|
||||
#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000045
|
||||
#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000046
|
||||
#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000047
|
||||
#define NT_STATUS_PORT_ALREADY_SET 0xC0000048
|
||||
#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000049
|
||||
#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC000004a
|
||||
#define NT_STATUS_THREAD_IS_TERMINATING 0xC000004b
|
||||
#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC000004c
|
||||
#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC000004d
|
||||
#define NT_STATUS_SECTION_PROTECTION 0xC000004e
|
||||
#define NT_STATUS_EAS_NOT_SUPPORTED 0xC000004f
|
||||
#define NT_STATUS_EA_TOO_LARGE 0xC0000050
|
||||
#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000051
|
||||
#define NT_STATUS_NO_EAS_ON_FILE 0xC0000052
|
||||
#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000053
|
||||
#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000054
|
||||
#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000055
|
||||
#define NT_STATUS_DELETE_PENDING 0xC0000056
|
||||
#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000057
|
||||
#define NT_STATUS_UNKNOWN_REVISION 0xC0000058
|
||||
#define NT_STATUS_REVISION_MISMATCH 0xC0000059
|
||||
#define NT_STATUS_INVALID_OWNER 0xC000005a
|
||||
#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC000005b
|
||||
#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC000005c
|
||||
#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC000005d
|
||||
#define NT_STATUS_NO_LOGON_SERVERS 0xC000005e
|
||||
#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC000005f
|
||||
#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000060
|
||||
#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000061
|
||||
#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000062
|
||||
#define NT_STATUS_USER_EXISTS 0xC0000063
|
||||
#define NT_STATUS_NO_SUCH_USER 0xC0000064
|
||||
#define NT_STATUS_GROUP_EXISTS 0xC0000065
|
||||
#define NT_STATUS_NO_SUCH_GROUP 0xC0000066
|
||||
#define NT_STATUS_MEMBER_IN_GROUP 0xC0000067
|
||||
#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000068
|
||||
#define NT_STATUS_LAST_ADMIN 0xC0000069
|
||||
#define NT_STATUS_WRONG_PASSWORD 0xC000006a
|
||||
#define NT_STATUS_ILL_FORMED_PASSWORD 0xC000006b
|
||||
#define NT_STATUS_PASSWORD_RESTRICTION 0xC000006c
|
||||
#define NT_STATUS_LOGON_FAILURE 0xC000006d
|
||||
#define NT_STATUS_ACCOUNT_RESTRICTION 0xC000006e
|
||||
#define NT_STATUS_INVALID_LOGON_HOURS 0xC000006f
|
||||
#define NT_STATUS_INVALID_WORKSTATION 0xC0000070
|
||||
#define NT_STATUS_PASSWORD_EXPIRED 0xC0000071
|
||||
#define NT_STATUS_ACCOUNT_DISABLED 0xC0000072
|
||||
#define NT_STATUS_NONE_MAPPED 0xC0000073
|
||||
#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000074
|
||||
#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000075
|
||||
#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000076
|
||||
#define NT_STATUS_INVALID_ACL 0xC0000077
|
||||
#define NT_STATUS_INVALID_SID 0xC0000078
|
||||
#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000079
|
||||
#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC000007a
|
||||
#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC000007b
|
||||
#define NT_STATUS_NO_TOKEN 0xC000007c
|
||||
#define NT_STATUS_BAD_INHERITANCE_ACL 0xC000007d
|
||||
#define NT_STATUS_RANGE_NOT_LOCKED 0xC000007e
|
||||
#define NT_STATUS_DISK_FULL 0xC000007f
|
||||
#define NT_STATUS_SERVER_DISABLED 0xC0000080
|
||||
#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000081
|
||||
#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000082
|
||||
#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000083
|
||||
#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000084
|
||||
#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000085
|
||||
#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000086
|
||||
#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000087
|
||||
#define NT_STATUS_NOT_MAPPED_DATA 0xC0000088
|
||||
#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000089
|
||||
#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC000008a
|
||||
#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC000008b
|
||||
#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008c
|
||||
#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC000008d
|
||||
#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008e
|
||||
#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC000008f
|
||||
#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000090
|
||||
#define NT_STATUS_FLOAT_OVERFLOW 0xC0000091
|
||||
#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000092
|
||||
#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000093
|
||||
#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094
|
||||
#define NT_STATUS_INTEGER_OVERFLOW 0xC0000095
|
||||
#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000096
|
||||
#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000097
|
||||
#define NT_STATUS_FILE_INVALID 0xC0000098
|
||||
#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000099
|
||||
#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC000009a
|
||||
#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC000009b
|
||||
#define NT_STATUS_DEVICE_DATA_ERROR 0xC000009c
|
||||
#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC000009d
|
||||
#define NT_STATUS_DEVICE_POWER_FAILURE 0xC000009e
|
||||
#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC000009f
|
||||
#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC00000a0
|
||||
#define NT_STATUS_WORKING_SET_QUOTA 0xC00000a1
|
||||
#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC00000a2
|
||||
#define NT_STATUS_DEVICE_NOT_READY 0xC00000a3
|
||||
#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC00000a4
|
||||
#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC00000a5
|
||||
#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC00000a6
|
||||
#define NT_STATUS_BAD_VALIDATION_CLASS 0xC00000a7
|
||||
#define NT_STATUS_BAD_TOKEN_TYPE 0xC00000a8
|
||||
#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC00000a9
|
||||
#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC00000aa
|
||||
#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC00000ab
|
||||
#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC00000ac
|
||||
#define NT_STATUS_INVALID_PIPE_STATE 0xC00000ad
|
||||
#define NT_STATUS_PIPE_BUSY 0xC00000ae
|
||||
#define NT_STATUS_ILLEGAL_FUNCTION 0xC00000af
|
||||
#define NT_STATUS_PIPE_DISCONNECTED 0xC00000b0
|
||||
#define NT_STATUS_PIPE_CLOSING 0xC00000b1
|
||||
#define NT_STATUS_PIPE_CONNECTED 0xC00000b2
|
||||
#define NT_STATUS_PIPE_LISTENING 0xC00000b3
|
||||
#define NT_STATUS_INVALID_READ_MODE 0xC00000b4
|
||||
#define NT_STATUS_IO_TIMEOUT 0xC00000b5
|
||||
#define NT_STATUS_FILE_FORCED_CLOSED 0xC00000b6
|
||||
#define NT_STATUS_PROFILING_NOT_STARTED 0xC00000b7
|
||||
#define NT_STATUS_PROFILING_NOT_STOPPED 0xC00000b8
|
||||
#define NT_STATUS_COULD_NOT_INTERPRET 0xC00000b9
|
||||
#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC00000ba
|
||||
#define NT_STATUS_NOT_SUPPORTED 0xC00000bb
|
||||
#define NT_STATUS_REMOTE_NOT_LISTENING 0xC00000bc
|
||||
#define NT_STATUS_DUPLICATE_NAME 0xC00000bd
|
||||
#define NT_STATUS_BAD_NETWORK_PATH 0xC00000be
|
||||
#define NT_STATUS_NETWORK_BUSY 0xC00000bf
|
||||
#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC00000c0
|
||||
#define NT_STATUS_TOO_MANY_COMMANDS 0xC00000c1
|
||||
#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC00000c2
|
||||
#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC00000c3
|
||||
#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC00000c4
|
||||
#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC00000c5
|
||||
#define NT_STATUS_PRINT_QUEUE_FULL 0xC00000c6
|
||||
#define NT_STATUS_NO_SPOOL_SPACE 0xC00000c7
|
||||
#define NT_STATUS_PRINT_CANCELLED 0xC00000c8
|
||||
#define NT_STATUS_NETWORK_NAME_DELETED 0xC00000c9
|
||||
#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC00000ca
|
||||
#define NT_STATUS_BAD_DEVICE_TYPE 0xC00000cb
|
||||
#define NT_STATUS_BAD_NETWORK_NAME 0xC00000cc
|
||||
#define NT_STATUS_TOO_MANY_NAMES 0xC00000cd
|
||||
#define NT_STATUS_TOO_MANY_SESSIONS 0xC00000ce
|
||||
#define NT_STATUS_SHARING_PAUSED 0xC00000cf
|
||||
#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC00000d0
|
||||
#define NT_STATUS_REDIRECTOR_PAUSED 0xC00000d1
|
||||
#define NT_STATUS_NET_WRITE_FAULT 0xC00000d2
|
||||
#define NT_STATUS_PROFILING_AT_LIMIT 0xC00000d3
|
||||
#define NT_STATUS_NOT_SAME_DEVICE 0xC00000d4
|
||||
#define NT_STATUS_FILE_RENAMED 0xC00000d5
|
||||
#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC00000d6
|
||||
#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC00000d7
|
||||
#define NT_STATUS_CANT_WAIT 0xC00000d8
|
||||
#define NT_STATUS_PIPE_EMPTY 0xC00000d9
|
||||
#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC00000da
|
||||
#define NT_STATUS_CANT_TERMINATE_SELF 0xC00000db
|
||||
#define NT_STATUS_INVALID_SERVER_STATE 0xC00000dc
|
||||
#define NT_STATUS_INVALID_DOMAIN_STATE 0xC00000dd
|
||||
#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC00000de
|
||||
#define NT_STATUS_NO_SUCH_DOMAIN 0xC00000df
|
||||
#define NT_STATUS_DOMAIN_EXISTS 0xC00000e0
|
||||
#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC00000e1
|
||||
#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC00000e2
|
||||
#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC00000e3
|
||||
#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC00000e4
|
||||
#define NT_STATUS_INTERNAL_ERROR 0xC00000e5
|
||||
#define NT_STATUS_GENERIC_NOT_MAPPED 0xC00000e6
|
||||
#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC00000e7
|
||||
#define NT_STATUS_INVALID_USER_BUFFER 0xC00000e8
|
||||
#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC00000e9
|
||||
#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC00000ea
|
||||
#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC00000eb
|
||||
#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC00000ec
|
||||
#define NT_STATUS_NOT_LOGON_PROCESS 0xC00000ed
|
||||
#define NT_STATUS_LOGON_SESSION_EXISTS 0xC00000ee
|
||||
#define NT_STATUS_INVALID_PARAMETER_1 0xC00000ef
|
||||
#define NT_STATUS_INVALID_PARAMETER_2 0xC00000f0
|
||||
#define NT_STATUS_INVALID_PARAMETER_3 0xC00000f1
|
||||
#define NT_STATUS_INVALID_PARAMETER_4 0xC00000f2
|
||||
#define NT_STATUS_INVALID_PARAMETER_5 0xC00000f3
|
||||
#define NT_STATUS_INVALID_PARAMETER_6 0xC00000f4
|
||||
#define NT_STATUS_INVALID_PARAMETER_7 0xC00000f5
|
||||
#define NT_STATUS_INVALID_PARAMETER_8 0xC00000f6
|
||||
#define NT_STATUS_INVALID_PARAMETER_9 0xC00000f7
|
||||
#define NT_STATUS_INVALID_PARAMETER_10 0xC00000f8
|
||||
#define NT_STATUS_INVALID_PARAMETER_11 0xC00000f9
|
||||
#define NT_STATUS_INVALID_PARAMETER_12 0xC00000fa
|
||||
#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC00000fb
|
||||
#define NT_STATUS_REDIRECTOR_STARTED 0xC00000fc
|
||||
#define NT_STATUS_STACK_OVERFLOW 0xC00000fd
|
||||
#define NT_STATUS_NO_SUCH_PACKAGE 0xC00000fe
|
||||
#define NT_STATUS_BAD_FUNCTION_TABLE 0xC00000ff
|
||||
#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000101
|
||||
#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000102
|
||||
#define NT_STATUS_NOT_A_DIRECTORY 0xC0000103
|
||||
#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000104
|
||||
#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000105
|
||||
#define NT_STATUS_NAME_TOO_LONG 0xC0000106
|
||||
#define NT_STATUS_FILES_OPEN 0xC0000107
|
||||
#define NT_STATUS_CONNECTION_IN_USE 0xC0000108
|
||||
#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000109
|
||||
#define NT_STATUS_PROCESS_IS_TERMINATING 0xC000010a
|
||||
#define NT_STATUS_INVALID_LOGON_TYPE 0xC000010b
|
||||
#define NT_STATUS_NO_GUID_TRANSLATION 0xC000010c
|
||||
#define NT_STATUS_CANNOT_IMPERSONATE 0xC000010d
|
||||
#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC000010e
|
||||
#define NT_STATUS_ABIOS_NOT_PRESENT 0xC000010f
|
||||
#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000110
|
||||
#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000111
|
||||
#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000112
|
||||
#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000113
|
||||
#define NT_STATUS_ABIOS_INVALID_LID 0xC0000114
|
||||
#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000115
|
||||
#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000116
|
||||
#define NT_STATUS_NO_LDT 0xC0000117
|
||||
#define NT_STATUS_INVALID_LDT_SIZE 0xC0000118
|
||||
#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000119
|
||||
#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC000011a
|
||||
#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC000011b
|
||||
#define NT_STATUS_RXACT_INVALID_STATE 0xC000011c
|
||||
#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC000011d
|
||||
#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC000011e
|
||||
#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC000011f
|
||||
#define NT_STATUS_CANCELLED 0xC0000120
|
||||
#define NT_STATUS_CANNOT_DELETE 0xC0000121
|
||||
#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000122
|
||||
#define NT_STATUS_FILE_DELETED 0xC0000123
|
||||
#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000124
|
||||
#define NT_STATUS_SPECIAL_GROUP 0xC0000125
|
||||
#define NT_STATUS_SPECIAL_USER 0xC0000126
|
||||
#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000127
|
||||
#define NT_STATUS_FILE_CLOSED 0xC0000128
|
||||
#define NT_STATUS_TOO_MANY_THREADS 0xC0000129
|
||||
#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC000012a
|
||||
#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC000012b
|
||||
#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC000012c
|
||||
#define NT_STATUS_COMMITMENT_LIMIT 0xC000012d
|
||||
#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC000012e
|
||||
#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC000012f
|
||||
#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000130
|
||||
#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000131
|
||||
#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000132
|
||||
#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000133
|
||||
#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000134
|
||||
#define NT_STATUS_DLL_NOT_FOUND 0xC0000135
|
||||
#define NT_STATUS_OPEN_FAILED 0xC0000136
|
||||
#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000137
|
||||
#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000138
|
||||
#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000139
|
||||
#define NT_STATUS_CONTROL_C_EXIT 0xC000013a
|
||||
#define NT_STATUS_LOCAL_DISCONNECT 0xC000013b
|
||||
#define NT_STATUS_REMOTE_DISCONNECT 0xC000013c
|
||||
#define NT_STATUS_REMOTE_RESOURCES 0xC000013d
|
||||
#define NT_STATUS_LINK_FAILED 0xC000013e
|
||||
#define NT_STATUS_LINK_TIMEOUT 0xC000013f
|
||||
#define NT_STATUS_INVALID_CONNECTION 0xC0000140
|
||||
#define NT_STATUS_INVALID_ADDRESS 0xC0000141
|
||||
#define NT_STATUS_DLL_INIT_FAILED 0xC0000142
|
||||
#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000143
|
||||
#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000144
|
||||
#define NT_STATUS_APP_INIT_FAILURE 0xC0000145
|
||||
#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000146
|
||||
#define NT_STATUS_NO_PAGEFILE 0xC0000147
|
||||
#define NT_STATUS_INVALID_LEVEL 0xC0000148
|
||||
#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000149
|
||||
#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC000014a
|
||||
#define NT_STATUS_PIPE_BROKEN 0xC000014b
|
||||
#define NT_STATUS_REGISTRY_CORRUPT 0xC000014c
|
||||
#define NT_STATUS_REGISTRY_IO_FAILED 0xC000014d
|
||||
#define NT_STATUS_NO_EVENT_PAIR 0xC000014e
|
||||
#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC000014f
|
||||
#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000150
|
||||
#define NT_STATUS_NO_SUCH_ALIAS 0xC0000151
|
||||
#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000152
|
||||
#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000153
|
||||
#define NT_STATUS_ALIAS_EXISTS 0xC0000154
|
||||
#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000155
|
||||
#define NT_STATUS_TOO_MANY_SECRETS 0xC0000156
|
||||
#define NT_STATUS_SECRET_TOO_LONG 0xC0000157
|
||||
#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000158
|
||||
#define NT_STATUS_FULLSCREEN_MODE 0xC0000159
|
||||
#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC000015a
|
||||
#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC000015b
|
||||
#define NT_STATUS_NOT_REGISTRY_FILE 0xC000015c
|
||||
#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC000015d
|
||||
#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC000015e
|
||||
#define NT_STATUS_FT_MISSING_MEMBER 0xC000015f
|
||||
#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000160
|
||||
#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000161
|
||||
#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000162
|
||||
#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000163
|
||||
#define NT_STATUS_FLOPPY_VOLUME 0xC0000164
|
||||
#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000165
|
||||
#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000166
|
||||
#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000167
|
||||
#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000168
|
||||
#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000169
|
||||
#define NT_STATUS_DISK_OPERATION_FAILED 0xC000016a
|
||||
#define NT_STATUS_DISK_RESET_FAILED 0xC000016b
|
||||
#define NT_STATUS_SHARED_IRQ_BUSY 0xC000016c
|
||||
#define NT_STATUS_FT_ORPHANING 0xC000016d
|
||||
#define NT_STATUS_PARTITION_FAILURE 0xC0000172
|
||||
#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000173
|
||||
#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000174
|
||||
#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000175
|
||||
#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000176
|
||||
#define NT_STATUS_EOM_OVERFLOW 0xC0000177
|
||||
#define NT_STATUS_NO_MEDIA 0xC0000178
|
||||
#define NT_STATUS_NO_SUCH_MEMBER 0xC000017a
|
||||
#define NT_STATUS_INVALID_MEMBER 0xC000017b
|
||||
#define NT_STATUS_KEY_DELETED 0xC000017c
|
||||
#define NT_STATUS_NO_LOG_SPACE 0xC000017d
|
||||
#define NT_STATUS_TOO_MANY_SIDS 0xC000017e
|
||||
#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC000017f
|
||||
#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000180
|
||||
#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000181
|
||||
#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000182
|
||||
#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000183
|
||||
#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000184
|
||||
#define NT_STATUS_IO_DEVICE_ERROR 0xC0000185
|
||||
#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000186
|
||||
#define NT_STATUS_BACKUP_CONTROLLER 0xC0000187
|
||||
#define NT_STATUS_LOG_FILE_FULL 0xC0000188
|
||||
#define NT_STATUS_TOO_LATE 0xC0000189
|
||||
#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC000018a
|
||||
#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC000018b
|
||||
#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC000018c
|
||||
#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC000018d
|
||||
#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC000018e
|
||||
#define NT_STATUS_EVENTLOG_CANT_START 0xC000018f
|
||||
#define NT_STATUS_TRUST_FAILURE 0xC0000190
|
||||
#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000191
|
||||
#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000192
|
||||
#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000193
|
||||
#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000194
|
||||
#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000195
|
||||
#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000196
|
||||
#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000197
|
||||
#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000198
|
||||
#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000199
|
||||
#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC000019a
|
||||
#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC000019b
|
||||
#define NT_STATUS_FS_DRIVER_REQUIRED 0xC000019c
|
||||
#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000202
|
||||
#define NT_STATUS_USER_SESSION_DELETED 0xC0000203
|
||||
#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000204
|
||||
#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000205
|
||||
#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000206
|
||||
#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000207
|
||||
#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000208
|
||||
#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000209
|
||||
#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC000020a
|
||||
#define NT_STATUS_ADDRESS_CLOSED 0xC000020b
|
||||
#define NT_STATUS_CONNECTION_DISCONNECTED 0xC000020c
|
||||
#define NT_STATUS_CONNECTION_RESET 0xC000020d
|
||||
#define NT_STATUS_TOO_MANY_NODES 0xC000020e
|
||||
#define NT_STATUS_TRANSACTION_ABORTED 0xC000020f
|
||||
#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000210
|
||||
#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000211
|
||||
#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000212
|
||||
#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000213
|
||||
#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000214
|
||||
#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000215
|
||||
#define NT_STATUS_NOT_SERVER_SESSION 0xC0000216
|
||||
#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000217
|
||||
#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000218
|
||||
#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000219
|
||||
#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC000021a
|
||||
#define NT_STATUS_DATA_NOT_ACCEPTED 0xC000021b
|
||||
#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC000021c
|
||||
#define NT_STATUS_VDM_HARD_ERROR 0xC000021d
|
||||
#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC000021e
|
||||
#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC000021f
|
||||
#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000220
|
||||
#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000221
|
||||
#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000222
|
||||
#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000223
|
||||
#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000224
|
||||
#define NT_STATUS_NOT_FOUND 0xC0000225
|
||||
#define NT_STATUS_NOT_TINY_STREAM 0xC0000226
|
||||
#define NT_STATUS_RECOVERY_FAILURE 0xC0000227
|
||||
#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000228
|
||||
#define NT_STATUS_FAIL_CHECK 0xC0000229
|
||||
#define NT_STATUS_DUPLICATE_OBJECTID 0xC000022a
|
||||
#define NT_STATUS_OBJECTID_EXISTS 0xC000022b
|
||||
#define NT_STATUS_CONVERT_TO_LARGE 0xC000022c
|
||||
#define NT_STATUS_RETRY 0xC000022d
|
||||
#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC000022e
|
||||
#define NT_STATUS_ALLOCATE_BUCKET 0xC000022f
|
||||
#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000230
|
||||
#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000231
|
||||
#define NT_STATUS_INVALID_VARIANT 0xC0000232
|
||||
#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000233
|
||||
#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000234
|
||||
#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000235
|
||||
#define NT_STATUS_CONNECTION_REFUSED 0xC0000236
|
||||
#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000237
|
||||
#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000238
|
||||
#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000239
|
||||
#define NT_STATUS_CONNECTION_INVALID 0xC000023a
|
||||
#define NT_STATUS_CONNECTION_ACTIVE 0xC000023b
|
||||
#define NT_STATUS_NETWORK_UNREACHABLE 0xC000023c
|
||||
#define NT_STATUS_HOST_UNREACHABLE 0xC000023d
|
||||
#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC000023e
|
||||
#define NT_STATUS_PORT_UNREACHABLE 0xC000023f
|
||||
#define NT_STATUS_REQUEST_ABORTED 0xC0000240
|
||||
#define NT_STATUS_CONNECTION_ABORTED 0xC0000241
|
||||
#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000242
|
||||
#define NT_STATUS_USER_MAPPED_FILE 0xC0000243
|
||||
#define NT_STATUS_AUDIT_FAILED 0xC0000244
|
||||
#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000245
|
||||
#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000246
|
||||
#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000247
|
||||
#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000248
|
||||
#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000249
|
||||
#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000250
|
||||
#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000251
|
||||
#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000252
|
||||
#define NT_STATUS_LPC_REPLY_LOST 0xC0000253
|
||||
#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000254
|
||||
#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000255
|
||||
#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000256
|
||||
#define NT_STATUS_PATH_NOT_COVERED 0xC0000257
|
||||
#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000258
|
||||
#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000259
|
||||
#define NT_STATUS_PWD_TOO_SHORT 0xC000025a
|
||||
#define NT_STATUS_PWD_TOO_RECENT 0xC000025b
|
||||
#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC000025c
|
||||
#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC000025e
|
||||
#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC000025f
|
||||
#define NT_STATUS_INVALID_HW_PROFILE 0xC0000260
|
||||
#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000261
|
||||
#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000262
|
||||
#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000263
|
||||
#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000264
|
||||
#define NT_STATUS_TOO_MANY_LINKS 0xC0000265
|
||||
#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000266
|
||||
#define NT_STATUS_FILE_IS_OFFLINE 0xC0000267
|
||||
#define NT_STATUS_NOT_A_REPARSE_POINT 0xC0000275
|
||||
#define NT_STATUS_NO_SUCH_JOB 0xC0000EDE
|
||||
|
||||
#define WERR_OK 0
|
||||
#define WERR_BADFUNC 1
|
||||
#define WERR_BADFILE 2
|
||||
#define WERR_ACCESS_DENIED 5
|
||||
#define WERR_BADFID 6
|
||||
#define WERR_NOMEM 8
|
||||
#define WERR_GENERAL_FAILURE 31
|
||||
#define WERR_NOT_SUPPORTED 50
|
||||
#define WERR_BAD_NETPATH 53
|
||||
#define WERR_PRINTQ_FULL 61
|
||||
#define WERR_NO_SPOOL_SPACE 62
|
||||
#define WERR_NO_SUCH_SHARE 67
|
||||
#define WERR_ALREADY_EXISTS 80
|
||||
#define WERR_BAD_PASSWORD 86
|
||||
#define WERR_INVALID_PARAM 87
|
||||
#define WERR_INSUFFICIENT_BUFFER 122
|
||||
#define WERR_INVALID_NAME 123
|
||||
#define WERR_UNKNOWN_LEVEL 124
|
||||
#define WERR_OBJECT_PATH_INVALID 161
|
||||
#define WERR_NO_MORE_ITEMS 259
|
||||
#define WERR_MORE_DATA 234
|
||||
#define WERR_INVALID_OWNER 1307
|
||||
#define WERR_CAN_NOT_COMPLETE 1003
|
||||
#define WERR_INVALID_SECURITY_DESCRIPTOR 1338
|
||||
#define WERR_SERVER_UNAVAILABLE 1722
|
||||
#define WERR_UNKNOWN_PRINTER_DRIVER 1797
|
||||
#define WERR_INVALID_ENVIRONMENT 1805
|
||||
#define WERR_INVALID_FORM_NAME 1902
|
||||
#define WERR_INVALID_FORM_SIZE 1903
|
||||
#define WERR_BUF_TOO_SMALL 2123
|
||||
#define WERR_JOB_NOT_FOUND 2151
|
||||
#define WERR_DEST_NOT_FOUND 2152
|
||||
#define WERR_NOT_LOCAL_DOMAIN 2320
|
||||
#define WERR_STATUS_MORE_ENTRIES 0x0105
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
# Parse command line
|
||||
|
||||
parser = OptionParser()
|
||||
|
||||
parser.add_option("-b", "--binding", action="store", type="string",
|
||||
dest="binding")
|
||||
|
||||
parser.add_option("-d", "--domain", action="store", type="string",
|
||||
dest="domain")
|
||||
|
||||
parser.add_option("-u", "--username", action="store", type="string",
|
||||
dest="username")
|
||||
|
||||
parser.add_option("-p", "--password", action="store", type="string",
|
||||
dest="password")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if not options.binding:
|
||||
parser.error('You must supply a binding string')
|
||||
|
||||
if not options.username or not options.password or not options.domain:
|
||||
parser.error('You must supply a domain, username and password')
|
||||
|
||||
binding = options.binding
|
||||
domain = options.domain
|
||||
username = options.username
|
||||
password = options.password
|
||||
|
||||
if len(args) == 0:
|
||||
parser.error('You must supply the name of a module to test')
|
||||
|
||||
# Import and test
|
||||
|
||||
for test in args:
|
||||
|
||||
try:
|
||||
module = __import__('torture_%s' % test)
|
||||
except ImportError:
|
||||
print 'No such module "%s"' % test
|
||||
sys.exit(1)
|
||||
|
||||
if not hasattr(module, 'runtests'):
|
||||
print 'Module "%s" does not have a runtests function' % test
|
||||
|
||||
module.runtests(binding, (domain, username, password))
|
||||
@@ -0,0 +1,437 @@
|
||||
import sys, string
|
||||
import dcerpc
|
||||
|
||||
|
||||
def ResizeBufferCall(fn, pipe, r):
|
||||
|
||||
r['buffer'] = None
|
||||
r['buf_size'] = 0
|
||||
|
||||
result = fn(pipe, r)
|
||||
|
||||
if result['result'] == dcerpc.WERR_INSUFFICIENT_BUFFER or \
|
||||
result['result'] == dcerpc.WERR_MORE_DATA:
|
||||
r['buffer'] = result['buf_size'] * '\x00'
|
||||
r['buf_size'] = result['buf_size']
|
||||
|
||||
result = fn(pipe, r)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def test_OpenPrinterEx(pipe, printer):
|
||||
|
||||
print 'spoolss_OpenPrinterEx(%s)' % printer
|
||||
|
||||
printername = '\\\\%s' % dcerpc.dcerpc_server_name(pipe)
|
||||
|
||||
if printer is not None:
|
||||
printername = printername + '\\%s' % printer
|
||||
|
||||
r = {}
|
||||
r['printername'] = printername
|
||||
r['datatype'] = None
|
||||
r['devmode_ctr'] = {}
|
||||
r['devmode_ctr']['size'] = 0
|
||||
r['devmode_ctr']['devmode'] = None
|
||||
r['access_mask'] = 0x02000000
|
||||
r['level'] = 1
|
||||
r['userlevel'] = {}
|
||||
r['userlevel']['level1'] = {}
|
||||
r['userlevel']['level1']['size'] = 0
|
||||
r['userlevel']['level1']['client'] = None
|
||||
r['userlevel']['level1']['user'] = None
|
||||
r['userlevel']['level1']['build'] = 1381
|
||||
r['userlevel']['level1']['major'] = 2
|
||||
r['userlevel']['level1']['minor'] = 0
|
||||
r['userlevel']['level1']['processor'] = 0
|
||||
|
||||
result = dcerpc.spoolss_OpenPrinterEx(pipe, r)
|
||||
|
||||
return result['handle']
|
||||
|
||||
|
||||
def test_ClosePrinter(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
|
||||
dcerpc.spoolss_ClosePrinter(pipe, r)
|
||||
|
||||
|
||||
def test_GetPrinter(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
|
||||
for level in [0, 1, 2, 3, 4, 5, 6, 7]:
|
||||
|
||||
print 'spoolss_GetPrinter(level = %d)' % level
|
||||
|
||||
r['level'] = level
|
||||
r['buffer'] = None
|
||||
r['buf_size'] = 0
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_GetPrinter, pipe, r)
|
||||
|
||||
|
||||
def test_EnumForms(pipe, handle):
|
||||
|
||||
print 'spoolss_EnumForms()'
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['level'] = 1
|
||||
r['buffer'] = None
|
||||
r['buf_size'] = 0
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_EnumForms, pipe, r)
|
||||
|
||||
forms = dcerpc.unmarshall_spoolss_FormInfo_array(
|
||||
result['buffer'], r['level'], result['count'])
|
||||
|
||||
for form in forms:
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['formname'] = form['info1']['formname']
|
||||
r['level'] = 1
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_GetForm, pipe, r)
|
||||
|
||||
|
||||
def test_EnumPorts(pipe, handle):
|
||||
|
||||
print 'spoolss_EnumPorts()'
|
||||
|
||||
for level in [1, 2]:
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['servername'] = None
|
||||
r['level'] = level
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_EnumPorts, pipe, r)
|
||||
|
||||
ports = dcerpc.unmarshall_spoolss_PortInfo_array(
|
||||
result['buffer'], r['level'], result['count'])
|
||||
|
||||
if level == 1:
|
||||
port_names = map(lambda x: x['info1']['port_name'], ports)
|
||||
|
||||
|
||||
def test_DeleteForm(pipe, handle, formname):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['formname'] = formname
|
||||
|
||||
dcerpc.spoolss_DeleteForm(pipe, r)
|
||||
|
||||
|
||||
def test_GetForm(pipe, handle, formname):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['formname'] = formname
|
||||
r['level'] = 1
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_GetForm, pipe, r)
|
||||
|
||||
return result['info']['info1']
|
||||
|
||||
|
||||
def test_SetForm(pipe, handle, form):
|
||||
|
||||
print 'spoolss_SetForm()'
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['level'] = 1
|
||||
r['formname'] = form['info1']['formname']
|
||||
r['info'] = form
|
||||
|
||||
dcerpc.spoolss_SetForm(pipe, r)
|
||||
|
||||
newform = test_GetForm(pipe, handle, r['formname'])
|
||||
|
||||
if form['info1'] != newform:
|
||||
print 'SetForm: mismatch: %s != %s' % \
|
||||
(r['info']['info1'], f)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def test_AddForm(pipe, handle):
|
||||
|
||||
print 'spoolss_AddForm()'
|
||||
|
||||
formname = '__testform__'
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['level'] = 1
|
||||
r['info'] = {}
|
||||
r['info']['info1'] = {}
|
||||
r['info']['info1']['formname'] = formname
|
||||
r['info']['info1']['flags'] = 0x0002
|
||||
r['info']['info1']['width'] = 100
|
||||
r['info']['info1']['length'] = 100
|
||||
r['info']['info1']['left'] = 0
|
||||
r['info']['info1']['top'] = 1000
|
||||
r['info']['info1']['right'] = 2000
|
||||
r['info']['info1']['bottom'] = 3000
|
||||
|
||||
try:
|
||||
result = dcerpc.spoolss_AddForm(pipe, r)
|
||||
except dcerpc.WERROR, arg:
|
||||
if arg[0] == dcerpc.WERR_ALREADY_EXISTS:
|
||||
test_DeleteForm(pipe, handle, formname)
|
||||
result = dcerpc.spoolss_AddForm(pipe, r)
|
||||
|
||||
f = test_GetForm(pipe, handle, formname)
|
||||
|
||||
if r['info']['info1'] != f:
|
||||
print 'AddForm: mismatch: %s != %s' % \
|
||||
(r['info']['info1'], f)
|
||||
sys.exit(1)
|
||||
|
||||
r['formname'] = formname
|
||||
|
||||
test_SetForm(pipe, handle, r['info'])
|
||||
|
||||
test_DeleteForm(pipe, handle, formname)
|
||||
|
||||
|
||||
def test_EnumJobs(pipe, handle):
|
||||
|
||||
print 'spoolss_EnumJobs()'
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['firstjob'] = 0
|
||||
r['numjobs'] = 0xffffffff
|
||||
r['level'] = 1
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_EnumJobs, pipe, r)
|
||||
|
||||
if result['buffer'] is None:
|
||||
return
|
||||
|
||||
jobs = dcerpc.unmarshall_spoolss_JobInfo_array(
|
||||
result['buffer'], r['level'], result['count'])
|
||||
|
||||
for job in jobs:
|
||||
|
||||
s = {}
|
||||
s['handle'] = handle
|
||||
s['job_id'] = job['info1']['job_id']
|
||||
s['level'] = 1
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_GetJob, pipe, s)
|
||||
|
||||
if result['info'] != job:
|
||||
print 'EnumJobs: mismatch: %s != %s' % (result['info'], job)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# TODO: AddJob, DeleteJob, ScheduleJob
|
||||
|
||||
|
||||
def test_EnumPrinterData(pipe, handle):
|
||||
|
||||
print 'test_EnumPrinterData()'
|
||||
|
||||
enum_index = 0
|
||||
|
||||
while 1:
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['enum_index'] = enum_index
|
||||
|
||||
r['value_offered'] = 0
|
||||
r['data_size'] = 0
|
||||
|
||||
result = dcerpc.spoolss_EnumPrinterData(pipe, r)
|
||||
|
||||
r['value_offered'] = result['value_needed']
|
||||
r['data_size'] = result['data_size']
|
||||
|
||||
result = dcerpc.spoolss_EnumPrinterData(pipe, r)
|
||||
|
||||
if result['result'] == dcerpc.WERR_NO_MORE_ITEMS:
|
||||
break
|
||||
|
||||
s = {}
|
||||
s['handle'] = handle
|
||||
s['value_name'] = result['value_name']
|
||||
|
||||
result2 = ResizeBufferCall(dcerpc.spoolss_GetPrinterData, pipe, s)
|
||||
|
||||
if result['buffer'][:result2['buf_size']] != result2['buffer']:
|
||||
print 'EnumPrinterData/GetPrinterData mismatch'
|
||||
sys.exit(1)
|
||||
|
||||
enum_index += 1
|
||||
|
||||
|
||||
def test_SetPrinterDataEx(pipe, handle):
|
||||
|
||||
valuename = '__printerdataextest__'
|
||||
data = '12345'
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['key_name'] = 'DsSpooler'
|
||||
r['value_name'] = valuename
|
||||
r['type'] = 3
|
||||
r['buffer'] = data
|
||||
r['buf_size'] = len(data)
|
||||
|
||||
result = dcerpc.spoolss_SetPrinterDataEx(pipe, r)
|
||||
|
||||
|
||||
def test_EnumPrinterDataEx(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['key_name'] = 'DsSpooler'
|
||||
r['buf_size'] = 0
|
||||
|
||||
result = dcerpc.spoolss_EnumPrinterDataEx(pipe, r)
|
||||
|
||||
if result['result'] == dcerpc.WERR_MORE_DATA:
|
||||
r['buf_size'] = result['buf_size']
|
||||
|
||||
result = dcerpc.spoolss_EnumPrinterDataEx(pipe, r)
|
||||
|
||||
# TODO: test spoolss_GetPrinterDataEx()
|
||||
|
||||
|
||||
def test_SetPrinterData(pipe, handle):
|
||||
|
||||
print 'testing spoolss_SetPrinterData()'
|
||||
|
||||
valuename = '__printerdatatest__'
|
||||
data = '12345'
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['value_name'] = valuename
|
||||
r['type'] = 3 # REG_BINARY
|
||||
r['buffer'] = data
|
||||
r['real_len'] = 5
|
||||
|
||||
dcerpc.spoolss_SetPrinterData(pipe, r)
|
||||
|
||||
s = {}
|
||||
s['handle'] = handle
|
||||
s['value_name'] = valuename
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_GetPrinterData, pipe, r)
|
||||
|
||||
if result['buffer'] != data:
|
||||
print 'SetPrinterData: mismatch'
|
||||
sys.exit(1)
|
||||
|
||||
dcerpc.spoolss_DeletePrinterData(pipe, r)
|
||||
|
||||
|
||||
def test_EnumPrinters(pipe):
|
||||
|
||||
print 'testing spoolss_EnumPrinters()'
|
||||
|
||||
printer_names = None
|
||||
|
||||
r = {}
|
||||
r['flags'] = 0x02
|
||||
r['server'] = None
|
||||
|
||||
for level in [0, 1, 2, 4, 5]:
|
||||
|
||||
print 'test_EnumPrinters(level = %d)' % level
|
||||
|
||||
r['level'] = level
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_EnumPrinters, pipe, r)
|
||||
|
||||
printers = dcerpc.unmarshall_spoolss_PrinterInfo_array(
|
||||
result['buffer'], r['level'], result['count'])
|
||||
|
||||
if level == 2:
|
||||
for p in printers:
|
||||
|
||||
# A nice check is for the specversion in the
|
||||
# devicemode. This has always been observed to be
|
||||
# 1025.
|
||||
|
||||
if p['info2']['devmode']['specversion'] != 1025:
|
||||
print 'test_EnumPrinters: specversion != 1025'
|
||||
sys.exit(1)
|
||||
|
||||
r['level'] = 1
|
||||
result = ResizeBufferCall(dcerpc.spoolss_EnumPrinters, pipe, r)
|
||||
|
||||
for printer in dcerpc.unmarshall_spoolss_PrinterInfo_array(
|
||||
result['buffer'], r['level'], result['count']):
|
||||
|
||||
if string.find(printer['info1']['name'], '\\\\') == 0:
|
||||
print 'Skipping remote printer %s' % printer['info1']['name']
|
||||
continue
|
||||
|
||||
printername = string.split(printer['info1']['name'], ',')[0]
|
||||
|
||||
handle = test_OpenPrinterEx(pipe, printername)
|
||||
|
||||
test_GetPrinter(pipe, handle)
|
||||
test_EnumPorts(pipe, handle)
|
||||
test_EnumForms(pipe, handle)
|
||||
test_AddForm(pipe, handle)
|
||||
test_EnumJobs(pipe, handle)
|
||||
test_EnumPrinterData(pipe, handle)
|
||||
test_EnumPrinterDataEx(pipe, handle)
|
||||
test_SetPrinterData(pipe, handle)
|
||||
# test_SetPrinterDataEx(pipe, handle)
|
||||
test_ClosePrinter(pipe, handle)
|
||||
|
||||
|
||||
def test_EnumPrinterDrivers(pipe):
|
||||
|
||||
print 'test spoolss_EnumPrinterDrivers()'
|
||||
|
||||
for level in [1, 2, 3]:
|
||||
|
||||
r = {}
|
||||
r['server'] = None
|
||||
r['environment'] = None
|
||||
r['level'] = level
|
||||
|
||||
result = ResizeBufferCall(dcerpc.spoolss_EnumPrinterDrivers, pipe, r)
|
||||
|
||||
drivers = dcerpc.unmarshall_spoolss_DriverInfo_array(
|
||||
result['buffer'], r['level'], result['count'])
|
||||
|
||||
if level == 1:
|
||||
driver_names = map(lambda x: x['info1']['driver_name'], drivers)
|
||||
|
||||
|
||||
def test_PrintServer(pipe):
|
||||
|
||||
handle = test_OpenPrinterEx(pipe, None)
|
||||
|
||||
# EnumForms and AddForm tests return WERR_BADFID here (??)
|
||||
|
||||
test_ClosePrinter(pipe, handle)
|
||||
|
||||
|
||||
def runtests(binding, domain, username, password):
|
||||
|
||||
print 'Testing SPOOLSS pipe'
|
||||
|
||||
pipe = dcerpc.pipe_connect(binding,
|
||||
dcerpc.DCERPC_SPOOLSS_UUID, dcerpc.DCERPC_SPOOLSS_VERSION,
|
||||
domain, username, password)
|
||||
|
||||
test_EnumPrinters(pipe)
|
||||
test_EnumPrinterDrivers(pipe)
|
||||
test_PrintServer(pipe)
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# A torture test for the Python Ldb bindings. Also a short guide on
|
||||
# how the API works.
|
||||
#
|
||||
|
||||
from Ldb import *
|
||||
|
||||
# Helpers
|
||||
|
||||
def t(cond, msg):
|
||||
"""Test a condition."""
|
||||
if not cond:
|
||||
raise RuntimeError('FAILED: %s' % msg)
|
||||
|
||||
#
|
||||
# Torture LdbMessage
|
||||
#
|
||||
|
||||
m = LdbMessage()
|
||||
|
||||
# Empty message
|
||||
|
||||
t(m.keys() == [], 'empty msg')
|
||||
t(m.dn == None, 'empty dn')
|
||||
|
||||
t(m.sanity_check() == LDB_ERR_INVALID_DN_SYNTAX, 'sanity check')
|
||||
|
||||
# Test invalid dn
|
||||
|
||||
try:
|
||||
m.dn = 'invalid dn'
|
||||
except LdbError, arg:
|
||||
if arg[0] != LDB_ERR_INVALID_DN_SYNTAX:
|
||||
raise
|
||||
else:
|
||||
t(False, 'LdbError not raised')
|
||||
|
||||
# Test valid dn
|
||||
|
||||
m.dn = 'name=spotty'
|
||||
t(m.dn == 'name=spotty', 'specified dn')
|
||||
|
||||
t(m.sanity_check() == LDB_SUCCESS, 'sanity check')
|
||||
|
||||
# Test some single-valued attributes
|
||||
|
||||
m['animal'] = 'dog'
|
||||
m['name'] = 'spotty'
|
||||
|
||||
t(m.keys() == ['animal', 'name'], 'keys() test failed')
|
||||
t(m.values() == [['dog'], ['spotty']], 'values() test failed')
|
||||
t(m.items() == [('animal', ['dog']), ('name', ['spotty'])],
|
||||
'items() test failed')
|
||||
|
||||
t(m.sanity_check() == LDB_SUCCESS, 'sanity check')
|
||||
|
||||
m['animal'] = 'canine'
|
||||
t(m['animal'] == ['canine'], 'replace value failed')
|
||||
|
||||
# Test a multi-valued attribute
|
||||
|
||||
names = ['spotty', 'foot']
|
||||
m['name'] = names
|
||||
|
||||
t(m['name'] == names, 'multi-valued attr failed')
|
||||
|
||||
t(m.sanity_check() == LDB_SUCCESS, 'sanity check')
|
||||
|
||||
# Test non-string attributes
|
||||
|
||||
try:
|
||||
m['foo'] = 42
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
t(False, 'TypeError not raised')
|
||||
|
||||
#
|
||||
# Torture Ldb
|
||||
#
|
||||
|
||||
l = Ldb('foo.ldb')
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import dcerpc, samr
|
||||
|
||||
def test_Connect(pipe):
|
||||
|
||||
handle = samr.Connect(pipe)
|
||||
handle = samr.Connect2(pipe)
|
||||
handle = samr.Connect3(pipe)
|
||||
handle = samr.Connect4(pipe)
|
||||
|
||||
# WIN2K3 only?
|
||||
|
||||
try:
|
||||
handle = samr.Connect5(pipe)
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if arg[0] != 0xc00000d2L: # NT_STATUS_NET_WRITE_FAULT
|
||||
raise
|
||||
|
||||
return handle
|
||||
|
||||
def test_UserHandle(user_handle):
|
||||
|
||||
# QuerySecurity()/SetSecurity()
|
||||
|
||||
user_handle.SetSecurity(user_handle.QuerySecurity())
|
||||
|
||||
# GetUserPwInfo()
|
||||
|
||||
user_handle.GetUserPwInfo()
|
||||
|
||||
# GetUserInfo()
|
||||
|
||||
for level in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 20,
|
||||
21, 23, 24, 25, 26]:
|
||||
|
||||
try:
|
||||
user_handle.QueryUserInfo(level)
|
||||
user_handle.QueryUserInfo2(level)
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if arg[0] != 0xc0000003L: # NT_STATUS_INVALID_INFO_CLASS
|
||||
raise
|
||||
|
||||
# GetGroupsForUser()
|
||||
|
||||
user_handle.GetGroupsForUser()
|
||||
|
||||
# TestPrivateFunctionsUser()
|
||||
|
||||
try:
|
||||
user_handle.TestPrivateFunctionsUser()
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if arg[0] != 0xC0000002L:
|
||||
raise
|
||||
|
||||
def test_GroupHandle(group_handle):
|
||||
|
||||
# QuerySecurity()/SetSecurity()
|
||||
|
||||
group_handle.SetSecurity(group_handle.QuerySecurity())
|
||||
|
||||
# QueryGroupInfo()
|
||||
|
||||
for level in [1, 2, 3, 4, 5]:
|
||||
info = group_handle.QueryGroupInfo(level)
|
||||
|
||||
# TODO: SetGroupinfo()
|
||||
|
||||
# QueryGroupMember()
|
||||
|
||||
group_handle.QueryGroupMember()
|
||||
|
||||
def test_AliasHandle(alias_handle):
|
||||
|
||||
# QuerySecurity()/SetSecurity()
|
||||
|
||||
alias_handle.SetSecurity(alias_handle.QuerySecurity())
|
||||
|
||||
print alias_handle.GetMembersInAlias()
|
||||
|
||||
def test_DomainHandle(name, sid, domain_handle):
|
||||
|
||||
print 'testing %s (%s)' % (name, sid)
|
||||
|
||||
# QuerySecurity()/SetSecurity()
|
||||
|
||||
domain_handle.SetSecurity(domain_handle.QuerySecurity())
|
||||
|
||||
# LookupNames(), none mapped
|
||||
|
||||
try:
|
||||
domain_handle.LookupNames(['xxNONAMExx'])
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if arg[0] != 0xc0000073L:
|
||||
raise dcerpc.NTSTATUS(arg)
|
||||
|
||||
# LookupNames(), some mapped
|
||||
|
||||
if name != 'Builtin':
|
||||
domain_handle.LookupNames(['Administrator', 'xxNONAMExx'])
|
||||
|
||||
# QueryDomainInfo()/SetDomainInfo()
|
||||
|
||||
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]
|
||||
set_ok = [1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0]
|
||||
|
||||
for i in range(len(levels)):
|
||||
|
||||
info = domain_handle.QueryDomainInfo(level = levels[i])
|
||||
|
||||
try:
|
||||
domain_handle.SetDomainInfo(levels[i], info)
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if not (arg[0] == 0xc0000003L and not set_ok[i]):
|
||||
raise
|
||||
|
||||
# QueryDomainInfo2()
|
||||
|
||||
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]
|
||||
|
||||
for i in range(len(levels)):
|
||||
domain_handle.QueryDomainInfo2(level = levels[i])
|
||||
|
||||
# EnumDomainUsers
|
||||
|
||||
print 'testing users'
|
||||
|
||||
users = domain_handle.EnumDomainUsers()
|
||||
rids = domain_handle.LookupNames(users)
|
||||
|
||||
for i in range(len(users)):
|
||||
test_UserHandle(domain_handle.OpenUser(rids[0][i]))
|
||||
|
||||
# QueryDisplayInfo
|
||||
|
||||
for i in [1, 2, 3, 4, 5]:
|
||||
domain_handle.QueryDisplayInfo(level = i)
|
||||
domain_handle.QueryDisplayInfo2(level = i)
|
||||
domain_handle.QueryDisplayInfo3(level = i)
|
||||
|
||||
# EnumDomainGroups
|
||||
|
||||
print 'testing groups'
|
||||
|
||||
groups = domain_handle.EnumDomainGroups()
|
||||
rids = domain_handle.LookupNames(groups)
|
||||
|
||||
for i in range(len(groups)):
|
||||
test_GroupHandle(domain_handle.OpenGroup(rids[0][i]))
|
||||
|
||||
# EnumDomainAliases
|
||||
|
||||
print 'testing aliases'
|
||||
|
||||
aliases = domain_handle.EnumDomainAliases()
|
||||
rids = domain_handle.LookupNames(aliases)
|
||||
|
||||
for i in range(len(aliases)):
|
||||
test_AliasHandle(domain_handle.OpenAlias(rids[0][i]))
|
||||
|
||||
# CreateUser
|
||||
# CreateUser2
|
||||
# CreateDomAlias
|
||||
# RidToSid
|
||||
# RemoveMemberFromForeignDomain
|
||||
# CreateDomainGroup
|
||||
# GetAliasMembership
|
||||
|
||||
# GetBootKeyInformation()
|
||||
|
||||
try:
|
||||
domain_handle.GetBootKeyInformation()
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
pass
|
||||
|
||||
# TestPrivateFunctionsDomain()
|
||||
|
||||
try:
|
||||
domain_handle.TestPrivateFunctionsDomain()
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if arg[0] != 0xC0000002L:
|
||||
raise
|
||||
|
||||
def test_ConnectHandle(connect_handle):
|
||||
|
||||
print 'testing connect handle'
|
||||
|
||||
# QuerySecurity/SetSecurity
|
||||
|
||||
connect_handle.SetSecurity(connect_handle.QuerySecurity())
|
||||
|
||||
# Lookup bogus domain
|
||||
|
||||
try:
|
||||
connect_handle.LookupDomain('xxNODOMAINxx')
|
||||
except dcerpc.NTSTATUS, arg:
|
||||
if arg[0] != 0xC00000DFL: # NT_STATUS_NO_SUCH_DOMAIN
|
||||
raise
|
||||
|
||||
# Test all domains
|
||||
|
||||
for domain_name in connect_handle.EnumDomains():
|
||||
|
||||
connect_handle.GetDomPwInfo(domain_name)
|
||||
sid = connect_handle.LookupDomain(domain_name)
|
||||
domain_handle = connect_handle.OpenDomain(sid)
|
||||
|
||||
test_DomainHandle(domain_name, sid, domain_handle)
|
||||
|
||||
# TODO: Test Shutdown() function
|
||||
|
||||
def runtests(binding, creds):
|
||||
|
||||
print 'Testing SAMR pipe'
|
||||
|
||||
pipe = dcerpc.pipe_connect(binding,
|
||||
dcerpc.DCERPC_SAMR_UUID, int(dcerpc.DCERPC_SAMR_VERSION), creds)
|
||||
|
||||
handle = test_Connect(pipe)
|
||||
test_ConnectHandle(handle)
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys, os
|
||||
import Tdb
|
||||
|
||||
def fail(msg):
|
||||
print 'FAILED:', msg
|
||||
sys.exit(1)
|
||||
|
||||
tdb_file = '/tmp/torture_tdb.tdb'
|
||||
|
||||
# Create temporary tdb file
|
||||
|
||||
t = Tdb.Tdb(tdb_file, flags = Tdb.CLEAR_IF_FIRST)
|
||||
|
||||
# Check non-existent key throws KeyError exception
|
||||
|
||||
try:
|
||||
t['__none__']
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
fail('non-existent key did not throw KeyError')
|
||||
|
||||
# Check storing key
|
||||
|
||||
t['bar'] = '1234'
|
||||
if t['bar'] != '1234':
|
||||
fail('store key failed')
|
||||
|
||||
# Check key exists
|
||||
|
||||
if not t.has_key('bar'):
|
||||
fail('has_key() failed for existing key')
|
||||
|
||||
if t.has_key('__none__'):
|
||||
fail('has_key() succeeded for non-existent key')
|
||||
|
||||
# Delete key
|
||||
|
||||
try:
|
||||
del(t['__none__'])
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
fail('delete of non-existent key did not throw KeyError')
|
||||
|
||||
del t['bar']
|
||||
if t.has_key('bar'):
|
||||
fail('delete of existing key did not delete key')
|
||||
|
||||
# Clear all keys
|
||||
|
||||
t.clear()
|
||||
if len(t) != 0:
|
||||
fail('clear failed to remove all keys')
|
||||
|
||||
# Other dict functions
|
||||
|
||||
t['a'] = '1'
|
||||
t['ab'] = '12'
|
||||
t['abc'] = '123'
|
||||
|
||||
if len(t) != 3:
|
||||
fail('len method produced wrong value')
|
||||
|
||||
keys = t.keys()
|
||||
values = t.values()
|
||||
items = t.items()
|
||||
|
||||
if set(keys) != set(['a', 'ab', 'abc']):
|
||||
fail('keys method produced wrong values')
|
||||
|
||||
if set(values) != set(['1', '12', '123']):
|
||||
fail('values method produced wrong values')
|
||||
|
||||
if set(items) != set([('a', '1'), ('ab', '12'), ('abc', '123')]):
|
||||
fail('values method produced wrong values')
|
||||
|
||||
t.close()
|
||||
|
||||
# Re-open read-only
|
||||
|
||||
t = Tdb.Tdb(tdb_file, open_flags = os.O_RDONLY)
|
||||
t.keys()
|
||||
t.close()
|
||||
|
||||
# Clean up
|
||||
|
||||
os.unlink(tdb_file)
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys, dcerpc
|
||||
|
||||
def test_OpenHKLM(pipe):
|
||||
|
||||
r = {}
|
||||
r['unknown'] = {}
|
||||
r['unknown']['unknown0'] = 0x9038
|
||||
r['unknown']['unknown1'] = 0x0000
|
||||
r['access_required'] = 0x02000000
|
||||
|
||||
result = dcerpc.winreg_OpenHKLM(pipe, r)
|
||||
|
||||
return result['handle']
|
||||
|
||||
def test_QueryInfoKey(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['class'] = {}
|
||||
r['class']['name'] = None
|
||||
|
||||
return dcerpc.winreg_QueryInfoKey(pipe, r)
|
||||
|
||||
def test_CloseKey(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
|
||||
dcerpc.winreg_CloseKey(pipe, r)
|
||||
|
||||
def test_FlushKey(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
|
||||
dcerpc.winreg_FlushKey(pipe, r)
|
||||
|
||||
def test_GetVersion(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
|
||||
dcerpc.winreg_GetVersion(pipe, r)
|
||||
|
||||
def test_GetKeySecurity(pipe, handle):
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['unknown'] = 4
|
||||
r['size'] = None
|
||||
r['data'] = {}
|
||||
r['data']['max_len'] = 0
|
||||
r['data']['data'] = ''
|
||||
|
||||
result = dcerpc.winreg_GetKeySecurity(pipe, r)
|
||||
|
||||
print result
|
||||
|
||||
if result['result'] == dcerpc.WERR_INSUFFICIENT_BUFFER:
|
||||
r['size'] = {}
|
||||
r['size']['max_len'] = result['data']['max_len']
|
||||
r['size']['offset'] = 0
|
||||
r['size']['len'] = result['data']['max_len']
|
||||
|
||||
result = dcerpc.winreg_GetKeySecurity(pipe, r)
|
||||
|
||||
print result
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
def test_Key(pipe, handle, name, depth = 0):
|
||||
|
||||
# Don't descend too far. Registries can be very deep.
|
||||
|
||||
if depth > 2:
|
||||
return
|
||||
|
||||
try:
|
||||
keyinfo = test_QueryInfoKey(pipe, handle)
|
||||
except dcerpc.WERROR, arg:
|
||||
if arg[0] == dcerpc.WERR_ACCESS_DENIED:
|
||||
return
|
||||
|
||||
test_GetVersion(pipe, handle)
|
||||
|
||||
test_FlushKey(pipe, handle)
|
||||
|
||||
test_GetKeySecurity(pipe, handle)
|
||||
|
||||
# Enumerate values in this key
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['name_in'] = {}
|
||||
r['name_in']['len'] = 0
|
||||
r['name_in']['max_len'] = (keyinfo['max_valnamelen'] + 1) * 2
|
||||
r['name_in']['buffer'] = {}
|
||||
r['name_in']['buffer']['max_len'] = keyinfo['max_valnamelen'] + 1
|
||||
r['name_in']['buffer']['offset'] = 0
|
||||
r['name_in']['buffer']['len'] = 0
|
||||
r['type'] = 0
|
||||
r['value_in'] = {}
|
||||
r['value_in']['max_len'] = keyinfo['max_valbufsize']
|
||||
r['value_in']['offset'] = 0
|
||||
r['value_in']['len'] = 0
|
||||
r['value_len1'] = keyinfo['max_valbufsize']
|
||||
r['value_len2'] = 0
|
||||
|
||||
for i in range(0, keyinfo['num_values']):
|
||||
|
||||
r['enum_index'] = i
|
||||
|
||||
dcerpc.winreg_EnumValue(pipe, r)
|
||||
|
||||
# Recursively test subkeys of this key
|
||||
|
||||
r = {}
|
||||
r['handle'] = handle
|
||||
r['key_name_len'] = 0
|
||||
r['unknown'] = 0x0414
|
||||
r['in_name'] = {}
|
||||
r['in_name']['unknown'] = 0x20a
|
||||
r['in_name']['key_name'] = {}
|
||||
r['in_name']['key_name']['name'] = None
|
||||
r['class'] = {}
|
||||
r['class']['name'] = None
|
||||
r['last_changed_time'] = {}
|
||||
r['last_changed_time']['low'] = 0
|
||||
r['last_changed_time']['high'] = 0
|
||||
|
||||
for i in range(0, keyinfo['num_subkeys']):
|
||||
|
||||
r['enum_index'] = i
|
||||
|
||||
subkey = dcerpc.winreg_EnumKey(pipe, r)
|
||||
|
||||
s = {}
|
||||
s['handle'] = handle
|
||||
s['keyname'] = {}
|
||||
s['keyname']['name'] = subkey['out_name']['name']
|
||||
s['unknown'] = 0
|
||||
s['access_mask'] = 0x02000000
|
||||
|
||||
result = dcerpc.winreg_OpenKey(pipe, s)
|
||||
|
||||
test_Key(pipe, result['handle'], name + '/' + s['keyname']['name'],
|
||||
depth + 1)
|
||||
|
||||
test_CloseKey(pipe, result['handle'])
|
||||
|
||||
# Enumerate values
|
||||
|
||||
def runtests(binding, domain, username, password):
|
||||
|
||||
print 'Testing WINREG pipe'
|
||||
|
||||
pipe = dcerpc.pipe_connect(binding,
|
||||
dcerpc.DCERPC_WINREG_UUID, dcerpc.DCERPC_WINREG_VERSION,
|
||||
domain, username, password)
|
||||
|
||||
handle = test_OpenHKLM(pipe)
|
||||
|
||||
test_Key(pipe, handle, 'HKLM')
|
||||
Reference in New Issue
Block a user