Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-wsgi
[kai/samba.git] / source / scripting / ejs / smbcalls_ldb.c
index ea6f70a41ec95c7fdca3247ecf89a07e5c735825..4a157945af5cdf9184792e3187addc87e05b2454 100644 (file)
@@ -8,7 +8,7 @@
    
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
    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.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "lib/appweb/ejs/ejs.h"
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
-#include "db_wrap.h"
+#include "ldb_wrap.h"
+#include "dsdb/samdb/samdb.h"
+#include "librpc/ndr/libndr.h"
+#include "libcli/security/security.h"
 
 /*
   get the connected db
  */
 static struct ldb_context *ejs_get_ldb_context(int eid)
 {
-       struct ldb_context *ldb = mprGetThisPtr(eid, "db");
+       struct ldb_context *ldb = (struct ldb_context *)mprGetThisPtr(eid, "db");
        if (ldb == NULL) {
                ejsSetErrorMsg(eid, "invalid ldb connection");
        }
@@ -48,7 +50,8 @@ static struct ldb_context *ejs_get_ldb_context(int eid)
      var attrs = new Array("attr1", "attr2", "attr3");
      ldb.search("expression", attrs);
      var basedn = "cn=this,dc=is,dc=a,dc=test";
-     ldb.search("expression", attrs, ldb.SCOPE_SUBTREE, basedn);
+     ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs);
+     ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs, controls);
 */
 static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
 {
@@ -60,10 +63,12 @@ static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
        TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
        struct ldb_context *ldb;
        int ret;
-       struct ldb_result *res;
+       struct ldb_control **parsed_controls = NULL;
+       struct ldb_result *res=NULL;
+       struct ldb_request *req;
 
        /* validate arguments */
-       if (argc < 1 || argc > 4) {
+       if (argc < 1 || argc > 5) {
                ejsSetErrorMsg(eid, "ldb.search invalid number of arguments");
                goto failed;
        }
@@ -83,11 +88,13 @@ static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
                /* a null basedn is valid */
        }
        if (base != NULL) {
-               basedn = ldb_dn_explode(tmp_ctx, base);
-               if (basedn == NULL) {
+               basedn = ldb_dn_new(tmp_ctx, ldb, base);
+               if ( ! ldb_dn_validate(basedn)) {
                        ejsSetErrorMsg(eid, "ldb.search malformed base dn");
                        goto failed;
                }
+       } else {
+               basedn = ldb_get_default_basedn(ldb);
        }
        if (argc > 2) {
                scope = mprToInt(argv[2]);
@@ -105,12 +112,49 @@ static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
        if (argc > 3) {
                attrs = mprToList(tmp_ctx, argv[3]);
        }
-       ret = ldb_search(ldb, basedn, scope, expression, attrs, &res);
+       if (argc > 4) {
+               const char **controls;
+               controls = mprToList(tmp_ctx, argv[4]);
+               if (controls) {
+                       parsed_controls = ldb_parse_control_strings(ldb, tmp_ctx, controls);
+                       if (!parsed_controls) {
+                               ejsSetErrorMsg(eid, "ldb.search cannot parse controls: %s", 
+                                              ldb_errstring(ldb));
+                               goto failed;
+                       }
+               }
+       }
+
+       res = talloc_zero(tmp_ctx, struct ldb_result);
+       if (!res) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       ret = ldb_build_search_req(&req, ldb, tmp_ctx,
+                                  basedn,
+                                  scope,
+                                  expression,
+                                  attrs,
+                                  parsed_controls,
+                                  res,
+                                  ldb_search_default_callback);
+
+       if (ret == LDB_SUCCESS) {
+
+               ldb_set_timeout(ldb, req, 0); /* use default timeout */
+               
+               ret = ldb_request(ldb, req);
+               
+               if (ret == LDB_SUCCESS) {
+                       ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+               }
+       }
+
        if (ret != LDB_SUCCESS) {
                ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb));
-               mpr_Return(eid, mprCreateUndefinedVar());
+               mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
        } else {
-               mpr_Return(eid, mprLdbArray(ldb, res->msgs, res->count, "ldb_message"));
+               mpr_Return(eid, mprLdbResult(ldb, ret, res));
        }
 
        talloc_free(tmp_ctx);
@@ -161,7 +205,7 @@ static int ejs_ldbAddModify(MprVarHandle eid, int argc, struct MprVar **argv,
                return -1;
        }
 
-       mpr_Return(eid, mprCreateBoolVar(ret == 0));
+       mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
        return 0;
 }
 
