2 Unix SMB/CIFS implementation.
4 provide hooks into smbd C calls from ejs scripts
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Jelmer Vernooij 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "scripting/ejs/smbcalls.h"
25 #include "lib/appweb/ejs/ejs.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "lib/ldb/include/ldb_errors.h"
29 #include "dsdb/samdb/samdb.h"
30 #include "librpc/ndr/libndr.h"
35 static struct ldb_context *ejs_get_ldb_context(int eid)
37 struct ldb_context *ldb = mprGetThisPtr(eid, "db");
39 ejsSetErrorMsg(eid, "invalid ldb connection");
45 perform an ldb search, returning an array of results
48 res = ldb.search("expression");
49 var attrs = new Array("attr1", "attr2", "attr3");
50 ldb.search("expression", attrs);
51 var basedn = "cn=this,dc=is,dc=a,dc=test";
52 ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs);
53 ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs, controls);
55 static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
57 const char **attrs = NULL;
58 const char *expression;
59 const char *base = NULL;
60 struct ldb_dn *basedn = NULL;
61 int scope = LDB_SCOPE_DEFAULT;
62 TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
63 struct ldb_context *ldb;
65 struct ldb_control **parsed_controls = NULL;
66 struct ldb_result *res=NULL;
67 struct ldb_request *req;
69 /* validate arguments */
70 if (argc < 1 || argc > 5) {
71 ejsSetErrorMsg(eid, "ldb.search invalid number of arguments");
74 if (argc > 3 && argv[3]->type != MPR_TYPE_OBJECT) {
75 ejsSetErrorMsg(eid, "ldb.search attributes must be an object");
79 ldb = ejs_get_ldb_context(eid);
84 expression = mprToString(argv[0]);
86 base = mprToString(argv[1]);
87 /* a null basedn is valid */
90 basedn = ldb_dn_new(tmp_ctx, ldb, base);
91 if ( ! ldb_dn_validate(basedn)) {
92 ejsSetErrorMsg(eid, "ldb.search malformed base dn");
96 basedn = ldb_get_default_basedn(ldb);
99 scope = mprToInt(argv[2]);
101 case LDB_SCOPE_DEFAULT:
103 case LDB_SCOPE_ONELEVEL:
104 case LDB_SCOPE_SUBTREE:
107 ejsSetErrorMsg(eid, "ldb.search invalid scope");
112 attrs = mprToList(tmp_ctx, argv[3]);
115 const char **controls;
116 controls = mprToList(tmp_ctx, argv[4]);
118 parsed_controls = ldb_parse_control_strings(ldb, tmp_ctx, controls);
119 if (!parsed_controls) {
120 ejsSetErrorMsg(eid, "ldb.search cannot parse controls: %s",
127 res = talloc_zero(tmp_ctx, struct ldb_result);
129 return LDB_ERR_OPERATIONS_ERROR;
132 ret = ldb_build_search_req(&req, ldb, tmp_ctx,
139 ldb_search_default_callback);
141 if (ret == LDB_SUCCESS) {
143 ldb_set_timeout(ldb, req, 0); /* use default timeout */
145 ret = ldb_request(ldb, req);
147 if (ret == LDB_SUCCESS) {
148 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
152 if (ret != LDB_SUCCESS) {
153 ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb));
154 mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
156 mpr_Return(eid, mprLdbResult(ldb, ret, res));
159 talloc_free(tmp_ctx);
163 talloc_free(tmp_ctx);
169 perform an ldb add or modify
171 static int ejs_ldbAddModify(MprVarHandle eid, int argc, struct MprVar **argv,
172 int fn(struct ldb_context *, const struct ldb_message *))
174 const char *ldifstring;
175 struct ldb_context *ldb;
176 struct ldb_ldif *ldif;
177 int ret = 0, count=0;
180 ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments");
184 ldifstring = mprToString(argv[0]);
185 if (ldifstring == NULL) {
186 ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments");
190 ldb = ejs_get_ldb_context(eid);
195 while ((ldif = ldb_ldif_read_string(ldb, &ldifstring))) {
197 ret = fn(ldb, ldif->msg);
203 ejsSetErrorMsg(eid, "ldb.add/modify invalid ldif");
207 mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
213 perform an ldb delete
217 static int ejs_ldbDelete(MprVarHandle eid, int argc, struct MprVar **argv)
220 struct ldb_context *ldb;
224 ejsSetErrorMsg(eid, "ldb.delete invalid arguments");
228 ldb = ejs_get_ldb_context(eid);
233 dn = ldb_dn_new(ldb, ldb, mprToString(argv[0]));
234 if ( ! ldb_dn_validate(dn)) {
235 ejsSetErrorMsg(eid, "ldb.delete malformed dn");
239 ret = ldb_delete(ldb, dn);
243 mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
248 perform an ldb rename
250 ok = ldb.rename(dn1, dn2);
252 static int ejs_ldbRename(MprVarHandle eid, int argc, struct MprVar **argv)
254 struct ldb_dn *dn1, *dn2;
255 struct ldb_context *ldb;
259 ejsSetErrorMsg(eid, "ldb.rename invalid arguments");
263 ldb = ejs_get_ldb_context(eid);
268 dn1 = ldb_dn_new(ldb, ldb, mprToString(argv[0]));
269 dn2 = ldb_dn_new(ldb, ldb, mprToString(argv[1]));
270 if ( ! ldb_dn_validate(dn1) || ! ldb_dn_validate(dn2)) {
271 ejsSetErrorMsg(eid, "ldb.rename invalid or malformed arguments");
275 ret = ldb_rename(ldb, dn1, dn2);
280 mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
285 get last error message
287 ok = ldb.errstring();
289 static int ejs_ldbErrstring(MprVarHandle eid, int argc, struct MprVar **argv)
291 struct ldb_context *ldb;
293 ldb = ejs_get_ldb_context(eid);
298 mpr_Return(eid, mprString(ldb_errstring(ldb)));
305 dataout = ldb.encode(datain)
307 static int ejs_base64encode(MprVarHandle eid, int argc, struct MprVar **argv)
312 ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count");
316 if (argv[0]->type == MPR_TYPE_STRING) {
317 const char *orig = mprToString(argv[0]);
318 ret = ldb_base64_encode(mprMemCtx(), orig, strlen(orig));
322 blob = mprToDataBlob(argv[0]);
324 ret = ldb_base64_encode(mprMemCtx(), (char *)blob->data, blob->length);
328 mpr_Return(eid, mprCreateUndefinedVar());
330 mpr_Return(eid, mprString(ret));
341 dataout = ldb.decode(datain)
343 static int ejs_base64decode(MprVarHandle eid, int argc, struct MprVar **argv)
349 ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count");
353 tmp = talloc_strdup(mprMemCtx(), mprToString(argv[0]));
354 ret = ldb_base64_decode(tmp);
356 mpr_Return(eid, mprCreateUndefinedVar());
359 blob.data = (uint8_t *)tmp;
361 mpr_Return(eid, mprDataBlob(blob));
372 dataout = ldb.dn_escape(datain)
374 static int ejs_dn_escape(MprVarHandle eid, int argc, struct MprVar **argv)
380 ejsSetErrorMsg(eid, "ldb.dn_escape invalid argument count");
384 val = data_blob_string_const(mprToString(argv[0]));
386 ret = ldb_dn_escape_value(mprMemCtx(), val);
388 mpr_Return(eid, mprCreateUndefinedVar());
390 mpr_Return(eid, mprString(ret));
401 ok = ldb.add(ldifstring);
403 static int ejs_ldbAdd(MprVarHandle eid, int argc, struct MprVar **argv)
405 return ejs_ldbAddModify(eid, argc, argv, ldb_add);
409 perform an ldb modify
412 ok = ldb.modify(ldifstring);
414 static int ejs_ldbModify(MprVarHandle eid, int argc, struct MprVar **argv)
416 return ejs_ldbAddModify(eid, argc, argv, ldb_modify);
420 connect to a database
422 ok = ldb.connect(dbfile);
423 ok = ldb.connect(dbfile, "modules:modlist");
425 ldb.credentials or ldb.session_info may be setup first
428 static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv)
430 struct ldb_context *ldb;
431 struct auth_session_info *session_info = NULL;
432 struct cli_credentials *creds = NULL;
433 struct MprVar *credentials, *session;
434 struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
439 ejsSetErrorMsg(eid, "ldb.connect invalid arguments");
443 credentials = mprGetProperty(this, "credentials", NULL);
445 creds = talloc_get_type(mprGetPtr(credentials, "creds"), struct cli_credentials);
448 session = mprGetProperty(this, "session_info", NULL);
450 session_info = talloc_get_type(mprGetPtr(session, "session_info"), struct auth_session_info);
455 ldb = ldb_wrap_connect(mprMemCtx(), dbfile,
457 0, (const char **)(argv+1));
459 ejsSetErrorMsg(eid, "ldb.connect failed to open %s", dbfile);
462 mprSetThisPtr(eid, "db", ldb);
463 mpr_Return(eid, mprCreateBoolVar(ldb != NULL));
469 close a db connection
471 static int ejs_ldbClose(MprVarHandle eid, int argc, struct MprVar **argv)
473 struct ldb_context *ldb;
476 ejsSetErrorMsg(eid, "ldb.close invalid arguments");
480 ldb = ejs_get_ldb_context(eid);
485 mprSetThisPtr(eid, "db", NULL);
486 mpr_Return(eid, mprCreateBoolVar(True));
492 start a ldb transaction
494 ok = ldb.transaction_start();
496 static int ejs_ldbTransactionStart(MprVarHandle eid, int argc, struct MprVar **argv)
498 struct ldb_context *ldb;
502 ejsSetErrorMsg(eid, "ldb.transaction_start invalid arguments");
506 ldb = ejs_get_ldb_context(eid);
511 ret = ldb_transaction_start(ldb);
513 mpr_Return(eid, mprCreateBoolVar(ret == 0));
518 cancel a ldb transaction
520 ok = ldb.transaction_cancel();
522 static int ejs_ldbTransactionCancel(MprVarHandle eid, int argc, struct MprVar **argv)
524 struct ldb_context *ldb;
528 ejsSetErrorMsg(eid, "ldb.transaction_cancel invalid arguments");
532 ldb = ejs_get_ldb_context(eid);
537 ret = ldb_transaction_cancel(ldb);
539 mpr_Return(eid, mprCreateBoolVar(ret == 0));
544 commit a ldb transaction
546 ok = ldb.transaction_commit();
548 static int ejs_ldbTransactionCommit(MprVarHandle eid, int argc, struct MprVar **argv)
550 struct ldb_context *ldb;
554 ejsSetErrorMsg(eid, "ldb.transaction_commit invalid arguments");
558 ldb = ejs_get_ldb_context(eid);
563 ret = ldb_transaction_commit(ldb);
565 mpr_Return(eid, mprCreateBoolVar(ret == 0));
570 commit a ldb attach a dsdb_schema from ldif files
572 ok = ldb.attach_dsdb_schema_from_ldif("prefixMap ldif content", "definition ldif content")
574 static int ejs_ldb_attach_dsdb_schema_from_ldif(MprVarHandle eid, int argc, char **argv)
576 struct ldb_context *ldb;
584 ejsSetErrorMsg(eid, "ldb.attach_dsdb_schema_from_ldif invalid arguments");
588 ldb = ejs_get_ldb_context(eid);
596 status = dsdb_attach_schema_from_ldif_file(ldb, pf, df);
598 mpr_Return(eid, mprWERROR(status));
603 commit a ldb attach a dsdb_schema from ldif files
605 ok = ldb.set_ntds_invocationId("7729aa4b-f990-41ad-b81a-8b6a14090f41");
607 static int ejs_ldb_set_ntds_invocationId(MprVarHandle eid, int argc, char **argv)
609 struct ldb_context *ldb;
616 ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId invalid arguments");
620 ldb = ejs_get_ldb_context(eid);
627 status = GUID_from_string(guid_str, &guid);
628 if (!NT_STATUS_IS_OK(status)) {
629 ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to parse GUID '%s' %s\n",
630 guid_str, nt_errstr(status));
634 ok = samdb_set_ntds_invocation_id(ldb, &guid);
636 ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to set cached ntds invocationId\n");
640 mpr_Return(eid, mprCreateBoolVar(ok));
645 commit a ldb attach a dsdb_schema from ldif files
647 ok = ldb.get_ntds_objectGUID("7729aa4b-f990-41ad-b81a-8b6a14090f41");
649 static int ejs_ldb_set_ntds_objectGUID(MprVarHandle eid, int argc, char **argv)
651 struct ldb_context *ldb;
658 ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID invalid arguments");
662 ldb = ejs_get_ldb_context(eid);
669 status = GUID_from_string(guid_str, &guid);
670 if (!NT_STATUS_IS_OK(status)) {
671 ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to parse GUID '%s' %s\n",
672 guid_str, nt_errstr(status));
676 ok = samdb_set_ntds_invocation_id(ldb, &guid);
678 ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to set cached ntds invocationId\n");
682 mpr_Return(eid, mprCreateBoolVar(ok));
687 initialise ldb ejs subsystem
689 static int ejs_ldb_init(MprVarHandle eid, int argc, struct MprVar **argv)
691 struct MprVar *ldb = mprInitObject(eid, "ldb", argc, argv);
693 mprSetStringCFunction(ldb, "connect", ejs_ldbConnect);
694 mprSetCFunction(ldb, "search", ejs_ldbSearch);
695 mprSetCFunction(ldb, "add", ejs_ldbAdd);
696 mprSetCFunction(ldb, "modify", ejs_ldbModify);
697 mprSetCFunction(ldb, "del", ejs_ldbDelete);
698 mprSetCFunction(ldb, "rename", ejs_ldbRename);
699 mprSetCFunction(ldb, "errstring", ejs_ldbErrstring);
700 mprSetCFunction(ldb, "encode", ejs_base64encode);
701 mprSetCFunction(ldb, "decode", ejs_base64decode);
702 mprSetCFunction(ldb, "dn_escape", ejs_dn_escape);
703 mprSetCFunction(ldb, "close", ejs_ldbClose);
704 mprSetCFunction(ldb, "transaction_start", ejs_ldbTransactionStart);
705 mprSetCFunction(ldb, "transaction_cancel", ejs_ldbTransactionCancel);
706 mprSetCFunction(ldb, "transaction_commit", ejs_ldbTransactionCommit);
707 mprSetStringCFunction(ldb, "attach_dsdb_schema_from_ldif",
708 ejs_ldb_attach_dsdb_schema_from_ldif);
709 mprSetStringCFunction(ldb, "set_ntds_invocationId",
710 ejs_ldb_set_ntds_invocationId);
711 mprSetStringCFunction(ldb, "set_ntds_objectGUID",
712 ejs_ldb_set_ntds_objectGUID);
713 mprSetVar(ldb, "SCOPE_BASE", mprCreateNumberVar(LDB_SCOPE_BASE));
714 mprSetVar(ldb, "SCOPE_ONE", mprCreateNumberVar(LDB_SCOPE_ONELEVEL));
715 mprSetVar(ldb, "SCOPE_SUBTREE", mprCreateNumberVar(LDB_SCOPE_SUBTREE));
716 mprSetVar(ldb, "SCOPE_DEFAULT", mprCreateNumberVar(LDB_SCOPE_DEFAULT));
723 setup C functions that be called from ejs
725 NTSTATUS smb_setup_ejs_ldb(void)
727 ejsDefineCFunction(-1, "ldb_init", ejs_ldb_init, NULL, MPR_VAR_SCRIPT_HANDLE);