@@ -187,8 +231,8 @@ static int ejs_ldbDelete(MprVarHandle eid, int argc, struct MprVar **argv)
                return -1;
        }
 
-       dn = ldb_dn_explode(ldb, mprToString(argv[0]));
-       if (dn == NULL) {
+       dn = ldb_dn_new(ldb, ldb, mprToString(argv[0]));
+       if ( ! ldb_dn_validate(dn)) {
                ejsSetErrorMsg(eid, "ldb.delete malformed dn");
                return -1;
        }
@@ -197,7 +241,7 @@ static int ejs_ldbDelete(MprVarHandle eid, int argc, struct MprVar **argv)
 
        talloc_free(dn);
 
-       mpr_Return(eid, mprCreateBoolVar(ret == 0));
+       mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
        return 0;
 }
 
@@ -222,9 +266,9 @@ static int ejs_ldbRename(MprVarHandle eid, int argc, struct MprVar **argv)
                return -1;
        }
 
-       dn1 = ldb_dn_explode(ldb, mprToString(argv[0]));
-       dn2 = ldb_dn_explode(ldb, mprToString(argv[1]));
-       if (dn1 == NULL || dn2 == NULL) {
+       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;
        }
@@ -234,7 +278,7 @@ static int ejs_ldbRename(MprVarHandle eid, int argc, struct MprVar **argv)
        talloc_free(dn1);
        talloc_free(dn2);
 
-       mpr_Return(eid, mprCreateBoolVar(ret == 0));
+       mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
        return 0;
 }
 
@@ -409,7 +453,7 @@ static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv)
 
        dbfile = argv[0];
 
-       ldb = ldb_wrap_connect(mprMemCtx(), dbfile, 
+       ldb = ldb_wrap_connect(mprMemCtx(), mprEventCtx(), mprLpCtx(), dbfile, 
                               session_info, creds,
                               0, (const char **)(argv+1));
        if (ldb == NULL) {
@@ -440,7 +484,7 @@ static int ejs_ldbClose(MprVarHandle eid, int argc, struct MprVar **argv)
        }
 
        mprSetThisPtr(eid, "db", NULL);
-       mpr_Return(eid, mprCreateBoolVar(True));
+       mpr_Return(eid, mprCreateBoolVar(true));
        return 0;
 }
 
@@ -523,6 +567,163 @@ static int ejs_ldbTransactionCommit(MprVarHandle eid, int argc, struct MprVar **
        return 0;
 }
 
+/*
+  commit a ldb attach a dsdb_schema from ldif files
+  usage:
+   ok = ldb.attach_dsdb_schema_from_ldif("prefixMap ldif content", "definition ldif content")
+*/
+static int ejs_ldb_attach_dsdb_schema_from_ldif(MprVarHandle eid, int argc, char **argv)
+{
+       struct ldb_context *ldb;
+       WERROR status;
+       const char *pf;
+       const char *df;
+
+       if (argc != 2) {
+               ejsSetErrorMsg(eid, "ldb.attach_dsdb_schema_from_ldif invalid arguments");
+               return -1;
+       }
+
+       ldb = ejs_get_ldb_context(eid);
+       if (ldb == NULL) {
+               return -1;
+       }
+
+       pf = argv[0];
+       df = argv[1];
+
+       status = dsdb_attach_schema_from_ldif_file(ldb, pf, df);
+
+       mpr_Return(eid, mprWERROR(status));
+       return 0;
+}
+
+/*
+  set a particular invocationId against the running LDB
+  usage:
+   ok = ldb.set_ntds_invocationId("7729aa4b-f990-41ad-b81a-8b6a14090f41");
+*/
+static int ejs_ldb_set_ntds_invocationId(MprVarHandle eid, int argc, char **argv)
+{
+       struct ldb_context *ldb;
+       NTSTATUS status;
+       struct GUID guid;
+       char *guid_str;
+       bool ok;
+
+       if (argc != 1) {
+               ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId invalid arguments");
+               return -1;
+       }
+
+       ldb = ejs_get_ldb_context(eid);
+       if (ldb == NULL) {
+               return -1;
+       }
+
+       guid_str = argv[0];
+
+       status = GUID_from_string(guid_str, &guid);
+       if (!NT_STATUS_IS_OK(status)) {
+               ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to parse GUID '%s' %s\n",
+                               guid_str, nt_errstr(status));
+               return -1;
+       }
+
+       ok = samdb_set_ntds_invocation_id(ldb, &guid);
+       if (!ok) {
+               ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to set cached ntds invocationId\n");
+               return -1;
+       }
+
+       mpr_Return(eid, mprCreateBoolVar(ok));
+       return 0;
+}
+
+/*
+  attach a particular ntds objectGUID against the current ldb
+  usage:
+   ok = ldb.set_ntds_objectGUID("7729aa4b-f990-41ad-b81a-8b6a14090f41");
+*/
+static int ejs_ldb_set_ntds_objectGUID(MprVarHandle eid, int argc, char **argv)
+{
+       struct ldb_context *ldb;
+       NTSTATUS status;
+       struct GUID guid;
+       char *guid_str;
+       bool ok;
+
+       if (argc != 1) {
+               ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID invalid arguments");
+               return -1;
+       }
+
+       ldb = ejs_get_ldb_context(eid);
+       if (ldb == NULL) {
+               return -1;
+       }
+
+       guid_str = argv[0];
+
+       status = GUID_from_string(guid_str, &guid);
+       if (!NT_STATUS_IS_OK(status)) {
+               ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to parse GUID '%s' %s\n",
+                               guid_str, nt_errstr(status));
+               return -1;
+       }
+
+       ok = samdb_set_ntds_invocation_id(ldb, &guid);
+       if (!ok) {
+               ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to set cached ntds invocationId\n");
+               return -1;
+       }
+
+       mpr_Return(eid, mprCreateBoolVar(ok));
+       return 0;
+}
+
+/*
+  attach a particular domain SID against the current ldb
+  usage:
+   ok = ldb.set_domain_sid("S-S-1-5-21-3065342217-3567412576-2214182334");
+*/
+static int ejs_ldb_set_domain_sid(MprVarHandle eid, int argc, char **argv)
+{
+       struct ldb_context *ldb;
+       struct dom_sid *dom_sid;
+       char *dom_sid_str;
+       bool ok;
+
+       if (argc != 1) {
+               ejsSetErrorMsg(eid, "ldb.set_domain_sid invalid arguments");
+               return -1;
+       }
+
+       ldb = ejs_get_ldb_context(eid);
+       if (ldb == NULL) {
+               return -1;
+       }
+
+       dom_sid_str = argv[0];
+
+       dom_sid = dom_sid_parse_talloc(NULL, dom_sid_str);
+       if (!dom_sid) {
+               ejsSetErrorMsg(eid, "ldb.set_domain_sid - failed to parse domain sid '%s'\n",
+                               dom_sid_str);
+               return -1;
+       }
+
+       ok = samdb_set_domain_sid(ldb, dom_sid);
+       talloc_free(dom_sid);
+       if (!ok) {
+               ejsSetErrorMsg(eid, "ldb.set_domain_sid - failed to set cached ntds invocationId\n");
+               return -1;
+       }
+
+       mpr_Return(eid, mprCreateBoolVar(ok));
+       return 0;
+}
+
 /*
   initialise ldb ejs subsystem
 */
@@ -544,6 +745,14 @@ static int ejs_ldb_init(MprVarHandle eid, int argc, struct MprVar **argv)
        mprSetCFunction(ldb, "transaction_start", ejs_ldbTransactionStart);
        mprSetCFunction(ldb, "transaction_cancel", ejs_ldbTransactionCancel);
        mprSetCFunction(ldb, "transaction_commit", ejs_ldbTransactionCommit);
+       mprSetStringCFunction(ldb, "attach_dsdb_schema_from_ldif",
+                             ejs_ldb_attach_dsdb_schema_from_ldif);
+       mprSetStringCFunction(ldb, "set_ntds_invocationId",
+                             ejs_ldb_set_ntds_invocationId);
+       mprSetStringCFunction(ldb, "set_ntds_objectGUID",
+                             ejs_ldb_set_ntds_objectGUID);
+       mprSetStringCFunction(ldb, "set_domain_sid",
+                             ejs_ldb_set_domain_sid);
        mprSetVar(ldb, "SCOPE_BASE", mprCreateNumberVar(LDB_SCOPE_BASE));
        mprSetVar(ldb, "SCOPE_ONE", mprCreateNumberVar(LDB_SCOPE_ONELEVEL));
        mprSetVar(ldb, "SCOPE_SUBTREE", mprCreateNumberVar(LDB_SCOPE_SUBTREE));